diff --git a/README.md b/README.md
index da9e3556b4ca..6d6383351caf 100644
--- a/README.md
+++ b/README.md
@@ -15,6 +15,7 @@ If you wish to _contribute_ to the compiler, you should read
Table of Contents
- [Quick Start](#quick-start)
+- [Installing from Source](#installing-from-source)
- [Getting Help](#getting-help)
- [Contributing](#contributing)
- [License](#license)
@@ -29,9 +30,10 @@ Read ["Installation"] from [The Book].
["Installation"]: https://doc.rust-lang.org/book/ch01-01-installation.html
[The Book]: https://doc.rust-lang.org/book/index.html
-## Installing from source
+## Installing from Source
-If you really want to install from source (though this is not recommended), see [INSTALL.md](INSTALL.md).
+If you really want to install from source (though this is not recommended), see
+[INSTALL.md](INSTALL.md).
## Getting Help
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 621516af9c05..90ddeec4bc7a 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -484,6 +484,19 @@ impl DroplessArena {
}
}
+ /// Used by `Lift` to check whether this slice is allocated
+ /// in this arena.
+ #[inline]
+ pub fn contains_slice(&self, slice: &[T]) -> bool {
+ for chunk in self.chunks.borrow_mut().iter_mut() {
+ let ptr = slice.as_ptr().cast::().cast_mut();
+ if chunk.start() <= ptr && chunk.end() >= ptr {
+ return true;
+ }
+ }
+ false
+ }
+
/// Allocates a string slice that is copied into the `DroplessArena`, returning a
/// reference to it. Will panic if passed an empty string.
///
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 7f5213431f7d..4eb8169d0c37 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -27,6 +27,7 @@ pub use UnsafeSource::*;
use crate::ptr::P;
use crate::token::{self, CommentKind, Delimiter};
use crate::tokenstream::{DelimSpan, LazyAttrTokenStream, TokenStream};
+use rustc_data_structures::packed::Pu128;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::stack::ensure_sufficient_stack;
use rustc_data_structures::sync::Lrc;
@@ -1833,7 +1834,7 @@ pub enum LitKind {
/// A character literal (`'a'`).
Char(char),
/// An integer literal (`1`).
- Int(u128, LitIntType),
+ Int(Pu128, LitIntType),
/// A float literal (`1.0`, `1f64` or `1E10f64`). The pre-suffix part is
/// stored as a symbol rather than `f64` so that `LitKind` can impl `Eq`
/// and `Hash`.
@@ -3304,13 +3305,9 @@ mod size_asserts {
static_assert_size!(Impl, 136);
static_assert_size!(Item, 136);
static_assert_size!(ItemKind, 64);
- // This can be removed after i128:128 is in the bootstrap compiler's target.
- #[cfg(not(bootstrap))]
- static_assert_size!(LitKind, 32);
+ static_assert_size!(LitKind, 24);
static_assert_size!(Local, 72);
- // This can be removed after i128:128 is in the bootstrap compiler's target.
- #[cfg(not(bootstrap))]
- static_assert_size!(MetaItemLit, 48);
+ static_assert_size!(MetaItemLit, 40);
static_assert_size!(Param, 40);
static_assert_size!(Pat, 72);
static_assert_size!(Path, 24);
diff --git a/compiler/rustc_ast/src/util/literal.rs b/compiler/rustc_ast/src/util/literal.rs
index fbae49645881..7b781ba1e112 100644
--- a/compiler/rustc_ast/src/util/literal.rs
+++ b/compiler/rustc_ast/src/util/literal.rs
@@ -366,7 +366,7 @@ fn integer_lit(symbol: Symbol, suffix: Option) -> Result LoweringContext<'_, 'hir> {
pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
let lit = self.arena.alloc(hir::Lit {
span: sp,
- node: ast::LitKind::Int(value as u128, ast::LitIntType::Unsigned(ast::UintTy::Usize)),
+ node: ast::LitKind::Int(
+ (value as u128).into(),
+ ast::LitIntType::Unsigned(ast::UintTy::Usize),
+ ),
});
self.expr(sp, hir::ExprKind::Lit(lit))
}
@@ -1907,7 +1910,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
let lit = self.arena.alloc(hir::Lit {
span: sp,
- node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ast::UintTy::U32)),
+ node: ast::LitKind::Int(
+ u128::from(value).into(),
+ ast::LitIntType::Unsigned(ast::UintTy::U32),
+ ),
});
self.expr(sp, hir::ExprKind::Lit(lit))
}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 192e458775a9..82236d2e3067 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -398,7 +398,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
&self,
exclusive_range_pattern,
pattern.span,
- "exclusive range pattern syntax is experimental"
+ "exclusive range pattern syntax is experimental",
+ "use an inclusive range pattern, like N..=M"
);
}
_ => {}
diff --git a/compiler/rustc_attr/src/builtin.rs b/compiler/rustc_attr/src/builtin.rs
index 6b903be6e5ee..a3783db5f80d 100644
--- a/compiler/rustc_attr/src/builtin.rs
+++ b/compiler/rustc_attr/src/builtin.rs
@@ -1185,9 +1185,9 @@ fn allow_unstable<'a>(
pub fn parse_alignment(node: &ast::LitKind) -> Result {
if let ast::LitKind::Int(literal, ast::LitIntType::Unsuffixed) = node {
- if literal.is_power_of_two() {
+ if literal.get().is_power_of_two() {
// rustc_middle::ty::layout::Align restricts align to <= 2^29
- if *literal <= 1 << 29 { Ok(*literal as u32) } else { Err("larger than 2^29") }
+ if *literal <= 1 << 29 { Ok(literal.get() as u32) } else { Err("larger than 2^29") }
} else {
Err("not a power of two")
}
diff --git a/compiler/rustc_attr/src/session_diagnostics.rs b/compiler/rustc_attr/src/session_diagnostics.rs
index 89606b81a994..315a00c8d2fc 100644
--- a/compiler/rustc_attr/src/session_diagnostics.rs
+++ b/compiler/rustc_attr/src/session_diagnostics.rs
@@ -296,7 +296,7 @@ impl<'a> IncorrectReprFormatGenericCause<'a> {
pub fn from_lit_kind(span: Span, kind: &ast::LitKind, name: &'a str) -> Option {
match kind {
ast::LitKind::Int(int, ast::LitIntType::Unsuffixed) => {
- Some(Self::Int { span, name, int: *int })
+ Some(Self::Int { span, name, int: int.get() })
}
ast::LitKind::Str(symbol, _) => Some(Self::Symbol { span, name, symbol: *symbol }),
_ => None,
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index b304fb5589f3..177fc1deca12 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -415,7 +415,7 @@ fn do_mir_borrowck<'tcx>(
let mut_span = tcx.sess.source_map().span_until_non_whitespace(span);
- tcx.emit_spanned_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
+ tcx.emit_node_span_lint(UNUSED_MUT, lint_root, span, VarNeedNotMut { span: mut_span })
}
let tainted_by_errors = mbcx.emit_errors();
diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs
index 4f7c0266343c..a01bbeac8249 100644
--- a/compiler/rustc_builtin_macros/src/concat_bytes.rs
+++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs
@@ -54,7 +54,7 @@ fn invalid_type_err(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
)) => {
- assert!(val > u8::MAX.into()); // must be an error
+ assert!(val.get() > u8::MAX.into()); // must be an error
dcx.emit_err(ConcatBytesOob { span });
}
Ok(ast::LitKind::Int(_, _)) => {
@@ -86,7 +86,7 @@ fn handle_array_element(
Ok(ast::LitKind::Int(
val,
ast::LitIntType::Unsuffixed | ast::LitIntType::Unsigned(ast::UintTy::U8),
- )) if val <= u8::MAX.into() => Some(val as u8),
+ )) if val.get() <= u8::MAX.into() => Some(val.get() as u8),
Ok(ast::LitKind::Byte(val)) => Some(val),
Ok(ast::LitKind::ByteStr(..)) => {
@@ -148,7 +148,7 @@ pub fn expand_concat_bytes(
if let Some(elem) =
handle_array_element(cx, &mut has_errors, &mut missing_literals, expr)
{
- for _ in 0..count_val {
+ for _ in 0..count_val.get() {
accumulator.push(elem);
}
}
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 93381b69fdcc..eb331ef58530 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -529,7 +529,7 @@ fn make_format_args(
// Only check for unused named argument names if there are no other errors to avoid causing
// too much noise in output errors, such as when a named argument is entirely unused.
- if invalid_refs.is_empty() && ecx.dcx().err_count() == 0 {
+ if invalid_refs.is_empty() && ecx.dcx().has_errors().is_none() {
for &(index, span, used_as) in &numeric_refences_to_named_arg {
let (position_sp_to_replace, position_sp_for_msg) = match used_as {
Placeholder(pspan) => (span, pspan),
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index 5881c6236ece..a80f6a1add09 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -325,7 +325,7 @@ codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
-codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#cargorustc-link-libkindname)
+codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)
codegen_ssa_version_script_write_failure = failed to write version script: {$error}
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 198b7ac41707..cca239a43b34 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -563,7 +563,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
if codegen_fn_attrs.inline == InlineAttr::Always {
if let (Some(no_sanitize_span), Some(inline_span)) = (no_sanitize_span, inline_span) {
let hir_id = tcx.local_def_id_to_hir_id(did);
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
lint::builtin::INLINE_NO_SANITIZE,
hir_id,
no_sanitize_span,
@@ -658,7 +658,7 @@ fn check_link_ordinal(tcx: TyCtxt<'_>, attr: &ast::Attribute) -> Option {
// if the resulting EXE runs, as I haven't yet built the necessary DLL -- see earlier comment
// about LINK.EXE failing.)
if *ordinal <= u16::MAX as u128 {
- Some(*ordinal as u16)
+ Some(ordinal.get() as u16)
} else {
let msg = format!("ordinal value in `link_ordinal` is too large: `{}`", &ordinal);
tcx.dcx()
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index ef39d13d78ab..e8d0430c9d95 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -175,7 +175,7 @@ pub(super) fn lint<'tcx, 'mir, L>(
{
let (span, frames) = get_span_and_frames(tcx, machine);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint,
// We use the root frame for this so the crate that defines the const defines whether the
// lint is emitted.
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 6947ace17c5e..f2e8821d6b65 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -611,7 +611,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
.0
.is_error();
let span = ecx.cur_span();
- ecx.tcx.emit_spanned_lint(
+ ecx.tcx.emit_node_span_lint(
rustc_session::lint::builtin::LONG_RUNNING_CONST_EVAL,
hir_id,
span,
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 9c2f336e9128..5564902396ed 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -796,7 +796,67 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
};
}
match rvalue {
- Rvalue::Use(_) | Rvalue::CopyForDeref(_) | Rvalue::Aggregate(..) => {}
+ Rvalue::Use(_) | Rvalue::CopyForDeref(_) => {}
+ Rvalue::Aggregate(kind, fields) => match **kind {
+ AggregateKind::Tuple => {}
+ AggregateKind::Array(dest) => {
+ for src in fields {
+ if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
+ self.fail(location, "array field has the wrong type");
+ }
+ }
+ }
+ AggregateKind::Adt(def_id, idx, args, _, Some(field)) => {
+ let adt_def = self.tcx.adt_def(def_id);
+ assert!(adt_def.is_union());
+ assert_eq!(idx, FIRST_VARIANT);
+ let dest = adt_def.non_enum_variant().fields[field].ty(self.tcx, args);
+ if fields.len() != 1 {
+ self.fail(location, "unions should have one initialized field");
+ }
+ if !self.mir_assign_valid_types(fields.raw[0].ty(self.body, self.tcx), dest) {
+ self.fail(location, "union field has the wrong type");
+ }
+ }
+ AggregateKind::Adt(def_id, idx, args, _, None) => {
+ let adt_def = self.tcx.adt_def(def_id);
+ assert!(!adt_def.is_union());
+ let variant = &adt_def.variants()[idx];
+ if variant.fields.len() != fields.len() {
+ self.fail(location, "adt has the wrong number of initialized fields");
+ }
+ for (src, dest) in std::iter::zip(fields, &variant.fields) {
+ if !self.mir_assign_valid_types(
+ src.ty(self.body, self.tcx),
+ dest.ty(self.tcx, args),
+ ) {
+ self.fail(location, "adt field has the wrong type");
+ }
+ }
+ }
+ AggregateKind::Closure(_, args) => {
+ let upvars = args.as_closure().upvar_tys();
+ if upvars.len() != fields.len() {
+ self.fail(location, "closure has the wrong number of initialized fields");
+ }
+ for (src, dest) in std::iter::zip(fields, upvars) {
+ if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
+ self.fail(location, "closure field has the wrong type");
+ }
+ }
+ }
+ AggregateKind::Coroutine(_, args) => {
+ let upvars = args.as_coroutine().upvar_tys();
+ if upvars.len() != fields.len() {
+ self.fail(location, "coroutine has the wrong number of initialized fields");
+ }
+ for (src, dest) in std::iter::zip(fields, upvars) {
+ if !self.mir_assign_valid_types(src.ty(self.body, self.tcx), dest) {
+ self.fail(location, "coroutine field has the wrong type");
+ }
+ }
+ }
+ },
Rvalue::Ref(_, BorrowKind::Fake, _) => {
if self.mir_phase >= MirPhase::Runtime(RuntimePhase::Initial) {
self.fail(
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 93b4032c3108..077e90350a3c 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -93,6 +93,7 @@ pub mod aligned;
pub mod frozen;
mod hashes;
pub mod owned_slice;
+pub mod packed;
pub mod sso;
pub mod steal;
pub mod tagged_ptr;
diff --git a/compiler/rustc_data_structures/src/packed.rs b/compiler/rustc_data_structures/src/packed.rs
new file mode 100644
index 000000000000..b8d4b295dfa1
--- /dev/null
+++ b/compiler/rustc_data_structures/src/packed.rs
@@ -0,0 +1,71 @@
+use crate::stable_hasher::{HashStable, StableHasher};
+use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
+use std::cmp::Ordering;
+use std::fmt;
+
+#[repr(packed(8))]
+#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
+pub struct Pu128(pub u128);
+
+impl Pu128 {
+ #[inline]
+ pub fn get(self) -> u128 {
+ self.0
+ }
+}
+
+impl From for Pu128 {
+ #[inline]
+ fn from(value: u128) -> Self {
+ Self(value)
+ }
+}
+
+impl PartialEq for Pu128 {
+ #[inline]
+ fn eq(&self, other: &u128) -> bool {
+ ({ self.0 }) == *other
+ }
+}
+
+impl PartialOrd for Pu128 {
+ #[inline]
+ fn partial_cmp(&self, other: &u128) -> Option {
+ { self.0 }.partial_cmp(other)
+ }
+}
+
+impl fmt::Display for Pu128 {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ { self.0 }.fmt(f)
+ }
+}
+
+impl fmt::UpperHex for Pu128 {
+ #[inline]
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ { self.0 }.fmt(f)
+ }
+}
+
+impl HashStable for Pu128 {
+ #[inline]
+ fn hash_stable(&self, ctx: &mut CTX, hasher: &mut StableHasher) {
+ { self.0 }.hash_stable(ctx, hasher)
+ }
+}
+
+impl Encodable for Pu128 {
+ #[inline]
+ fn encode(&self, s: &mut S) {
+ { self.0 }.encode(s);
+ }
+}
+
+impl Decodable for Pu128 {
+ #[inline]
+ fn decode(d: &mut D) -> Self {
+ Self(u128::decode(d))
+ }
+}
diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs
index 39252dea2830..f6679ae9bb35 100644
--- a/compiler/rustc_errors/src/diagnostic_impls.rs
+++ b/compiler/rustc_errors/src/diagnostic_impls.rs
@@ -110,6 +110,14 @@ impl IntoDiagnosticArg for char {
}
}
+impl IntoDiagnosticArg for Vec {
+ fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
+ DiagnosticArgValue::StrListSepByAnd(
+ self.into_iter().map(|c| Cow::Owned(format!("{c:?}"))).collect(),
+ )
+ }
+}
+
impl IntoDiagnosticArg for Symbol {
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
self.to_ident_string().into_diagnostic_arg()
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 141547b537de..9d80c4565172 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -421,16 +421,16 @@ pub struct DiagCtxt {
struct DiagCtxtInner {
flags: DiagCtxtFlags,
- /// The number of lint errors that have been emitted.
+ /// The number of lint errors that have been emitted, including duplicates.
lint_err_count: usize,
- /// The number of errors that have been emitted, including duplicates.
- ///
- /// This is not necessarily the count that's reported to the user once
- /// compilation ends.
+ /// The number of non-lint errors that have been emitted, including duplicates.
err_count: usize,
+
+ /// The error count shown to the user at the end.
deduplicated_err_count: usize,
- /// The warning count, used for a recap upon finishing
+ /// The warning count shown to the user at the end.
deduplicated_warn_count: usize,
+
/// Has this diagnostic context printed any diagnostics? (I.e. has
/// `self.emitter.emit_diagnostic()` been called?
has_printed: bool,
@@ -927,11 +927,13 @@ impl DiagCtxt {
self.struct_bug(msg).emit()
}
+ /// This excludes lint errors and delayed bugs.
#[inline]
pub fn err_count(&self) -> usize {
self.inner.borrow().err_count
}
+ /// This excludes lint errors and delayed bugs.
pub fn has_errors(&self) -> Option {
self.inner.borrow().has_errors().then(|| {
#[allow(deprecated)]
@@ -939,30 +941,24 @@ impl DiagCtxt {
})
}
+ /// This excludes delayed bugs. Unless absolutely necessary, prefer
+ /// `has_errors` to this method.
pub fn has_errors_or_lint_errors(&self) -> Option {
let inner = self.inner.borrow();
- let has_errors_or_lint_errors = inner.has_errors() || inner.lint_err_count > 0;
- has_errors_or_lint_errors.then(|| {
+ let result = inner.has_errors() || inner.lint_err_count > 0;
+ result.then(|| {
#[allow(deprecated)]
ErrorGuaranteed::unchecked_claim_error_was_emitted()
})
}
- pub fn has_errors_or_span_delayed_bugs(&self) -> Option {
+ /// Unless absolutely necessary, prefer `has_errors` or
+ /// `has_errors_or_lint_errors` to this method.
+ pub fn has_errors_or_lint_errors_or_delayed_bugs(&self) -> Option {
let inner = self.inner.borrow();
- let has_errors_or_span_delayed_bugs =
- inner.has_errors() || !inner.span_delayed_bugs.is_empty();
- has_errors_or_span_delayed_bugs.then(|| {
- #[allow(deprecated)]
- ErrorGuaranteed::unchecked_claim_error_was_emitted()
- })
- }
-
- pub fn is_compilation_going_to_fail(&self) -> Option {
- let inner = self.inner.borrow();
- let will_fail =
+ let result =
inner.has_errors() || inner.lint_err_count > 0 || !inner.span_delayed_bugs.is_empty();
- will_fail.then(|| {
+ result.then(|| {
#[allow(deprecated)]
ErrorGuaranteed::unchecked_claim_error_was_emitted()
})
@@ -1162,7 +1158,7 @@ impl DiagCtxt {
let mut inner = self.inner.borrow_mut();
if loud && lint_level.is_error() {
- inner.err_count += 1;
+ inner.lint_err_count += 1;
inner.panic_if_treat_err_as_bug();
}
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index e3dc73d0d851..3ca0787ce8e1 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -124,7 +124,7 @@ fn parse_depth<'sess>(
};
if let Ok(lit_kind) = LitKind::from_token_lit(*lit)
&& let LitKind::Int(n_u128, LitIntType::Unsuffixed) = lit_kind
- && let Ok(n_usize) = usize::try_from(n_u128)
+ && let Ok(n_usize) = usize::try_from(n_u128.get())
{
Ok(n_usize)
} else {
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 6e3996b45099..1155366db85e 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -339,9 +339,6 @@ declare_features! (
/// Allows `#[track_caller]` to be used which provides
/// accurate caller location reporting during panic (RFC 2091).
(accepted, track_caller, "1.46.0", Some(47809)),
- /// Allows dyn upcasting trait objects via supertraits.
- /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
- (accepted, trait_upcasting, "1.76.0", Some(65991)),
/// Allows #[repr(transparent)] on univariant enums (RFC 2645).
(accepted, transparent_enums, "1.42.0", Some(60405)),
/// Allows indexing tuples.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 371b651f5e85..6eed2178ead8 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -584,6 +584,9 @@ declare_features! (
(unstable, thread_local, "1.0.0", Some(29594)),
/// Allows defining `trait X = A + B;` alias items.
(unstable, trait_alias, "1.24.0", Some(41517)),
+ /// Allows dyn upcasting trait objects via supertraits.
+ /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
+ (unstable, trait_upcasting, "1.56.0", Some(65991)),
/// Allows for transmuting between arrays with sizes that contain generic consts.
(unstable, transmute_generic_consts, "1.70.0", Some(109929)),
/// Allows #[repr(transparent)] on unions (RFC 2645).
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index 1cc1f11b3c85..85d10872b3d1 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -213,8 +213,11 @@ language_item_table! {
Iterator, sym::iterator, iterator_trait, Target::Trait, GenericRequirement::Exact(0);
Future, sym::future_trait, future_trait, Target::Trait, GenericRequirement::Exact(0);
AsyncIterator, sym::async_iterator, async_iterator_trait, Target::Trait, GenericRequirement::Exact(0);
+
CoroutineState, sym::coroutine_state, coroutine_state, Target::Enum, GenericRequirement::None;
Coroutine, sym::coroutine, coroutine_trait, Target::Trait, GenericRequirement::Minimum(1);
+ CoroutineResume, sym::coroutine_resume, coroutine_resume, Target::Method(MethodKind::Trait { body: false }), GenericRequirement::None;
+
Unpin, sym::unpin, unpin_trait, Target::Trait, GenericRequirement::None;
Pin, sym::pin, pin_type, Target::Struct, GenericRequirement::None;
diff --git a/compiler/rustc_hir_analysis/src/astconv/bounds.rs b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
index 401efff9242e..3aad510f3660 100644
--- a/compiler/rustc_hir_analysis/src/astconv/bounds.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/bounds.rs
@@ -329,7 +329,7 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
}
let projection_ty = if let ty::AssocKind::Fn = assoc_kind {
- let mut emitted_bad_param_err = false;
+ let mut emitted_bad_param_err = None;
// If we have an method return type bound, then we need to substitute
// the method's early bound params with suitable late-bound params.
let mut num_bound_vars = candidate.bound_vars().len();
@@ -346,46 +346,30 @@ impl<'tcx> dyn AstConv<'tcx> + '_ {
)
.into(),
ty::GenericParamDefKind::Type { .. } => {
- if !emitted_bad_param_err {
+ let guar = *emitted_bad_param_err.get_or_insert_with(|| {
tcx.dcx().emit_err(
crate::errors::ReturnTypeNotationIllegalParam::Type {
span: path_span,
param_span: tcx.def_span(param.def_id),
},
- );
- emitted_bad_param_err = true;
- }
- Ty::new_bound(
- tcx,
- ty::INNERMOST,
- ty::BoundTy {
- var: ty::BoundVar::from_usize(num_bound_vars),
- kind: ty::BoundTyKind::Param(param.def_id, param.name),
- },
- )
- .into()
+ )
+ });
+ Ty::new_error(tcx, guar).into()
}
ty::GenericParamDefKind::Const { .. } => {
- if !emitted_bad_param_err {
+ let guar = *emitted_bad_param_err.get_or_insert_with(|| {
tcx.dcx().emit_err(
crate::errors::ReturnTypeNotationIllegalParam::Const {
span: path_span,
param_span: tcx.def_span(param.def_id),
},
- );
- emitted_bad_param_err = true;
- }
+ )
+ });
let ty = tcx
.type_of(param.def_id)
.no_bound_vars()
.expect("ct params cannot have early bound vars");
- ty::Const::new_bound(
- tcx,
- ty::INNERMOST,
- ty::BoundVar::from_usize(num_bound_vars),
- ty,
- )
- .into()
+ ty::Const::new_error(tcx, guar, ty).into()
}
};
num_bound_vars += 1;
diff --git a/compiler/rustc_hir_analysis/src/astconv/generics.rs b/compiler/rustc_hir_analysis/src/astconv/generics.rs
index f9628d1d6f3e..4284758b1172 100644
--- a/compiler/rustc_hir_analysis/src/astconv/generics.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/generics.rs
@@ -656,7 +656,7 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes(
} else {
let mut multispan = MultiSpan::from_span(span);
multispan.push_span_label(span_late, note);
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
LATE_BOUND_LIFETIME_ARGUMENTS,
args.args[0].hir_id(),
multispan,
diff --git a/compiler/rustc_hir_analysis/src/astconv/lint.rs b/compiler/rustc_hir_analysis/src/astconv/lint.rs
index b5f42e98127e..33e782abc68e 100644
--- a/compiler/rustc_hir_analysis/src/astconv/lint.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/lint.rs
@@ -94,15 +94,17 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
return false;
};
let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())];
+ let mut is_downgradable = true;
let is_object_safe = match self_ty.kind {
hir::TyKind::TraitObject(objects, ..) => {
objects.iter().all(|o| match o.trait_ref.path.res {
- Res::Def(DefKind::Trait, id) if Some(id) == owner => {
- // When we're dealing with a recursive trait, we don't want to downgrade
- // the error, so we consider them to be object safe always. (#119652)
- true
+ Res::Def(DefKind::Trait, id) => {
+ if Some(id) == owner {
+ // For recursive traits, don't downgrade the error. (#119652)
+ is_downgradable = false;
+ }
+ tcx.check_is_object_safe(id)
}
- Res::Def(DefKind::Trait, id) => tcx.check_is_object_safe(id),
_ => false,
})
}
@@ -130,7 +132,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
],
Applicability::MachineApplicable,
);
- } else if diag.is_error() {
+ } else if diag.is_error() && is_downgradable {
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
}
@@ -156,7 +158,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
}
if !is_object_safe {
diag.note(format!("`{trait_name}` it is not object safe, so it can't be `dyn`"));
- if diag.is_error() {
+ if diag.is_error() && is_downgradable {
// We'll emit the object safety error already, with a structured suggestion.
diag.downgrade_to_delayed_bug();
}
@@ -238,24 +240,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
diag.stash(self_ty.span, StashKey::TraitMissingMethod);
} else {
let msg = "trait objects without an explicit `dyn` are deprecated";
- tcx.struct_span_lint_hir(
- BARE_TRAIT_OBJECTS,
- self_ty.hir_id,
- self_ty.span,
- msg,
- |lint| {
- if self_ty.span.can_be_used_for_suggestions()
- && !self.maybe_lint_impl_trait(self_ty, lint)
- {
- lint.multipart_suggestion_verbose(
- "use `dyn`",
- sugg,
- Applicability::MachineApplicable,
- );
- }
- self.maybe_lint_blanket_trait_impl(self_ty, lint);
- },
- );
+ tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, msg, |lint| {
+ if self_ty.span.can_be_used_for_suggestions()
+ && !self.maybe_lint_impl_trait(self_ty, lint)
+ {
+ lint.multipart_suggestion_verbose(
+ "use `dyn`",
+ sugg,
+ Applicability::MachineApplicable,
+ );
+ }
+ self.maybe_lint_blanket_trait_impl(self_ty, lint);
+ });
}
}
}
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 00f0d6e7c224..7c97c2a1a6ff 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -1394,7 +1394,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let ty = self.projected_ty_from_poly_trait_ref(span, assoc_ty_did, assoc_segment, bound);
if let Some(variant_def_id) = variant_resolution {
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
AMBIGUOUS_ASSOCIATED_ITEMS,
hir_ref_id,
span,
diff --git a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
index 8967b51749c8..5f35f75c77b0 100644
--- a/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/object_safety.rs
@@ -220,7 +220,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let def_id = projection_bound.projection_def_id();
def_ids.remove(&def_id);
if tcx.generics_require_sized_self(def_id) {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNUSED_ASSOCIATED_TYPE_BOUNDS,
hir_id,
*span,
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 03e2b0e00220..c63bafcdcd46 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -46,7 +46,7 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) {
.emit();
}
None => {
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
UNSUPPORTED_CALLING_CONVENTIONS,
hir_id,
span,
@@ -183,7 +183,7 @@ fn check_static_inhabited(tcx: TyCtxt<'_>, def_id: LocalDefId) {
}
};
if layout.abi.is_uninhabited() {
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
UNINHABITED_STATIC,
tcx.local_def_id_to_hir_id(def_id),
span,
@@ -1079,7 +1079,7 @@ pub(super) fn check_transparent<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>)
// If there are any non-trivial fields, then there can be no non-exhaustive 1-zsts.
// Otherwise, it's only an issue if there's >1 non-exhaustive 1-zst.
if non_trivial_count > 0 || prev_non_exhaustive_1zst {
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS,
tcx.local_def_id_to_hir_id(adt.did().expect_local()),
span,
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
index 0d8de0cabd1a..6d2ebb150b95 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item/refine.rs
@@ -283,7 +283,7 @@ fn report_mismatched_rpitit_signature<'tcx>(
});
let span = unmatched_bound.unwrap_or(span);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
REFINING_IMPL_TRAIT,
tcx.local_def_id_to_hir_id(impl_m_def_id.expect_local()),
span,
diff --git a/compiler/rustc_hir_analysis/src/check/errs.rs b/compiler/rustc_hir_analysis/src/check/errs.rs
index 27bb2c57a5cb..87a1f3d34258 100644
--- a/compiler/rustc_hir_analysis/src/check/errs.rs
+++ b/compiler/rustc_hir_analysis/src/check/errs.rs
@@ -88,7 +88,7 @@ fn handle_static_mut_ref(
"shared ",
)
};
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
STATIC_MUT_REF,
hir_id,
span,
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
index db619d5169e4..d03b02f028da 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsicck.rs
@@ -270,7 +270,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> {
if !spans.is_empty() {
let (default_modifier, default_result) =
reg_class.default_modifier(asm_arch).unwrap();
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
lint::builtin::ASM_SUB_REGISTER,
expr.hir_id,
spans,
diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
index 3b9837ff7c2b..70213ee0614f 100644
--- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs
+++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs
@@ -116,7 +116,7 @@ where
let errors = wfcx.select_all_or_error();
if !errors.is_empty() {
let err = infcx.err_ctxt().report_fulfillment_errors(errors);
- if tcx.dcx().err_count() > 0 {
+ if tcx.dcx().has_errors().is_some() {
return Err(err);
} else {
// HACK(oli-obk): tests/ui/specialization/min_specialization/specialize_on_type_error.rs
diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs
index 36cb8f7a2022..aa5db4f6aa7b 100644
--- a/compiler/rustc_hir_analysis/src/check_unused.rs
+++ b/compiler/rustc_hir_analysis/src/check_unused.rs
@@ -40,12 +40,6 @@ fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) {
} else {
"unused import".to_owned()
};
- tcx.struct_span_lint_hir(
- lint::builtin::UNUSED_IMPORTS,
- item.hir_id(),
- path.span,
- msg,
- |_| {},
- );
+ tcx.node_span_lint(lint::builtin::UNUSED_IMPORTS, item.hir_id(), path.span, msg, |_| {});
}
}
diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
index c1d0e0444b67..1736de760d5a 100644
--- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs
@@ -495,7 +495,7 @@ fn lint_auto_trait_impl<'tcx>(
return;
}
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
lint::builtin::SUSPICIOUS_AUTO_TRAIT_IMPLS,
tcx.local_def_id_to_hir_id(impl_def_id),
tcx.def_span(impl_def_id),
diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
index b44b2eefabbc..c29d41318430 100644
--- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs
+++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs
@@ -274,7 +274,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics {
Defaults::FutureCompatDisallowed
if tcx.features().default_type_parameter_fallback => {}
Defaults::FutureCompatDisallowed => {
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
lint::builtin::INVALID_TYPE_PARAM_DEFAULT,
param.hir_id,
param.span,
diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
index 4f049f699e6c..a857e01f4fa7 100644
--- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
+++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs
@@ -912,7 +912,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> {
continue;
}
self.insert_lifetime(lt, ResolvedArg::StaticLifetime);
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
lint::builtin::UNUSED_LIFETIMES,
lifetime.hir_id,
lifetime.ident.span,
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index a720a858f3c1..bd8a2024caa1 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -587,7 +587,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
};
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
- fcx.tcx.emit_spanned_lint(
+ fcx.tcx.emit_node_span_lint(
lint,
self.expr.hir_id,
self.span,
@@ -900,7 +900,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
- fcx.tcx.emit_spanned_lint(
+ fcx.tcx.emit_node_span_lint(
lint::builtin::CENUM_IMPL_DROP_CAST,
self.expr.hir_id,
self.span,
@@ -934,7 +934,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
};
let lint = errors::LossyProvenancePtr2Int { expr_ty, cast_ty, sugg };
- fcx.tcx.emit_spanned_lint(
+ fcx.tcx.emit_node_span_lint(
lint::builtin::LOSSY_PROVENANCE_CASTS,
self.expr.hir_id,
self.span,
@@ -950,7 +950,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
let expr_ty = fcx.resolve_vars_if_possible(self.expr_ty);
let cast_ty = fcx.resolve_vars_if_possible(self.cast_ty);
let lint = errors::LossyProvenanceInt2Ptr { expr_ty, cast_ty, sugg };
- fcx.tcx.emit_spanned_lint(
+ fcx.tcx.emit_node_span_lint(
lint::builtin::FUZZY_PROVENANCE_CASTS,
self.expr.hir_id,
self.span,
diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs
index c887368b2a23..4d9f5b831c16 100644
--- a/compiler/rustc_hir_typeck/src/check.rs
+++ b/compiler/rustc_hir_typeck/src/check.rs
@@ -2,8 +2,7 @@ use std::cell::RefCell;
use crate::coercion::CoerceMany;
use crate::gather_locals::GatherLocalsVisitor;
-use crate::CoroutineTypes;
-use crate::FnCtxt;
+use crate::{CoroutineTypes, Diverges, FnCtxt};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::intravisit::Visitor;
@@ -76,6 +75,12 @@ pub(super) fn check_fn<'a, 'tcx>(
let ty: Option<&hir::Ty<'_>> = try { inputs_hir?.get(idx)? };
let ty_span = ty.map(|ty| ty.span);
fcx.check_pat_top(param.pat, param_ty, ty_span, None, None);
+ if param.pat.is_never_pattern() {
+ fcx.function_diverges_because_of_empty_arguments.set(Diverges::Always {
+ span: param.pat.span,
+ custom_note: Some("any code following a never pattern is unreachable"),
+ });
+ }
// Check that argument is Sized.
if !params_can_be_unsized {
@@ -105,6 +110,7 @@ pub(super) fn check_fn<'a, 'tcx>(
hir::FnRetTy::Return(ty) => ty.span,
};
fcx.require_type_is_sized(declared_ret_ty, return_or_body_span, traits::SizedReturnType);
+ fcx.is_whole_body.set(true);
fcx.check_return_expr(body.value, false);
// Finalize the return check by taking the LUB of the return types
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index e9d373119fa4..858faf161f6e 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -625,6 +625,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
)];
let mut has_unsized_tuple_coercion = false;
+ let mut has_trait_upcasting_coercion = None;
// Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
// emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -692,6 +693,13 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
// these here and emit a feature error if coercion doesn't fail
// due to another reason.
match impl_source {
+ traits::ImplSource::Builtin(
+ BuiltinImplSource::TraitUpcasting { .. },
+ _,
+ ) => {
+ has_trait_upcasting_coercion =
+ Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
+ }
traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
has_unsized_tuple_coercion = true;
}
@@ -702,6 +710,21 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
}
}
+ if let Some((sub, sup)) = has_trait_upcasting_coercion
+ && !self.tcx().features().trait_upcasting
+ {
+ // Renders better when we erase regions, since they're not really the point here.
+ let (sub, sup) = self.tcx.erase_regions((sub, sup));
+ let mut err = feature_err(
+ &self.tcx.sess,
+ sym::trait_upcasting,
+ self.cause.span,
+ format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
+ );
+ err.note(format!("required when coercing `{source}` into `{target}`"));
+ err.emit();
+ }
+
if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion {
feature_err(
&self.tcx.sess,
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index aca17ec77a4b..3bc259c17b77 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -208,10 +208,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// without the final expr (e.g. `try { return; }`). We don't want to generate an
// unreachable_code lint for it since warnings for autogenerated code are confusing.
let is_try_block_generated_unit_expr = match expr.kind {
- ExprKind::Call(_, args) if expr.span.is_desugaring(DesugaringKind::TryBlock) => {
- args.len() == 1 && args[0].span.is_desugaring(DesugaringKind::TryBlock)
+ ExprKind::Call(_, [arg]) => {
+ expr.span.is_desugaring(DesugaringKind::TryBlock)
+ && arg.span.is_desugaring(DesugaringKind::TryBlock)
}
-
_ => false,
};
@@ -220,9 +220,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
self.warn_if_unreachable(expr.hir_id, expr.span, "expression");
}
- // Hide the outer diverging and has_errors flags.
+ // Whether a past expression diverges doesn't affect typechecking of this expression, so we
+ // reset `diverges` while checking `expr`.
let old_diverges = self.diverges.replace(Diverges::Maybe);
+ if self.is_whole_body.replace(false) {
+ // If this expression is the whole body and the function diverges because of its
+ // arguments, we check this here to ensure the body is considered to diverge.
+ self.diverges.set(self.function_diverges_because_of_empty_arguments.get())
+ };
+
let ty = ensure_sufficient_stack(|| match &expr.kind {
hir::ExprKind::Path(
qpath @ (hir::QPath::Resolved(..) | hir::QPath::TypeRelative(..)),
@@ -2981,10 +2988,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// fixed expression:
if let ExprKind::Lit(lit) = idx.kind
&& let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node
- && i < types
- .len()
- .try_into()
- .expect("expected tuple index to be < usize length")
+ && i.get()
+ < types
+ .len()
+ .try_into()
+ .expect("expected tuple index to be < usize length")
{
err.span_suggestion(
brackets_span,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index 3ea409827b4b..09dbfaa57d24 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -62,7 +62,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
debug!("warn_if_unreachable: id={:?} span={:?} kind={}", id, span, kind);
let msg = format!("unreachable {kind}");
- self.tcx().struct_span_lint_hir(
+ self.tcx().node_span_lint(
lint::builtin::UNREACHABLE_CODE,
id,
span,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index ddb4224b60db..136ed1a709e9 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1471,6 +1471,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
/// Type check a `let` statement.
pub fn check_decl_local(&self, local: &'tcx hir::Local<'tcx>) {
self.check_decl(local.into());
+ if local.pat.is_never_pattern() {
+ self.diverges.set(Diverges::Always {
+ span: local.pat.span,
+ custom_note: Some("any code following a never pattern is unreachable"),
+ });
+ }
}
pub fn check_stmt(&self, stmt: &'tcx hir::Stmt<'tcx>) {
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
index e6c2091d85ad..f65e9b698ab2 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs
@@ -103,6 +103,13 @@ pub struct FnCtxt<'a, 'tcx> {
/// the diverges flag is set to something other than `Maybe`.
pub(super) diverges: Cell,
+ /// If one of the function arguments is a never pattern, this counts as diverging code. This
+ /// affect typechecking of the function body.
+ pub(super) function_diverges_because_of_empty_arguments: Cell,
+
+ /// Whether the currently checked node is the whole body of the function.
+ pub(super) is_whole_body: Cell,
+
pub(super) enclosing_breakables: RefCell>,
pub(super) inh: &'a Inherited<'tcx>,
@@ -124,6 +131,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ret_coercion_span: Cell::new(None),
coroutine_types: None,
diverges: Cell::new(Diverges::Maybe),
+ function_diverges_because_of_empty_arguments: Cell::new(Diverges::Maybe),
+ is_whole_body: Cell::new(false),
enclosing_breakables: RefCell::new(EnclosingBreakables {
stack: Vec::new(),
by_id: Default::default(),
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 2778ada655e3..7780ceda1c1b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -11,6 +11,7 @@ use crate::ty::TypeAndMut;
use core::cmp::min;
use core::iter;
use rustc_ast::util::parser::{ExprPrecedence, PREC_POSTFIX};
+use rustc_data_structures::packed::Pu128;
use rustc_errors::{Applicability, Diagnostic, MultiSpan};
use rustc_hir as hir;
use rustc_hir::def::Res;
@@ -1409,8 +1410,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
let (_, suffix) = snippet.split_at(snippet.len() - 3);
let value = match suffix {
- "f32" => (lit - 0xf32) / (16 * 16 * 16),
- "f64" => (lit - 0xf64) / (16 * 16 * 16),
+ "f32" => (lit.get() - 0xf32) / (16 * 16 * 16),
+ "f64" => (lit.get() - 0xf64) / (16 * 16 * 16),
_ => return false,
};
err.span_suggestions(
@@ -1440,7 +1441,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
};
// Provided expression needs to be a literal `0`.
- let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(0, _), span }) = expr.kind else {
+ let ExprKind::Lit(Spanned { node: rustc_ast::LitKind::Int(Pu128(0), _), span }) = expr.kind
+ else {
return false;
};
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 43d258de6ca7..0e43cb40485a 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -77,7 +77,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// Inherent impls only require not relying on autoref and autoderef in order to
// ensure that the trait implementation won't be used
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
prelude_or_array_lint,
self_expr.hir_id,
self_expr.span,
@@ -127,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
} else {
// trait implementations require full disambiguation to not clash with the new prelude
// additions (i.e. convert from dot-call to fully-qualified call)
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
prelude_or_array_lint,
call_expr.hir_id,
call_expr.span,
@@ -238,7 +238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
return;
}
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
RUST_2021_PRELUDE_COLLISIONS,
expr_id,
span,
diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs
index 4dc802008d03..17eff54f7ae8 100644
--- a/compiler/rustc_hir_typeck/src/method/probe.rs
+++ b/compiler/rustc_hir_typeck/src/method/probe.rs
@@ -440,7 +440,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
if self.tcx.sess.at_least_rust_2018() {
self.dcx().emit_err(MethodCallOnUnknownRawPointee { span });
} else {
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
lint::builtin::TYVAR_BEHIND_RAW_POINTER,
scope_expr_id,
span,
@@ -1380,7 +1380,7 @@ impl<'tcx> Pick<'tcx> {
return;
}
let def_kind = self.item.kind.as_def_kind();
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
lint::builtin::UNSTABLE_NAME_COLLISIONS,
scope_expr_id,
span,
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index ee411f8ed5f1..ff82e2d653cf 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -4,6 +4,7 @@ use super::method::MethodCallee;
use super::{has_expected_num_generic_args, FnCtxt};
use crate::Expectation;
use rustc_ast as ast;
+use rustc_data_structures::packed::Pu128;
use rustc_errors::{struct_span_code_err, Applicability, Diagnostic, DiagnosticBuilder};
use rustc_hir as hir;
use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
@@ -834,7 +835,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
hir::Expr {
kind:
hir::ExprKind::Lit(Spanned {
- node: ast::LitKind::Int(1, _),
+ node: ast::LitKind::Int(Pu128(1), _),
..
}),
..
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 371068672770..73fc0ee499e6 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -1840,7 +1840,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
&unmentioned_fields.iter().map(|(_, i)| i).collect::>(),
);
- self.tcx.struct_span_lint_hir(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
+ self.tcx.node_span_lint(NON_EXHAUSTIVE_OMITTED_PATTERNS, pat.hir_id, pat.span, "some fields are not explicitly listed", |lint| {
lint.span_label(pat.span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns));
lint.help(
"ensure that all fields are mentioned explicitly by adding the suggested fields",
diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs
index f6b05e1b35a6..82c5e566f161 100644
--- a/compiler/rustc_hir_typeck/src/upvar.rs
+++ b/compiler/rustc_hir_typeck/src/upvar.rs
@@ -754,7 +754,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let closure_hir_id = self.tcx.local_def_id_to_hir_id(closure_def_id);
let closure_head_span = self.tcx.def_span(closure_def_id);
- self.tcx.struct_span_lint_hir(
+ self.tcx.node_span_lint(
lint::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES,
closure_hir_id,
closure_head_span,
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index e18b1365d9c0..2578f284dee7 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -312,7 +312,7 @@ pub fn finalize_session_directory(sess: &Session, svh: Option) {
let incr_comp_session_dir: PathBuf = sess.incr_comp_session_dir().clone();
- if let Some(_) = sess.dcx().has_errors_or_span_delayed_bugs() {
+ if sess.dcx().has_errors_or_lint_errors_or_delayed_bugs().is_some() {
// If there have been any errors during compilation, we don't want to
// publish this session directory. Rather, we'll just delete it.
diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs
index 08b7d08bcc00..ff0c58d09de2 100644
--- a/compiler/rustc_incremental/src/persist/save.rs
+++ b/compiler/rustc_incremental/src/persist/save.rs
@@ -31,8 +31,8 @@ pub fn save_dep_graph(tcx: TyCtxt<'_>) {
if sess.opts.incremental.is_none() {
return;
}
- // This is going to be deleted in finalize_session_directory, so let's not create it
- if let Some(_) = sess.dcx().has_errors_or_span_delayed_bugs() {
+ // This is going to be deleted in finalize_session_directory, so let's not create it.
+ if sess.dcx().has_errors_or_lint_errors_or_delayed_bugs().is_some() {
return;
}
@@ -87,7 +87,7 @@ pub fn save_work_product_index(
return;
}
// This is going to be deleted in finalize_session_directory, so let's not create it
- if let Some(_) = sess.dcx().has_errors_or_span_delayed_bugs() {
+ if sess.dcx().has_errors_or_lint_errors().is_some() {
return;
}
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 875e94fcd9f1..7882e761a0c3 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -117,9 +117,9 @@ fn escape_literal(s: &str) -> String {
/// field is only populated during an in-progress typeck.
/// Get an instance by calling `InferCtxt::err_ctxt` or `FnCtxt::err_ctxt`.
///
-/// You must only create this if you intend to actually emit an error.
-/// This provides a lot of utility methods which should not be used
-/// during the happy path.
+/// You must only create this if you intend to actually emit an error (or
+/// perhaps a warning, though preferably not.) It provides a lot of utility
+/// methods which should not be used during the happy path.
pub struct TypeErrCtxt<'a, 'tcx> {
pub infcx: &'a InferCtxt<'tcx>,
pub typeck_results: Option>>,
@@ -133,9 +133,10 @@ pub struct TypeErrCtxt<'a, 'tcx> {
impl Drop for TypeErrCtxt<'_, '_> {
fn drop(&mut self) {
- if let Some(_) = self.dcx().has_errors_or_span_delayed_bugs() {
- // ok, emitted an error.
+ if self.dcx().has_errors().is_some() {
+ // Ok, emitted an error.
} else {
+ // Didn't emit an error; maybe it was created but not yet emitted.
self.infcx
.tcx
.sess
diff --git a/compiler/rustc_infer/src/infer/relate/combine.rs b/compiler/rustc_infer/src/infer/relate/combine.rs
index 9e1dab12b4d4..1c120646f1f9 100644
--- a/compiler/rustc_infer/src/infer/relate/combine.rs
+++ b/compiler/rustc_infer/src/infer/relate/combine.rs
@@ -165,9 +165,9 @@ impl<'tcx> InferCtxt<'tcx> {
//
// This probe is probably not strictly necessary but it seems better to be safe and not accidentally find
// ourselves with a check to find bugs being required for code to compile because it made inference progress.
- let compatible_types = self.probe(|_| {
+ self.probe(|_| {
if a.ty() == b.ty() {
- return Ok(());
+ return;
}
// We don't have access to trait solving machinery in `rustc_infer` so the logic for determining if the
@@ -177,32 +177,18 @@ impl<'tcx> InferCtxt<'tcx> {
relation.param_env().and((a.ty(), b.ty())),
&mut OriginalQueryValues::default(),
);
- self.tcx.check_tys_might_be_eq(canonical).map_err(|_| {
+ self.tcx.check_tys_might_be_eq(canonical).unwrap_or_else(|_| {
+ // The error will only be reported later. If we emit an ErrorGuaranteed
+ // here, then we will never get to the code that actually emits the error.
self.tcx.dcx().delayed_bug(format!(
"cannot relate consts of different types (a={a:?}, b={b:?})",
- ))
- })
+ ));
+ // We treat these constants as if they were of the same type, so that any
+ // such constants being used in impls make these impls match barring other mismatches.
+ // This helps with diagnostics down the road.
+ });
});
- // If the consts have differing types, just bail with a const error with
- // the expected const's type. Specifically, we don't want const infer vars
- // to do any type shapeshifting before and after resolution.
- if let Err(guar) = compatible_types {
- // HACK: equating both sides with `[const error]` eagerly prevents us
- // from leaving unconstrained inference vars during things like impl
- // matching in the solver.
- let a_error = ty::Const::new_error(self.tcx, guar, a.ty());
- if let ty::ConstKind::Infer(InferConst::Var(vid)) = a.kind() {
- return self.unify_const_variable(vid, a_error, relation.param_env());
- }
- let b_error = ty::Const::new_error(self.tcx, guar, b.ty());
- if let ty::ConstKind::Infer(InferConst::Var(vid)) = b.kind() {
- return self.unify_const_variable(vid, b_error, relation.param_env());
- }
-
- return Ok(if relation.a_is_expected() { a_error } else { b_error });
- }
-
match (a.kind(), b.kind()) {
(
ty::ConstKind::Infer(InferConst::Var(a_vid)),
diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs
index 555c822ad6d6..2d4963a8b901 100644
--- a/compiler/rustc_interface/src/tests.rs
+++ b/compiler/rustc_interface/src/tests.rs
@@ -98,6 +98,7 @@ fn assert_same_hash(x: &Options, y: &Options) {
assert_same_clone(y);
}
+#[track_caller]
fn assert_different_hash(x: &Options, y: &Options) {
assert_ne!(x.dep_tracking_hash(true), y.dep_tracking_hash(true));
assert_ne!(x.dep_tracking_hash(false), y.dep_tracking_hash(false));
@@ -713,7 +714,6 @@ fn test_unstable_options_tracking_hash() {
untracked!(unpretty, Some("expanded".to_string()));
untracked!(unstable_options, true);
untracked!(validate_mir, true);
- untracked!(verbose_internals, true);
untracked!(write_long_types_to_disk, false);
// tidy-alphabetical-end
@@ -845,6 +845,7 @@ fn test_unstable_options_tracking_hash() {
};
}
tracked_no_crate_hash!(no_codegen, true);
+ tracked_no_crate_hash!(verbose_internals, true);
}
#[test]
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 43dfd34a6ff7..f6c9289b529c 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -20,8 +20,9 @@
//! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-// We want to be able to build this crate with a stable compiler, so no
-// `#![feature]` attributes should be added.
+// We want to be able to build this crate with a stable compiler,
+// so no `#![feature]` attributes should be added.
+#![deny(unstable_features)]
mod cursor;
pub mod unescape;
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index b6fa2f1f2216..5652a34103b0 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -148,7 +148,7 @@ lint_builtin_unsafe_impl = implementation of an `unsafe` trait
lint_builtin_unsafe_trait = declaration of an `unsafe` trait
-lint_builtin_unstable_features = unstable feature
+lint_builtin_unstable_features = use of an unstable feature
lint_builtin_unused_doc_comment = unused doc comment
.label = rustdoc does not generate documentation for {$kind}
@@ -240,7 +240,10 @@ lint_hidden_unicode_codepoints = unicode codepoint changing visible direction of
lint_identifier_non_ascii_char = identifier contains non-ASCII characters
-lint_identifier_uncommon_codepoints = identifier contains uncommon Unicode codepoints
+lint_identifier_uncommon_codepoints = identifier contains {$codepoints_len ->
+ [one] an uncommon Unicode codepoint
+ *[other] uncommon Unicode codepoints
+}: {$codepoints}
lint_ignored_unless_crate_specified = {$level}({$name}) is ignored unless specified at crate level
@@ -345,6 +348,9 @@ lint_multiple_supertrait_upcastable = `{$ident}` is object-safe and has multiple
lint_node_source = `forbid` level set here
.note = {$reason}
+lint_non_binding_let_multi_drop_fn =
+ consider immediately dropping the value using `drop(..)` after the `let` statement
+
lint_non_binding_let_multi_suggestion =
consider immediately dropping the value
diff --git a/compiler/rustc_lint/src/array_into_iter.rs b/compiler/rustc_lint/src/array_into_iter.rs
index 814991cd8c97..3a5c585366a3 100644
--- a/compiler/rustc_lint/src/array_into_iter.rs
+++ b/compiler/rustc_lint/src/array_into_iter.rs
@@ -132,7 +132,7 @@ impl<'tcx> LateLintPass<'tcx> for ArrayIntoIter {
} else {
None
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
ARRAY_INTO_ITER,
call.ident.span,
ArrayIntoIterDiag { target, suggestion: call.ident.span, sub },
diff --git a/compiler/rustc_lint/src/async_fn_in_trait.rs b/compiler/rustc_lint/src/async_fn_in_trait.rs
index 512136473617..5f7a3137d52d 100644
--- a/compiler/rustc_lint/src/async_fn_in_trait.rs
+++ b/compiler/rustc_lint/src/async_fn_in_trait.rs
@@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for AsyncFnInTrait {
def.owner_id.def_id,
" + Send",
);
- cx.tcx.emit_spanned_lint(
+ cx.tcx.emit_node_span_lint(
ASYNC_FN_IN_TRAIT,
item.hir_id(),
async_span,
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 5e1f2ed11ac9..07f127414dbc 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -121,7 +121,7 @@ impl EarlyLintPass for WhileTrue {
"{}loop",
label.map_or_else(String::new, |label| format!("{}: ", label.ident,))
);
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
WHILE_TRUE,
condition_span,
BuiltinWhileTrue { suggestion: condition_span, replace },
@@ -162,7 +162,7 @@ impl BoxPointers {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack()
&& leaf_ty.is_box()
{
- cx.emit_spanned_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
+ cx.emit_span_lint(BOX_POINTERS, span, BuiltinBoxPointers { ty });
}
}
}
@@ -265,7 +265,7 @@ impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns {
if cx.tcx.find_field_index(ident, variant)
== Some(cx.typeck_results().field_index(fieldpat.hir_id))
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NON_SHORTHAND_FIELD_PATTERNS,
fieldpat.span,
BuiltinNonShorthandFieldPatterns {
@@ -334,7 +334,7 @@ impl UnsafeCode {
return;
}
- cx.emit_spanned_lint(UNSAFE_CODE, span, decorate);
+ cx.emit_span_lint(UNSAFE_CODE, span, decorate);
}
}
@@ -509,7 +509,7 @@ impl MissingDoc {
let attrs = cx.tcx.hir().attrs(cx.tcx.local_def_id_to_hir_id(def_id));
let has_doc = attrs.iter().any(has_doc);
if !has_doc {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
MISSING_DOCS,
cx.tcx.def_span(def_id),
BuiltinMissingDoc { article, desc },
@@ -710,7 +710,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingCopyImplementations {
)
.is_ok()
{
- cx.emit_spanned_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, BuiltinMissingCopyImpl);
+ cx.emit_span_lint(MISSING_COPY_IMPLEMENTATIONS, item.span, BuiltinMissingCopyImpl);
}
}
}
@@ -795,7 +795,7 @@ impl<'tcx> LateLintPass<'tcx> for MissingDebugImplementations {
.next()
.is_some();
if !has_impl {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
MISSING_DEBUG_IMPLEMENTATIONS,
item.span,
BuiltinMissingDebugImpl { tcx: cx.tcx, def_id: debug },
@@ -874,7 +874,7 @@ impl EarlyLintPass for AnonymousParameters {
} else {
("", Applicability::HasPlaceholders)
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
ANONYMOUS_PARAMETERS,
arg.pat.span,
BuiltinAnonymousParams { suggestion: (arg.pat.span, appl), ty_snip },
@@ -921,7 +921,7 @@ impl EarlyLintPass for DeprecatedAttr {
BuiltinDeprecatedAttrLinkSuggestion::Default { suggestion: attr.span }
}
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DEPRECATED,
attr.span,
BuiltinDeprecatedAttrLink { name, reason, link, suggestion },
@@ -931,7 +931,7 @@ impl EarlyLintPass for DeprecatedAttr {
}
}
if attr.has_name(sym::no_start) || attr.has_name(sym::crate_id) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DEPRECATED,
attr.span,
BuiltinDeprecatedAttrUsed {
@@ -973,7 +973,7 @@ fn warn_if_doc(cx: &EarlyContext<'_>, node_span: Span, node_kind: &str, attrs: &
BuiltinUnusedDocCommentSub::BlockHelp
}
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNUSED_DOC_COMMENTS,
span,
BuiltinUnusedDocComment { kind: node_kind, label: node_span, sub },
@@ -1107,7 +1107,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
match param.kind {
GenericParamKind::Lifetime { .. } => {}
GenericParamKind::Type { .. } | GenericParamKind::Const { .. } => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NO_MANGLE_GENERIC_ITEMS,
span,
BuiltinNoMangleGeneric { suggestion: no_mangle_attr.span },
@@ -1138,7 +1138,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidNoMangleItems {
// Const items do not refer to a particular location in memory, and therefore
// don't have anything to attach a symbol to
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NO_MANGLE_CONST_ITEMS,
it.span,
BuiltinConstNoMangle { suggestion },
@@ -1201,7 +1201,7 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (ty1.kind(), ty2.kind()))
{
if from_mutbl < to_mutbl {
- cx.emit_spanned_lint(MUTABLE_TRANSMUTES, expr.span, BuiltinMutablesTransmutes);
+ cx.emit_span_lint(MUTABLE_TRANSMUTES, expr.span, BuiltinMutablesTransmutes);
}
}
@@ -1233,10 +1233,30 @@ impl<'tcx> LateLintPass<'tcx> for MutableTransmutes {
}
declare_lint! {
- /// The `unstable_features` is deprecated and should no longer be used.
+ /// The `unstable_features` lint detects uses of `#![feature]`.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,compile_fail
+ /// #![deny(unstable_features)]
+ /// #![feature(test)]
+ /// ```
+ ///
+ /// {{produces}}
+ ///
+ /// ### Explanation
+ ///
+ /// In larger nightly-based projects which
+ ///
+ /// * consist of a multitude of crates where a subset of crates has to compile on
+ /// stable either unconditionally or depending on a `cfg` flag to for example
+ /// allow stable users to depend on them,
+ /// * don't use nightly for experimental features but for, e.g., unstable options only,
+ ///
+ /// this lint may come in handy to enforce policies of these kinds.
UNSTABLE_FEATURES,
Allow,
- "enabling unstable features (deprecated. do not use)"
+ "enabling unstable features"
}
declare_lint_pass!(
@@ -1246,11 +1266,11 @@ declare_lint_pass!(
impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
fn check_attribute(&mut self, cx: &LateContext<'_>, attr: &ast::Attribute) {
- if attr.has_name(sym::feature) {
- if let Some(items) = attr.meta_item_list() {
- for item in items {
- cx.emit_spanned_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
- }
+ if attr.has_name(sym::feature)
+ && let Some(items) = attr.meta_item_list()
+ {
+ for item in items {
+ cx.emit_span_lint(UNSTABLE_FEATURES, item.span(), BuiltinUnstableFeatures);
}
}
}
@@ -1303,7 +1323,7 @@ impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
// Now, check if the function has the `#[track_caller]` attribute
&& let Some(attr) = cx.tcx.get_attr(def_id, sym::track_caller)
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNGATED_ASYNC_FN_TRACK_CALLER,
attr.span,
BuiltinUngatedAsyncFnTrackCaller { label: span, session: &cx.tcx.sess },
@@ -1369,7 +1389,7 @@ impl UnreachablePub {
applicability = Applicability::MaybeIncorrect;
}
let def_span = cx.tcx.def_span(def_id);
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNREACHABLE_PUB,
def_span,
BuiltinUnreachablePub {
@@ -1498,7 +1518,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
suggested_changing_assoc_types = true;
SuggestChangingAssocTypes { ty: hir_ty }
});
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
TYPE_ALIAS_BOUNDS,
where_spans,
BuiltinTypeAliasWhereClause {
@@ -1514,7 +1534,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeAliasBounds {
suggested_changing_assoc_types = true;
SuggestChangingAssocTypes { ty: hir_ty }
});
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
TYPE_ALIAS_BOUNDS,
inline_spans,
BuiltinTypeAliasGenericBounds { suggestion, sub },
@@ -1613,7 +1633,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
| ClauseKind::ConstEvaluatable(..) => continue,
};
if predicate.is_global() {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
TRIVIAL_BOUNDS,
span,
BuiltinTrivialBounds { predicate_kind_name, predicate },
@@ -1731,7 +1751,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
replace,
});
} else {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
pat.span,
BuiltinEllipsisInclusiveRangePatternsLint::Parenthesise {
@@ -1749,7 +1769,7 @@ impl EarlyLintPass for EllipsisInclusiveRangePatterns {
replace: replace.to_string(),
});
} else {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
join,
BuiltinEllipsisInclusiveRangePatternsLint::NonParenthesise {
@@ -1875,7 +1895,7 @@ impl KeywordIdents {
return;
}
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
KEYWORD_IDENTS,
ident.span,
BuiltinKeywordIdents { kw: ident, next: next_edition, suggestion: ident.span },
@@ -2183,7 +2203,7 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements {
lint_spans.sort_unstable();
lint_spans.dedup();
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
EXPLICIT_OUTLIVES_REQUIREMENTS,
lint_spans.clone(),
BuiltinExplicitOutlives {
@@ -2270,13 +2290,13 @@ impl EarlyLintPass for IncompleteInternalFeatures {
let help =
HAS_MIN_FEATURES.contains(&name).then_some(BuiltinIncompleteFeaturesHelp);
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
INCOMPLETE_FEATURES,
span,
BuiltinIncompleteFeatures { name, note, help },
);
} else {
- cx.emit_spanned_lint(INTERNAL_FEATURES, span, BuiltinInternalFeatures { name });
+ cx.emit_span_lint(INTERNAL_FEATURES, span, BuiltinInternalFeatures { name });
}
});
}
@@ -2592,7 +2612,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidValue {
InitKind::Uninit => fluent::lint_builtin_unpermitted_type_init_uninit,
};
let sub = BuiltinUnpermittedTypeInitSub { err };
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
INVALID_VALUE,
expr.span,
BuiltinUnpermittedTypeInit {
@@ -2680,7 +2700,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr {
if let rustc_hir::ExprKind::Unary(rustc_hir::UnOp::Deref, expr_deref) = expr.kind {
if is_null_ptr(cx, expr_deref) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DEREF_NULLPTR,
expr.span,
BuiltinDerefNullptr { label: expr.span },
@@ -2829,7 +2849,7 @@ impl<'tcx> LateLintPass<'tcx> for NamedAsmLabels {
let target_spans: MultiSpan =
if spans.len() > 0 { spans.into() } else { (*template_span).into() };
- cx.lookup_with_diagnostics(
+ cx.span_lint_with_diagnostics(
NAMED_ASM_LABELS,
Some(target_spans),
fluent::lint_builtin_asm_labels,
@@ -2905,12 +2925,12 @@ impl EarlyLintPass for SpecialModuleName {
}
match item.ident.name.as_str() {
- "lib" => cx.emit_spanned_lint(
+ "lib" => cx.emit_span_lint(
SPECIAL_MODULE_NAME,
item.span,
BuiltinSpecialModuleNameUsed::Lib,
),
- "main" => cx.emit_spanned_lint(
+ "main" => cx.emit_span_lint(
SPECIAL_MODULE_NAME,
item.span,
BuiltinSpecialModuleNameUsed::Main,
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index ffd8f1b3c79c..04201a38c35e 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -530,9 +530,9 @@ pub trait LintContext {
/// Emit a lint at the appropriate level, with an optional associated span and an existing
/// diagnostic.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
- fn lookup_with_diagnostics(
+ fn span_lint_with_diagnostics(
&self,
lint: &'static Lint,
span: Option>,
@@ -541,7 +541,7 @@ pub trait LintContext {
diagnostic: BuiltinLintDiagnostics,
) {
// We first generate a blank diagnostic.
- self.lookup(lint, span, msg, |db| {
+ self.opt_span_lint(lint, span, msg, |db| {
// Now, set up surrounding context.
diagnostics::builtin(self.sess(), diagnostic, db);
// Rewrap `db`, and pass control to the user.
@@ -553,9 +553,9 @@ pub trait LintContext {
// set the span in their `decorate` function (preferably using set_span).
/// Emit a lint at the appropriate level, with an optional associated span.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
- fn lookup>(
+ fn opt_span_lint>(
&self,
lint: &'static Lint,
span: Option,
@@ -565,42 +565,42 @@ pub trait LintContext {
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
/// typically generated by `#[derive(LintDiagnostic)]`).
- fn emit_spanned_lint>(
+ fn emit_span_lint>(
&self,
lint: &'static Lint,
span: S,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
- self.lookup(lint, Some(span), decorator.msg(), |diag| {
+ self.opt_span_lint(lint, Some(span), decorator.msg(), |diag| {
decorator.decorate_lint(diag);
});
}
/// Emit a lint at the appropriate level, with an associated span.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
- fn struct_span_lint>(
+ fn span_lint>(
&self,
lint: &'static Lint,
span: S,
msg: impl Into,
decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
- self.lookup(lint, Some(span), msg, decorate);
+ self.opt_span_lint(lint, Some(span), msg, decorate);
}
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
/// generated by `#[derive(LintDiagnostic)]`).
fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> DecorateLint<'a, ()>) {
- self.lookup(lint, None as Option, decorator.msg(), |diag| {
+ self.opt_span_lint(lint, None as Option, decorator.msg(), |diag| {
decorator.decorate_lint(diag);
});
}
/// Emit a lint at the appropriate level, with no associated span.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
fn lint(
&self,
@@ -608,7 +608,7 @@ pub trait LintContext {
msg: impl Into,
decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
- self.lookup(lint, None as Option, msg, decorate);
+ self.opt_span_lint(lint, None as Option, msg, decorate);
}
/// This returns the lint level for the given lint at the current location.
@@ -666,7 +666,7 @@ impl<'tcx> LintContext for LateContext<'tcx> {
}
#[rustc_lint_diagnostics]
- fn lookup>(
+ fn opt_span_lint>(
&self,
lint: &'static Lint,
span: Option,
@@ -676,8 +676,8 @@ impl<'tcx> LintContext for LateContext<'tcx> {
let hir_id = self.last_node_with_lint_attrs;
match span {
- Some(s) => self.tcx.struct_span_lint_hir(lint, hir_id, s, msg, decorate),
- None => self.tcx.struct_lint_node(lint, hir_id, msg, decorate),
+ Some(s) => self.tcx.node_span_lint(lint, hir_id, s, msg, decorate),
+ None => self.tcx.node_lint(lint, hir_id, msg, decorate),
}
}
@@ -693,14 +693,14 @@ impl LintContext for EarlyContext<'_> {
}
#[rustc_lint_diagnostics]
- fn lookup>(
+ fn opt_span_lint>(
&self,
lint: &'static Lint,
span: Option,
msg: impl Into,
decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
- self.builder.struct_lint(lint, span.map(|s| s.into()), msg, decorate)
+ self.builder.opt_span_lint(lint, span.map(|s| s.into()), msg, decorate)
}
fn get_lint_level(&self, lint: &'static Lint) -> Level {
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index 98bafc0f2637..9bc81d2c46aa 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -5,6 +5,7 @@ use crate::{
use rustc_hir as hir;
use rustc_middle::ty;
+use rustc_session::lint::FutureIncompatibilityReason;
use rustc_span::sym;
use rustc_trait_selection::traits::supertraits;
@@ -12,6 +13,9 @@ declare_lint! {
/// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
/// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
///
+ /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
+ /// The `deref` functions will no longer be called implicitly, so there might be behavior change.
+ ///
/// ### Example
///
/// ```rust,compile_fail
@@ -40,10 +44,15 @@ declare_lint! {
///
/// ### Explanation
///
- /// The implicit dyn upcasting coercion take priority over those `Deref` impls.
+ /// The dyn upcasting coercion feature adds new coercion rules, taking priority
+ /// over certain other coercion rules, which will cause some behavior change.
pub DEREF_INTO_DYN_SUPERTRAIT,
Warn,
- "`Deref` implementation usage with a supertrait trait object for output are shadow by implicit coercion",
+ "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
+ @future_incompatible = FutureIncompatibleInfo {
+ reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
+ reference: "issue #89460 ",
+ };
}
declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
@@ -78,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefIntoDynSupertrait {
.find_map(|i| (i.ident.name == sym::Target).then_some(i.span))
.map(|label| SupertraitAsDerefTargetLabel { label });
let span = tcx.def_span(item.owner_id.def_id);
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DEREF_INTO_DYN_SUPERTRAIT,
span,
SupertraitAsDerefTarget {
diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs
index 390a1620a2a5..9a31aa062f01 100644
--- a/compiler/rustc_lint/src/drop_forget_useless.rs
+++ b/compiler/rustc_lint/src/drop_forget_useless.rs
@@ -149,28 +149,28 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
let drop_is_single_call_in_arm = is_single_call_in_arm(cx, arg, expr);
match fn_name {
sym::mem_drop if arg_ty.is_ref() && !drop_is_single_call_in_arm => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DROPPING_REFERENCES,
expr.span,
DropRefDiag { arg_ty, label: arg.span },
);
}
sym::mem_forget if arg_ty.is_ref() => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
FORGETTING_REFERENCES,
expr.span,
ForgetRefDiag { arg_ty, label: arg.span },
);
}
sym::mem_drop if is_copy && !drop_is_single_call_in_arm => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DROPPING_COPY_TYPES,
expr.span,
DropCopyDiag { arg_ty, label: arg.span },
);
}
sym::mem_forget if is_copy => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
FORGETTING_COPY_TYPES,
expr.span,
ForgetCopyDiag { arg_ty, label: arg.span },
@@ -180,7 +180,7 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless {
if let ty::Adt(adt, _) = arg_ty.kind()
&& adt.is_manually_drop() =>
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNDROPPED_MANUALLY_DROPS,
expr.span,
UndroppedManuallyDropsDiag {
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 70af6572246f..5ae080d47023 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -45,7 +45,13 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
fn inlined_check_id(&mut self, id: ast::NodeId) {
for early_lint in self.context.buffered.take(id) {
let BufferedEarlyLint { span, msg, node_id: _, lint_id, diagnostic } = early_lint;
- self.context.lookup_with_diagnostics(lint_id.lint, Some(span), msg, |_| {}, diagnostic);
+ self.context.span_lint_with_diagnostics(
+ lint_id.lint,
+ Some(span),
+ msg,
+ |_| {},
+ diagnostic,
+ );
}
}
diff --git a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
index 05fe64830d17..a67f1b62fb0d 100644
--- a/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
+++ b/compiler/rustc_lint/src/enum_intrinsics_non_enums.rs
@@ -53,7 +53,7 @@ fn enforce_mem_discriminant(
) {
let ty_param = cx.typeck_results().node_args(func_expr.hir_id).type_at(0);
if is_non_enum(ty_param) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
ENUM_INTRINSICS_NON_ENUMS,
expr_span,
EnumIntrinsicsMemDiscriminate { ty_param, note: args_span },
@@ -64,11 +64,7 @@ fn enforce_mem_discriminant(
fn enforce_mem_variant_count(cx: &LateContext<'_>, func_expr: &hir::Expr<'_>, span: Span) {
let ty_param = cx.typeck_results().node_args(func_expr.hir_id).type_at(0);
if is_non_enum(ty_param) {
- cx.emit_spanned_lint(
- ENUM_INTRINSICS_NON_ENUMS,
- span,
- EnumIntrinsicsMemVariant { ty_param },
- );
+ cx.emit_span_lint(ENUM_INTRINSICS_NON_ENUMS, span, EnumIntrinsicsMemVariant { ty_param });
}
}
diff --git a/compiler/rustc_lint/src/expect.rs b/compiler/rustc_lint/src/expect.rs
index 2b6290e8a006..40db765da53a 100644
--- a/compiler/rustc_lint/src/expect.rs
+++ b/compiler/rustc_lint/src/expect.rs
@@ -29,7 +29,7 @@ fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option) {
{
let rationale = expectation.reason.map(|rationale| ExpectationNote { rationale });
let note = expectation.is_unfulfilled_lint_expectations.then_some(());
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNFULFILLED_LINT_EXPECTATIONS,
*hir_id,
expectation.emission_span,
diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
index ea922785a954..cb7feea16b53 100644
--- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs
+++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs
@@ -81,7 +81,7 @@ impl<'tcx> LateLintPass<'tcx> for ForLoopsOverFallibles {
end_span: pat.span.between(arg.span),
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
FOR_LOOPS_OVER_FALLIBLES,
arg.span,
ForLoopsOverFalliblesDiag { article, ty, sub, question_mark, suggestion },
diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs
index ecb7a157f39b..b995f38f23c6 100644
--- a/compiler/rustc_lint/src/foreign_modules.rs
+++ b/compiler/rustc_lint/src/foreign_modules.rs
@@ -161,7 +161,7 @@ impl ClashingExternDeclarations {
sub,
}
};
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
CLASHING_EXTERN_DECLARATIONS,
this_fi.hir_id(),
mismatch_label,
diff --git a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
index 7c1af6bee1dd..054cfe92a3a4 100644
--- a/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
+++ b/compiler/rustc_lint/src/hidden_unicode_codepoints.rs
@@ -74,7 +74,7 @@ impl HiddenUnicodeCodepoints {
HiddenUnicodeCodepointsDiagSub::NoEscape { spans }
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
TEXT_DIRECTION_CODEPOINT_IN_LITERAL,
span,
HiddenUnicodeCodepointsDiag { label, count, span_label: span, labels, sub },
diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs
index e3405aa2e559..eb2490a47d09 100644
--- a/compiler/rustc_lint/src/internal.rs
+++ b/compiler/rustc_lint/src/internal.rs
@@ -43,7 +43,7 @@ impl LateLintPass<'_> for DefaultHashTypes {
Some(sym::HashSet) => "FxHashSet",
_ => return,
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DEFAULT_HASH_TYPES,
path.span,
DefaultHashTypesDiag { preferred, used: cx.tcx.item_name(def_id) },
@@ -91,7 +91,7 @@ impl LateLintPass<'_> for QueryStability {
if let Ok(Some(instance)) = ty::Instance::resolve(cx.tcx, cx.param_env, def_id, args) {
let def_id = instance.def_id();
if cx.tcx.has_attr(def_id, sym::rustc_lint_query_instability) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
POTENTIAL_QUERY_INSTABILITY,
span,
QueryInstability { query: cx.tcx.item_name(def_id) },
@@ -136,7 +136,7 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
{
let span =
path.span.with_hi(segment.args.map_or(segment.ident.span, |a| a.span_ext).hi());
- cx.emit_spanned_lint(USAGE_OF_TY_TYKIND, path.span, TykindKind { suggestion: span });
+ cx.emit_span_lint(USAGE_OF_TY_TYKIND, path.span, TykindKind { suggestion: span });
}
}
@@ -186,19 +186,19 @@ impl<'tcx> LateLintPass<'tcx> for TyTyKind {
match span {
Some(span) => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
USAGE_OF_TY_TYKIND,
path.span,
TykindKind { suggestion: span },
);
}
- None => cx.emit_spanned_lint(USAGE_OF_TY_TYKIND, path.span, TykindDiag),
+ None => cx.emit_span_lint(USAGE_OF_TY_TYKIND, path.span, TykindDiag),
}
} else if !ty.span.from_expansion()
&& path.segments.len() > 1
&& let Some(ty) = is_ty_or_ty_ctxt(cx, path)
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
USAGE_OF_QUALIFIED_TY,
path.span,
TyQualified { ty, suggestion: path.span },
@@ -285,7 +285,7 @@ impl EarlyLintPass for LintPassImpl {
&& call_site.ctxt().outer_expn_data().kind
!= ExpnKind::Macro(MacroKind::Bang, sym::declare_lint_pass)
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
LINT_PASS_IMPL_WITHOUT_MACRO,
lint_pass.path.span,
LintPassByHand,
@@ -327,7 +327,7 @@ impl<'tcx> LateLintPass<'tcx> for ExistingDocKeyword {
if is_doc_keyword(keyword) {
return;
}
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
EXISTING_DOC_KEYWORD,
attr.span,
NonExistentDocKeyword { keyword },
@@ -405,7 +405,7 @@ impl LateLintPass<'_> for Diagnostics {
}
debug!(?found_impl);
if !found_parent_with_attr && !found_impl {
- cx.emit_spanned_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
+ cx.emit_span_lint(DIAGNOSTIC_OUTSIDE_OF_IMPL, span, DiagOutOfImpl);
}
let mut found_diagnostic_message = false;
@@ -421,7 +421,7 @@ impl LateLintPass<'_> for Diagnostics {
}
debug!(?found_diagnostic_message);
if !found_parent_with_attr && !found_diagnostic_message {
- cx.emit_spanned_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag);
+ cx.emit_span_lint(UNTRANSLATABLE_DIAGNOSTIC, span, UntranslatableDiag);
}
}
}
@@ -490,7 +490,7 @@ impl EarlyLintPass for Diagnostics {
}) {
return;
}
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNTRANSLATABLE_DIAGNOSTIC_TRIVIAL,
stmt.span,
UntranslatableDiagnosticTrivial,
@@ -528,7 +528,7 @@ impl LateLintPass<'_> for BadOptAccess {
&& let Some(lit) = item.lit()
&& let ast::LitKind::Str(val, _) = lit.kind
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
BAD_OPT_ACCESS,
expr.span,
BadOptAccessDiag { msg: val.as_str() },
@@ -553,7 +553,7 @@ impl<'tcx> LateLintPass<'tcx> for SpanUseEqCtxt {
expr.kind
{
if is_span_ctxt_call(cx, lhs) && is_span_ctxt_call(cx, rhs) {
- cx.emit_spanned_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
+ cx.emit_span_lint(SPAN_USE_EQ_CTXT, expr.span, SpanUseEqCtxtDiag);
}
}
}
diff --git a/compiler/rustc_lint/src/invalid_from_utf8.rs b/compiler/rustc_lint/src/invalid_from_utf8.rs
index 0b91b77a9f24..081e3e875302 100644
--- a/compiler/rustc_lint/src/invalid_from_utf8.rs
+++ b/compiler/rustc_lint/src/invalid_from_utf8.rs
@@ -78,7 +78,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
let valid_up_to = utf8_error.valid_up_to();
let is_unchecked_variant = diag_item.as_str().contains("unchecked");
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
if is_unchecked_variant {
INVALID_FROM_UTF8_UNCHECKED
} else {
@@ -111,7 +111,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidFromUtf8 {
.map(|e| match &e.kind {
ExprKind::Lit(Spanned { node: lit, .. }) => match lit {
LitKind::Byte(b) => Some(*b),
- LitKind::Int(b, _) => Some(*b as u8),
+ LitKind::Int(b, _) => Some(b.get() as u8),
_ => None,
},
_ => None,
diff --git a/compiler/rustc_lint/src/let_underscore.rs b/compiler/rustc_lint/src/let_underscore.rs
index bdace8e01f6c..c552b9832553 100644
--- a/compiler/rustc_lint/src/let_underscore.rs
+++ b/compiler/rustc_lint/src/let_underscore.rs
@@ -5,7 +5,7 @@ use crate::{
use rustc_errors::MultiSpan;
use rustc_hir as hir;
use rustc_middle::ty;
-use rustc_span::Symbol;
+use rustc_span::{sym, Symbol};
declare_lint! {
/// The `let_underscore_drop` lint checks for statements which don't bind
@@ -105,51 +105,66 @@ const SYNC_GUARD_SYMBOLS: [Symbol; 3] = [
impl<'tcx> LateLintPass<'tcx> for LetUnderscore {
fn check_local(&mut self, cx: &LateContext<'_>, local: &hir::Local<'_>) {
- if !matches!(local.pat.kind, hir::PatKind::Wild) {
- return;
- }
-
if matches!(local.source, rustc_hir::LocalSource::AsyncFn) {
return;
}
- if let Some(init) = local.init {
- let init_ty = cx.typeck_results().expr_ty(init);
- // If the type has a trivial Drop implementation, then it doesn't
- // matter that we drop the value immediately.
- if !init_ty.needs_drop(cx.tcx, cx.param_env) {
+
+ let mut top_level = true;
+
+ // We recursively walk through all patterns, so that we can catch cases where the lock is nested in a pattern.
+ // For the basic `let_underscore_drop` lint, we only look at the top level, since there are many legitimate reasons
+ // to bind a sub-pattern to an `_`, if we're only interested in the rest.
+ // But with locks, we prefer having the chance of "false positives" over missing cases, since the effects can be
+ // quite catastrophic.
+ local.pat.walk_always(|pat| {
+ let is_top_level = top_level;
+ top_level = false;
+
+ if !matches!(pat.kind, hir::PatKind::Wild) {
return;
}
- let is_sync_lock = match init_ty.kind() {
+
+ let ty = cx.typeck_results().pat_ty(pat);
+
+ // If the type has a trivial Drop implementation, then it doesn't
+ // matter that we drop the value immediately.
+ if !ty.needs_drop(cx.tcx, cx.param_env) {
+ return;
+ }
+ // Lint for patterns like `mutex.lock()`, which returns `Result` as well.
+ let potential_lock_type = match ty.kind() {
+ ty::Adt(adt, args) if cx.tcx.is_diagnostic_item(sym::Result, adt.did()) => {
+ args.type_at(0)
+ }
+ _ => ty,
+ };
+ let is_sync_lock = match potential_lock_type.kind() {
ty::Adt(adt, _) => SYNC_GUARD_SYMBOLS
.iter()
.any(|guard_symbol| cx.tcx.is_diagnostic_item(*guard_symbol, adt.did())),
_ => false,
};
+ let can_use_init = is_top_level.then_some(local.init).flatten();
+
let sub = NonBindingLetSub {
- suggestion: local.pat.span,
- multi_suggestion_start: local.span.until(init.span),
- multi_suggestion_end: init.span.shrink_to_hi(),
+ suggestion: pat.span,
+ // We can't suggest `drop()` when we're on the top level.
+ drop_fn_start_end: can_use_init
+ .map(|init| (local.span.until(init.span), init.span.shrink_to_hi())),
is_assign_desugar: matches!(local.source, rustc_hir::LocalSource::AssignDesugar(_)),
};
if is_sync_lock {
- let mut span = MultiSpan::from_spans(vec![local.pat.span, init.span]);
+ let mut span = MultiSpan::from_span(pat.span);
span.push_span_label(
- local.pat.span,
+ pat.span,
"this lock is not assigned to a binding and is immediately dropped".to_string(),
);
- span.push_span_label(
- init.span,
- "this binding will immediately drop the value assigned to it".to_string(),
- );
- cx.emit_spanned_lint(LET_UNDERSCORE_LOCK, span, NonBindingLet::SyncLock { sub });
- } else {
- cx.emit_spanned_lint(
- LET_UNDERSCORE_DROP,
- local.span,
- NonBindingLet::DropType { sub },
- );
+ cx.emit_span_lint(LET_UNDERSCORE_LOCK, span, NonBindingLet::SyncLock { sub });
+ // Only emit let_underscore_drop for top-level `_` patterns.
+ } else if can_use_init.is_some() {
+ cx.emit_span_lint(LET_UNDERSCORE_DROP, local.span, NonBindingLet::DropType { sub });
}
- }
+ });
}
}
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index b98b1a2935c0..d37f0c151714 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -24,7 +24,7 @@ use rustc_hir::HirId;
use rustc_index::IndexVec;
use rustc_middle::hir::nested_filter;
use rustc_middle::lint::{
- reveal_actual_level, struct_lint_level, LevelAndSource, LintExpectation, LintLevelSource,
+ lint_level, reveal_actual_level, LevelAndSource, LintExpectation, LintLevelSource,
ShallowLintLevelMap,
};
use rustc_middle::query::Providers;
@@ -682,7 +682,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
sub,
});
} else {
- self.emit_spanned_lint(
+ self.emit_span_lint(
FORBIDDEN_LINT_GROUPS,
src.span().into(),
OverruledAttributeLint {
@@ -925,7 +925,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
}
Err((Some(ids), ref new_lint_name)) => {
let lint = builtin::RENAMED_AND_REMOVED_LINTS;
- self.emit_spanned_lint(
+ self.emit_span_lint(
lint,
sp.into(),
DeprecatedLintName {
@@ -976,13 +976,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
RenamedLintSuggestion::WithSpan { suggestion: sp, replace };
let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
let lint = RenamedLint { name: name.as_str(), suggestion };
- self.emit_spanned_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
+ self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
}
CheckLintNameResult::Removed(ref reason) => {
let name = tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
let lint = RemovedLint { name: name.as_str(), reason };
- self.emit_spanned_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
+ self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
}
CheckLintNameResult::NoLint(suggestion) => {
@@ -995,7 +995,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
UnknownLintSuggestion::WithSpan { suggestion: sp, replace, from_rustc }
});
let lint = UnknownLint { name, suggestion };
- self.emit_spanned_lint(UNKNOWN_LINTS, sp.into(), lint);
+ self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint);
}
}
// If this lint was renamed, apply the new lint instead of ignoring the attribute.
@@ -1041,7 +1041,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
continue;
};
- self.emit_spanned_lint(
+ self.emit_span_lint(
UNUSED_ATTRIBUTES,
lint_attr_span.into(),
IgnoredUnlessCrateSpecified { level: level.as_str(), name: lint_attr_name },
@@ -1062,7 +1062,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
if self.lint_added_lints {
let lint = builtin::UNKNOWN_LINTS;
let (level, src) = self.lint_level(builtin::UNKNOWN_LINTS);
- struct_lint_level(
+ lint_level(
self.sess,
lint,
level,
@@ -1096,10 +1096,10 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
/// Used to emit a lint-related diagnostic based on the current state of
/// this lint context.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
- pub(crate) fn struct_lint(
+ pub(crate) fn opt_span_lint(
&self,
lint: &'static Lint,
span: Option,
@@ -1107,18 +1107,18 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
let (level, src) = self.lint_level(lint);
- struct_lint_level(self.sess, lint, level, src, span, msg, decorate)
+ lint_level(self.sess, lint, level, src, span, msg, decorate)
}
#[track_caller]
- pub fn emit_spanned_lint(
+ pub fn emit_span_lint(
&self,
lint: &'static Lint,
span: MultiSpan,
decorate: impl for<'a> DecorateLint<'a, ()>,
) {
let (level, src) = self.lint_level(lint);
- struct_lint_level(self.sess, lint, level, src, Some(span), decorate.msg(), |lint| {
+ lint_level(self.sess, lint, level, src, Some(span), decorate.msg(), |lint| {
decorate.decorate_lint(lint);
});
}
@@ -1126,7 +1126,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
#[track_caller]
pub fn emit_lint(&self, lint: &'static Lint, decorate: impl for<'a> DecorateLint<'a, ()>) {
let (level, src) = self.lint_level(lint);
- struct_lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
+ lint_level(self.sess, lint, level, src, None, decorate.msg(), |lint| {
decorate.decorate_lint(lint);
});
}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index a9996e4a155b..b5798af75536 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -35,6 +35,7 @@
#![feature(iter_intersperse)]
#![feature(iter_order_by)]
#![feature(let_chains)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
#![feature(min_specialization)]
#![feature(never_type)]
#![feature(rustc_attrs)]
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 73db5790c2b3..e19bb1cb62f5 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -532,7 +532,6 @@ pub enum BuiltinSpecialModuleNameUsed {
// deref_into_dyn_supertrait.rs
#[derive(LintDiagnostic)]
#[diag(lint_supertrait_as_deref_target)]
-#[help]
pub struct SupertraitAsDerefTarget<'a> {
pub self_ty: Ty<'a>,
pub supertrait_principal: PolyExistentialTraitRef<'a>,
@@ -930,8 +929,7 @@ pub enum NonBindingLet {
pub struct NonBindingLetSub {
pub suggestion: Span,
- pub multi_suggestion_start: Span,
- pub multi_suggestion_end: Span,
+ pub drop_fn_start_end: Option<(Span, Span)>,
pub is_assign_desugar: bool,
}
@@ -940,21 +938,31 @@ impl AddToDiagnostic for NonBindingLetSub {
where
F: Fn(&mut Diagnostic, SubdiagnosticMessage) -> SubdiagnosticMessage,
{
- let prefix = if self.is_assign_desugar { "let " } else { "" };
- diag.span_suggestion_verbose(
- self.suggestion,
- fluent::lint_non_binding_let_suggestion,
- format!("{prefix}_unused"),
- Applicability::MachineApplicable,
- );
- diag.multipart_suggestion(
- fluent::lint_non_binding_let_multi_suggestion,
- vec![
- (self.multi_suggestion_start, "drop(".to_string()),
- (self.multi_suggestion_end, ")".to_string()),
- ],
- Applicability::MachineApplicable,
- );
+ let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar;
+
+ if can_suggest_binding {
+ let prefix = if self.is_assign_desugar { "let " } else { "" };
+ diag.span_suggestion_verbose(
+ self.suggestion,
+ fluent::lint_non_binding_let_suggestion,
+ format!("{prefix}_unused"),
+ Applicability::MachineApplicable,
+ );
+ } else {
+ diag.span_help(self.suggestion, fluent::lint_non_binding_let_suggestion);
+ }
+ if let Some(drop_fn_start_end) = self.drop_fn_start_end {
+ diag.multipart_suggestion(
+ fluent::lint_non_binding_let_multi_suggestion,
+ vec![
+ (drop_fn_start_end.0, "drop(".to_string()),
+ (drop_fn_start_end.1, ")".to_string()),
+ ],
+ Applicability::MachineApplicable,
+ );
+ } else {
+ diag.help(fluent::lint_non_binding_let_multi_drop_fn);
+ }
}
}
@@ -1099,7 +1107,10 @@ pub struct IdentifierNonAsciiChar;
#[derive(LintDiagnostic)]
#[diag(lint_identifier_uncommon_codepoints)]
-pub struct IdentifierUncommonCodepoints;
+pub struct IdentifierUncommonCodepoints {
+ pub codepoints: Vec,
+ pub codepoints_len: usize,
+}
#[derive(LintDiagnostic)]
#[diag(lint_confusable_identifier_pair)]
diff --git a/compiler/rustc_lint/src/map_unit_fn.rs b/compiler/rustc_lint/src/map_unit_fn.rs
index 7c692fee3338..07980cfb6fa0 100644
--- a/compiler/rustc_lint/src/map_unit_fn.rs
+++ b/compiler/rustc_lint/src/map_unit_fn.rs
@@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
let fn_ty = cx.tcx.fn_sig(id).skip_binder();
let ret_ty = fn_ty.output().skip_binder();
if is_unit_type(ret_ty) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
MAP_UNIT_FN,
span,
MappingToUnit {
@@ -80,7 +80,7 @@ impl<'tcx> LateLintPass<'tcx> for MapUnitFn {
let cl_ty = subs.as_closure().sig();
let ret_ty = cl_ty.output().skip_binder();
if is_unit_type(ret_ty) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
MAP_UNIT_FN,
span,
MappingToUnit {
diff --git a/compiler/rustc_lint/src/methods.rs b/compiler/rustc_lint/src/methods.rs
index 5b63b19c53c8..9cfdaf0ce2ff 100644
--- a/compiler/rustc_lint/src/methods.rs
+++ b/compiler/rustc_lint/src/methods.rs
@@ -57,7 +57,7 @@ fn lint_cstring_as_ptr(
if cx.tcx.is_diagnostic_item(sym::Result, def.did()) {
if let ty::Adt(adt, _) = args.type_at(0).kind() {
if cx.tcx.is_diagnostic_item(sym::cstring_type, adt.did()) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
TEMPORARY_CSTRING_AS_PTR,
as_ptr_span,
CStringPtr { as_ptr: as_ptr_span, unwrap: unwrap.span },
diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
index dfefaf82fd7d..69d623b547b5 100644
--- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
+++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs
@@ -49,7 +49,7 @@ impl<'tcx> LateLintPass<'tcx> for MultipleSupertraitUpcastable {
.into_iter()
.filter_map(|(pred, _)| pred.as_trait_clause());
if direct_super_traits_iter.count() > 1 {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
MULTIPLE_SUPERTRAIT_UPCASTABLE,
cx.tcx.def_span(def_id),
crate::lints::MultipleSupertraitUpcastable { ident: item.ident },
diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs
index 3405dd3a9169..f78b32ce5e77 100644
--- a/compiler/rustc_lint/src/non_ascii_idents.rs
+++ b/compiler/rustc_lint/src/non_ascii_idents.rs
@@ -186,11 +186,21 @@ impl EarlyLintPass for NonAsciiIdents {
continue;
}
has_non_ascii_idents = true;
- cx.emit_spanned_lint(NON_ASCII_IDENTS, sp, IdentifierNonAsciiChar);
+ cx.emit_span_lint(NON_ASCII_IDENTS, sp, IdentifierNonAsciiChar);
if check_uncommon_codepoints
&& !symbol_str.chars().all(GeneralSecurityProfile::identifier_allowed)
{
- cx.emit_spanned_lint(UNCOMMON_CODEPOINTS, sp, IdentifierUncommonCodepoints);
+ let codepoints: Vec<_> = symbol_str
+ .chars()
+ .filter(|c| !GeneralSecurityProfile::identifier_allowed(*c))
+ .collect();
+ let codepoints_len = codepoints.len();
+
+ cx.emit_span_lint(
+ UNCOMMON_CODEPOINTS,
+ sp,
+ IdentifierUncommonCodepoints { codepoints, codepoints_len },
+ );
}
}
@@ -218,7 +228,7 @@ impl EarlyLintPass for NonAsciiIdents {
.entry(skeleton_sym)
.and_modify(|(existing_symbol, existing_span, existing_is_ascii)| {
if !*existing_is_ascii || !is_ascii {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
CONFUSABLE_IDENTS,
sp,
ConfusableIdentifierPair {
@@ -339,7 +349,7 @@ impl EarlyLintPass for NonAsciiIdents {
let char_info = format!("'{}' (U+{:04X})", ch, ch as u32);
includes += &char_info;
}
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
MIXED_SCRIPT_CONFUSABLES,
sp,
MixedScriptConfusables { set: script_set.to_string(), includes },
diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs
index 479acd88d718..ebef77f68797 100644
--- a/compiler/rustc_lint/src/non_fmt_panic.rs
+++ b/compiler/rustc_lint/src/non_fmt_panic.rs
@@ -121,7 +121,7 @@ fn check_panic<'tcx>(cx: &LateContext<'tcx>, f: &'tcx hir::Expr<'tcx>, arg: &'tc
}
#[allow(rustc::diagnostic_outside_of_impl)]
- cx.struct_span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
+ cx.span_lint(NON_FMT_PANICS, arg_span, fluent::lint_non_fmt_panic, |lint| {
lint.arg("name", symbol);
lint.note(fluent::lint_note);
lint.note(fluent::lint_more_info_note);
@@ -251,7 +251,7 @@ fn check_panic_str<'tcx>(
.map(|span| fmt_span.from_inner(InnerSpan::new(span.start, span.end)))
.collect(),
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NON_FMT_PANICS,
arg_spans,
NonFmtPanicUnused {
@@ -268,7 +268,7 @@ fn check_panic_str<'tcx>(
.collect()
});
let count = brace_spans.as_ref().map(|v| v.len()).unwrap_or(/* any number >1 */ 2);
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NON_FMT_PANICS,
brace_spans.unwrap_or_else(|| vec![span]),
NonFmtPanicBraces {
diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs
index 59f27a88aec6..05b39829a12f 100644
--- a/compiler/rustc_lint/src/nonstandard_style.rs
+++ b/compiler/rustc_lint/src/nonstandard_style.rs
@@ -150,7 +150,7 @@ impl NonCamelCaseTypes {
} else {
NonCamelCaseTypeSub::Label { span: ident.span }
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NON_CAMEL_CASE_TYPES,
ident.span,
NonCamelCaseType { sort, name, sub },
@@ -320,7 +320,7 @@ impl NonSnakeCase {
} else {
NonSnakeCaseDiagSub::Label { span }
};
- cx.emit_spanned_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sc, sub });
+ cx.emit_span_lint(NON_SNAKE_CASE, span, NonSnakeCaseDiag { sort, name, sc, sub });
}
}
}
@@ -481,7 +481,7 @@ impl NonUpperCaseGlobals {
} else {
NonUpperCaseGlobalSub::Label { span: ident.span }
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NON_UPPER_CASE_GLOBALS,
ident.span,
NonUpperCaseGlobal { sort, name, sub },
diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs
index cfbca6efbfa5..26c5e4fb4837 100644
--- a/compiler/rustc_lint/src/noop_method_call.rs
+++ b/compiler/rustc_lint/src/noop_method_call.rs
@@ -121,7 +121,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
let orig_ty = expr_ty.peel_refs();
if receiver_ty == expr_ty {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
NOOP_METHOD_CALL,
span,
NoopMethodCallDiag { method: call.ident.name, orig_ty, trait_, label: span },
@@ -131,12 +131,12 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
// If `type_of(x) == T` and `x.borrow()` is used to get `&T`,
// then that should be allowed
sym::noop_method_borrow => return,
- sym::noop_method_clone => cx.emit_spanned_lint(
+ sym::noop_method_clone => cx.emit_span_lint(
SUSPICIOUS_DOUBLE_REF_OP,
span,
SuspiciousDoubleRefCloneDiag { ty: expr_ty },
),
- sym::noop_method_deref => cx.emit_spanned_lint(
+ sym::noop_method_deref => cx.emit_span_lint(
SUSPICIOUS_DOUBLE_REF_OP,
span,
SuspiciousDoubleRefDerefDiag { ty: expr_ty },
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 44b23b8bdc0c..f64509fe8bc6 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
}),
_ => None,
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OPAQUE_HIDDEN_INFERRED_BOUND,
pred_span,
OpaqueHiddenInferredBoundLint {
diff --git a/compiler/rustc_lint/src/pass_by_value.rs b/compiler/rustc_lint/src/pass_by_value.rs
index fce750c9b558..160d42caa9e2 100644
--- a/compiler/rustc_lint/src/pass_by_value.rs
+++ b/compiler/rustc_lint/src/pass_by_value.rs
@@ -29,7 +29,7 @@ impl<'tcx> LateLintPass<'tcx> for PassByValue {
}
}
if let Some(t) = path_for_pass_by_value(cx, inner_ty) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
PASS_BY_VALUE,
ty.span,
PassByValueDiag { ty: t, suggestion: ty.span },
diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs
index 4ac8a5ceb855..8038115ef51c 100644
--- a/compiler/rustc_lint/src/ptr_nulls.rs
+++ b/compiler/rustc_lint/src/ptr_nulls.rs
@@ -97,7 +97,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
)
&& let Some(diag) = incorrect_check(cx, arg) =>
{
- cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
+ cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
}
// Catching:
@@ -110,7 +110,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
)
&& let Some(diag) = incorrect_check(cx, receiver) =>
{
- cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
+ cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
}
ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
@@ -134,7 +134,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
&& let LitKind::Int(v, _) = spanned.node
&& v == 0 =>
{
- cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
+ cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
}
// Catching:
@@ -145,7 +145,7 @@ impl<'tcx> LateLintPass<'tcx> for PtrNullChecks {
&& let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
&& (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut) =>
{
- cx.emit_spanned_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
+ cx.emit_span_lint(USELESS_PTR_NULL_CHECKS, expr.span, diag)
}
_ => {}
diff --git a/compiler/rustc_lint/src/redundant_semicolon.rs b/compiler/rustc_lint/src/redundant_semicolon.rs
index 9a8b14b4907e..1681ac2f1e5a 100644
--- a/compiler/rustc_lint/src/redundant_semicolon.rs
+++ b/compiler/rustc_lint/src/redundant_semicolon.rs
@@ -47,7 +47,7 @@ fn maybe_lint_redundant_semis(cx: &EarlyContext<'_>, seq: &mut Option<(Span, boo
return;
}
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
REDUNDANT_SEMICOLONS,
span,
RedundantSemicolonsDiag { multiple, suggestion: span },
diff --git a/compiler/rustc_lint/src/reference_casting.rs b/compiler/rustc_lint/src/reference_casting.rs
index 96290288f072..9e6cca853178 100644
--- a/compiler/rustc_lint/src/reference_casting.rs
+++ b/compiler/rustc_lint/src/reference_casting.rs
@@ -47,7 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for InvalidReferenceCasting {
let orig_cast = if init.span != e.span { Some(init.span) } else { None };
let ty_has_interior_mutability = ty_has_interior_mutability.then_some(());
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
INVALID_REFERENCE_CASTING,
expr.span,
if pat == PatternKind::Assign {
diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs
index e812493b3dd3..789f154eac5b 100644
--- a/compiler/rustc_lint/src/traits.rs
+++ b/compiler/rustc_lint/src/traits.rs
@@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
continue;
}
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
DROP_BOUNDS,
span,
DropTraitConstraintsDiag { predicate, tcx: cx.tcx, def_id },
@@ -116,7 +116,7 @@ impl<'tcx> LateLintPass<'tcx> for DropTraitConstraints {
let def_id = bound.trait_ref.trait_def_id();
if cx.tcx.lang_items().drop_trait() == def_id {
let Some(def_id) = cx.tcx.get_diagnostic_item(sym::needs_drop) else { return };
- cx.emit_spanned_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
+ cx.emit_span_lint(DYN_DROP, bound.span, DropGlue { tcx: cx.tcx, def_id });
}
}
}
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index a86fe2db2b2d..e3d3150b36ef 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -254,7 +254,7 @@ fn lint_overflowing_range_endpoint<'tcx>(
}
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OVERFLOWING_LITERALS,
struct_expr.span,
RangeEndpointOutOfRange { ty, sub: sub_sugg },
@@ -371,7 +371,7 @@ fn report_bin_hex_error(
})
.flatten();
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OVERFLOWING_LITERALS,
expr.span,
OverflowingBinHex {
@@ -473,7 +473,7 @@ fn lint_int_literal<'tcx>(
let help = get_type_suggestion(cx.typeck_results().node_type(e.hir_id), v, negative)
.map(|suggestion_ty| OverflowingIntHelp { suggestion_ty });
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OVERFLOWING_LITERALS,
span,
OverflowingInt { ty: t.name_str(), lit, min, max, help },
@@ -492,7 +492,7 @@ fn lint_uint_literal<'tcx>(
let lit_val: u128 = match lit.node {
// _v is u8, within range by definition
ast::LitKind::Byte(_v) => return,
- ast::LitKind::Int(v, _) => v,
+ ast::LitKind::Int(v, _) => v.get(),
_ => bug!(),
};
if lit_val < min || lit_val > max {
@@ -501,7 +501,7 @@ fn lint_uint_literal<'tcx>(
match par_e.kind {
hir::ExprKind::Cast(..) => {
if let ty::Char = cx.typeck_results().expr_ty(par_e).kind() {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OVERFLOWING_LITERALS,
par_e.span,
OnlyCastu8ToChar { span: par_e.span, literal: lit_val },
@@ -528,7 +528,7 @@ fn lint_uint_literal<'tcx>(
);
return;
}
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OVERFLOWING_LITERALS,
e.span,
OverflowingUInt {
@@ -555,7 +555,7 @@ fn lint_literal<'tcx>(
ty::Int(t) => {
match lit.node {
ast::LitKind::Int(v, ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed) => {
- lint_int_literal(cx, type_limits, e, lit, t, v)
+ lint_int_literal(cx, type_limits, e, lit, t, v.get())
}
_ => bug!(),
};
@@ -570,7 +570,7 @@ fn lint_literal<'tcx>(
_ => bug!(),
};
if is_infinite == Ok(true) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
OVERFLOWING_LITERALS,
e.span,
OverflowingLiteral {
@@ -654,7 +654,7 @@ fn lint_nan<'tcx>(
_ => return,
};
- cx.emit_spanned_lint(INVALID_NAN_COMPARISONS, e.span, lint);
+ cx.emit_span_lint(INVALID_NAN_COMPARISONS, e.span, lint);
}
fn lint_wide_pointer<'tcx>(
@@ -700,7 +700,7 @@ fn lint_wide_pointer<'tcx>(
let (Some(l_span), Some(r_span)) =
(l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span))
else {
- return cx.emit_spanned_lint(
+ return cx.emit_span_lint(
AMBIGUOUS_WIDE_POINTER_COMPARISONS,
e.span,
AmbiguousWidePointerComparisons::Spanless,
@@ -718,7 +718,7 @@ fn lint_wide_pointer<'tcx>(
let deref_left = &*"*".repeat(l_ty_refs);
let deref_right = &*"*".repeat(r_ty_refs);
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
AMBIGUOUS_WIDE_POINTER_COMPARISONS,
e.span,
AmbiguousWidePointerComparisons::Spanful {
@@ -770,7 +770,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
hir::ExprKind::Binary(binop, ref l, ref r) => {
if is_comparison(binop) {
if !check_limits(cx, binop, l, r) {
- cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
+ cx.emit_span_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
} else {
lint_nan(cx, e, binop, l, r);
lint_wide_pointer(cx, e, binop.node, l, r);
@@ -842,7 +842,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
ast::LitKind::Int(
v,
ast::LitIntType::Signed(_) | ast::LitIntType::Unsuffixed,
- ) => v as i128,
+ ) => v.get() as i128,
_ => return true,
},
_ => bug!(),
@@ -853,7 +853,7 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
let (min, max): (u128, u128) = uint_ty_range(uint_ty);
let lit_val: u128 = match lit.kind {
hir::ExprKind::Lit(li) => match li.node {
- ast::LitKind::Int(v, _) => v,
+ ast::LitKind::Int(v, _) => v.get(),
_ => return true,
},
_ => bug!(),
@@ -1464,7 +1464,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
} else {
None
};
- self.cx.emit_spanned_lint(
+ self.cx.emit_span_lint(
lint,
sp,
ImproperCTypes { ty, desc, label: sp, help, note, span_note },
@@ -1792,7 +1792,7 @@ impl<'tcx> LateLintPass<'tcx> for VariantSizeDifferences {
// We only warn if the largest variant is at least thrice as large as
// the second-largest.
if largest > slargest * 3 && slargest > 0 {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
VARIANT_SIZE_DIFFERENCES,
enum_definition.variants[largest_index].span,
VariantSizeDifferencesDiag { largest },
@@ -1913,17 +1913,9 @@ impl InvalidAtomicOrdering {
&& (ordering == invalid_ordering || ordering == sym::AcqRel)
{
if method == sym::load {
- cx.emit_spanned_lint(
- INVALID_ATOMIC_ORDERING,
- ordering_arg.span,
- AtomicOrderingLoad,
- );
+ cx.emit_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, AtomicOrderingLoad);
} else {
- cx.emit_spanned_lint(
- INVALID_ATOMIC_ORDERING,
- ordering_arg.span,
- AtomicOrderingStore,
- );
+ cx.emit_span_lint(INVALID_ATOMIC_ORDERING, ordering_arg.span, AtomicOrderingStore);
};
}
}
@@ -1935,7 +1927,7 @@ impl InvalidAtomicOrdering {
&& matches!(cx.tcx.get_diagnostic_name(def_id), Some(sym::fence | sym::compiler_fence))
&& Self::match_ordering(cx, &args[0]) == Some(sym::Relaxed)
{
- cx.emit_spanned_lint(INVALID_ATOMIC_ORDERING, args[0].span, AtomicOrderingFence);
+ cx.emit_span_lint(INVALID_ATOMIC_ORDERING, args[0].span, AtomicOrderingFence);
}
}
@@ -1957,7 +1949,7 @@ impl InvalidAtomicOrdering {
let Some(fail_ordering) = Self::match_ordering(cx, fail_order_arg) else { return };
if matches!(fail_ordering, sym::Release | sym::AcqRel) {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
INVALID_ATOMIC_ORDERING,
fail_order_arg.span,
InvalidAtomicOrderingDiag { method, fail_order_arg_span: fail_order_arg.span },
diff --git a/compiler/rustc_lint/src/unit_bindings.rs b/compiler/rustc_lint/src/unit_bindings.rs
index c80889f3ae75..b74430d8fa09 100644
--- a/compiler/rustc_lint/src/unit_bindings.rs
+++ b/compiler/rustc_lint/src/unit_bindings.rs
@@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for UnitBindings {
&& !matches!(init.kind, hir::ExprKind::Tup([]))
&& !matches!(local.pat.kind, hir::PatKind::Tuple([], ..))
{
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNIT_BINDINGS,
local.span,
UnitBindingsDiag { label: local.pat.span },
diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs
index 39decf1faabf..ea3747dfac4b 100644
--- a/compiler/rustc_lint/src/unused.rs
+++ b/compiler/rustc_lint/src/unused.rs
@@ -182,7 +182,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
let mut op_warned = false;
if let Some(must_use_op) = must_use_op {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNUSED_MUST_USE,
expr.span,
UnusedOp {
@@ -202,7 +202,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
}
if !(type_lint_emitted_or_suppressed || fn_warned || op_warned) {
- cx.emit_spanned_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
+ cx.emit_span_lint(UNUSED_RESULTS, s.span, UnusedResult { ty });
}
fn check_fn_must_use(
@@ -494,21 +494,21 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults {
);
}
MustUsePath::Closure(span) => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNUSED_MUST_USE,
*span,
UnusedClosure { count: plural_len, pre: descr_pre, post: descr_post },
);
}
MustUsePath::Coroutine(span) => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNUSED_MUST_USE,
*span,
UnusedCoroutine { count: plural_len, pre: descr_pre, post: descr_post },
);
}
MustUsePath::Def(span, def_id, reason) => {
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNUSED_MUST_USE,
*span,
UnusedDef {
@@ -568,9 +568,9 @@ impl<'tcx> LateLintPass<'tcx> for PathStatements {
} else {
PathStatementDropSub::Help { span: s.span }
};
- cx.emit_spanned_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
+ cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementDrop { sub })
} else {
- cx.emit_spanned_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
+ cx.emit_span_lint(PATH_STATEMENTS, s.span, PathStatementNoEffect);
}
}
}
@@ -824,7 +824,7 @@ trait UnusedDelimLint {
end_replace: hi_replace,
}
});
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
self.lint(),
primary_span,
UnusedDelim { delim: Self::DELIM_STR, item: msg, suggestion },
@@ -1507,7 +1507,7 @@ impl UnusedImportBraces {
ast::UseTreeKind::Nested(_) => return,
};
- cx.emit_spanned_lint(
+ cx.emit_span_lint(
UNUSED_IMPORT_BRACES,
item.span,
UnusedImportBracesDiag { node: node_name },
@@ -1564,10 +1564,10 @@ impl<'tcx> LateLintPass<'tcx> for UnusedAllocation {
if let adjustment::Adjust::Borrow(adjustment::AutoBorrow::Ref(_, m)) = adj.kind {
match m {
adjustment::AutoBorrowMutability::Not => {
- cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
+ cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationDiag);
}
adjustment::AutoBorrowMutability::Mut { .. } => {
- cx.emit_spanned_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
+ cx.emit_span_lint(UNUSED_ALLOCATION, e.span, UnusedAllocationMutDiag);
}
};
}
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e917e7cb02b3..e6d837ecd92b 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -2755,6 +2755,11 @@ declare_lint! {
pub UNSAFE_OP_IN_UNSAFE_FN,
Allow,
"unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
+ @future_incompatible = FutureIncompatibleInfo {
+ reason: FutureIncompatibilityReason::EditionSemanticsChange(Edition::Edition2024),
+ reference: "issue #71668 ",
+ explain_reason: false
+ };
@edition Edition2024 => Warn;
}
@@ -4604,3 +4609,50 @@ declare_lint! {
reference: "issue #X ",
};
}
+
+declare_lint! {
+ /// The `private_macro_use` lint detects private macros that are imported
+ /// with `#[macro_use]`.
+ ///
+ /// ### Example
+ ///
+ /// ```rust,ignore (needs extern crate)
+ /// // extern_macro.rs
+ /// macro_rules! foo_ { () => {}; }
+ /// use foo_ as foo;
+ ///
+ /// // code.rs
+ ///
+ /// #![deny(private_macro_use)]
+ ///
+ /// #[macro_use]
+ /// extern crate extern_macro;
+ ///
+ /// fn main() {
+ /// foo!();
+ /// }
+ /// ```
+ ///
+ /// This will produce:
+ ///
+ /// ```text
+ /// error: cannot find macro `foo` in this scope
+ /// ```
+ ///
+ /// ### Explanation
+ ///
+ /// This lint arises from overlooking visibility checks for macros
+ /// in an external crate.
+ ///
+ /// This is a [future-incompatible] lint to transition this to a
+ /// hard error in the future.
+ ///
+ /// [future-incompatible]: ../index.md#future-incompatible-lints
+ pub PRIVATE_MACRO_USE,
+ Warn,
+ "detects certain macro bindings that should not be re-exported",
+ @future_incompatible = FutureIncompatibleInfo {
+ reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
+ reference: "issue #120192 ",
+ };
+}
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index d3a4e7ba7d19..135b9e32fe7e 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -90,7 +90,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
/// Then, later, to emit the error:
///
/// ```ignore (rust)
-/// cx.struct_span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
+/// cx.span_lint(INVALID_ATOMIC_ORDERING, fail_order_arg_span, AtomicOrderingInvalidLint {
/// method,
/// success_ordering,
/// fail_ordering,
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 3475e582a8f2..dec3419819ff 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -49,6 +49,7 @@
#![feature(associated_type_bounds)]
#![feature(rustc_attrs)]
#![feature(control_flow_enum)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
#![feature(trusted_step)]
#![feature(try_blocks)]
#![feature(try_reserve_kind)]
diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs
index 4ab16cf19ba9..6ffa0819f357 100644
--- a/compiler/rustc_middle/src/lint.rs
+++ b/compiler/rustc_middle/src/lint.rs
@@ -247,18 +247,18 @@ pub fn explain_lint_level_source(
///
/// If you are looking to implement a lint, look for higher level functions,
/// for example:
-/// - [`TyCtxt::emit_spanned_lint`]
-/// - [`TyCtxt::struct_span_lint_hir`]
-/// - [`TyCtxt::emit_lint`]
-/// - [`TyCtxt::struct_lint_node`]
-/// - `LintContext::lookup`
+/// - [`TyCtxt::emit_node_span_lint`]
+/// - [`TyCtxt::node_span_lint`]
+/// - [`TyCtxt::emit_node_lint`]
+/// - [`TyCtxt::node_lint`]
+/// - `LintContext::opt_span_lint`
///
/// ## `decorate`
///
/// It is not intended to call `emit`/`cancel` on the `DiagnosticBuilder` passed
/// in the `decorate` callback.
#[track_caller]
-pub fn struct_lint_level(
+pub fn lint_level(
sess: &Session,
lint: &'static Lint,
level: Level,
@@ -270,7 +270,7 @@ pub fn struct_lint_level(
// Avoid codegen bloat from monomorphization by immediately doing dyn dispatch of `decorate` to
// the "real" work.
#[track_caller]
- fn struct_lint_level_impl(
+ fn lint_level_impl(
sess: &Session,
lint: &'static Lint,
level: Level,
@@ -399,7 +399,7 @@ pub fn struct_lint_level(
explain_lint_level_source(lint, level, src, &mut *err);
err.emit()
}
- struct_lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
+ lint_level_impl(sess, lint, level, src, span, msg, Box::new(decorate))
}
/// Returns whether `span` originates in a foreign crate's external macro.
diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs
index efe7bdfa06db..afb6937b43b9 100644
--- a/compiler/rustc_middle/src/middle/stability.rs
+++ b/compiler/rustc_middle/src/middle/stability.rs
@@ -217,7 +217,7 @@ fn late_report_deprecation(
return;
}
let method_span = method_span.unwrap_or(span);
- tcx.struct_span_lint_hir(lint, hir_id, method_span, message, |diag| {
+ tcx.node_span_lint(lint, hir_id, method_span, message, |diag| {
if let hir::Node::Expr(_) = tcx.hir_node(hir_id) {
let kind = tcx.def_descr(def_id);
deprecation_suggestion(diag, kind, suggestion, method_span);
@@ -585,7 +585,7 @@ impl<'tcx> TyCtxt<'tcx> {
unmarked: impl FnOnce(Span, DefId),
) -> bool {
let soft_handler = |lint, span, msg: String| {
- self.struct_span_lint_hir(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |_| {})
+ self.node_span_lint(lint, id.unwrap_or(hir::CRATE_HIR_ID), span, msg, |_| {})
};
let eval_result =
self.eval_stability_allow_unstable(def_id, id, span, method_span, allow_unstable);
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 2c38f998c959..9731d86fb17c 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -195,7 +195,7 @@ impl<'tcx> ConstValue<'tcx> {
/// Constants
#[derive(Clone, Copy, PartialEq, Eq, TyEncodable, TyDecodable, Hash, HashStable, Debug)]
-#[derive(TypeFoldable, TypeVisitable)]
+#[derive(TypeFoldable, TypeVisitable, Lift)]
pub enum Const<'tcx> {
/// This constant came from the type system.
///
@@ -456,7 +456,7 @@ impl<'tcx> Const<'tcx> {
/// An unevaluated (potentially generic) constant used in MIR.
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
-#[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
+#[derive(Hash, HashStable, TypeFoldable, TypeVisitable, Lift)]
pub struct UnevaluatedConst<'tcx> {
pub def: DefId,
pub args: GenericArgsRef<'tcx>,
diff --git a/compiler/rustc_middle/src/mir/interpret/queries.rs b/compiler/rustc_middle/src/mir/interpret/queries.rs
index b20df1b23434..5f9e7f6e3685 100644
--- a/compiler/rustc_middle/src/mir/interpret/queries.rs
+++ b/compiler/rustc_middle/src/mir/interpret/queries.rs
@@ -108,7 +108,7 @@ impl<'tcx> TyCtxt<'tcx> {
let mir_body = self.mir_for_ctfe(instance.def_id());
if mir_body.is_polymorphic {
let Some(local_def_id) = ct.def.as_local() else { return };
- self.struct_span_lint_hir(
+ self.node_span_lint(
lint::builtin::CONST_EVALUATABLE_UNCHECKED,
self.local_def_id_to_hir_id(local_def_id),
self.def_span(ct.def),
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index 624ae8c22f9d..36f5ba161d5f 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1672,19 +1672,13 @@ mod size_asserts {
use super::*;
use rustc_data_structures::static_assert_size;
// tidy-alphabetical-start
- // This can be removed after i128:128 is in the bootstrap compiler's target.
- #[cfg(not(bootstrap))]
- static_assert_size!(BasicBlockData<'_>, 144);
+ static_assert_size!(BasicBlockData<'_>, 136);
static_assert_size!(LocalDecl<'_>, 40);
static_assert_size!(SourceScopeData<'_>, 72);
static_assert_size!(Statement<'_>, 32);
static_assert_size!(StatementKind<'_>, 16);
- // This can be removed after i128:128 is in the bootstrap compiler's target.
- #[cfg(not(bootstrap))]
- static_assert_size!(Terminator<'_>, 112);
- // This can be removed after i128:128 is in the bootstrap compiler's target.
- #[cfg(not(bootstrap))]
- static_assert_size!(TerminatorKind<'_>, 96);
+ static_assert_size!(Terminator<'_>, 104);
+ static_assert_size!(TerminatorKind<'_>, 88);
static_assert_size!(VarDebugInfo<'_>, 88);
// tidy-alphabetical-end
}
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 6ebe57e29da2..a5c229879a74 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -13,6 +13,7 @@ use crate::ty::{self, List, Ty};
use crate::ty::{Region, UserTypeAnnotationIndex};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
+use rustc_data_structures::packed::Pu128;
use rustc_hir::def_id::DefId;
use rustc_hir::{self, CoroutineKind};
use rustc_index::IndexVec;
@@ -829,7 +830,7 @@ impl TerminatorKind<'_> {
pub struct SwitchTargets {
/// Possible values. The locations to branch to in each case
/// are found in the corresponding indices from the `targets` vector.
- pub(super) values: SmallVec<[u128; 1]>,
+ pub(super) values: SmallVec<[Pu128; 1]>,
/// Possible branch sites. The last element of this vector is used
/// for the otherwise branch, so targets.len() == values.len() + 1
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 385237b357b4..fdbbf468ecea 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -3,6 +3,7 @@ use rustc_hir::LangItem;
use smallvec::SmallVec;
use super::TerminatorKind;
+use rustc_data_structures::packed::Pu128;
use rustc_macros::HashStable;
use std::slice;
@@ -14,7 +15,8 @@ impl SwitchTargets {
/// The iterator may be empty, in which case the `SwitchInt` instruction is equivalent to
/// `goto otherwise;`.
pub fn new(targets: impl Iterator- , otherwise: BasicBlock) -> Self {
- let (values, mut targets): (SmallVec<_>, SmallVec<_>) = targets.unzip();
+ let (values, mut targets): (SmallVec<_>, SmallVec<_>) =
+ targets.map(|(v, t)| (Pu128(v), t)).unzip();
targets.push(otherwise);
Self { values, targets }
}
@@ -22,7 +24,7 @@ impl SwitchTargets {
/// Builds a switch targets definition that jumps to `then` if the tested value equals `value`,
/// and to `else_` if not.
pub fn static_if(value: u128, then: BasicBlock, else_: BasicBlock) -> Self {
- Self { values: smallvec![value], targets: smallvec![then, else_] }
+ Self { values: smallvec![Pu128(value)], targets: smallvec![then, else_] }
}
/// Inverse of `SwitchTargets::static_if`.
@@ -31,7 +33,7 @@ impl SwitchTargets {
if let &[value] = &self.values[..]
&& let &[then, else_] = &self.targets[..]
{
- Some((value, then, else_))
+ Some((value.get(), then, else_))
} else {
None
}
@@ -75,7 +77,7 @@ impl SwitchTargets {
}
pub struct SwitchTargetsIter<'a> {
- inner: iter::Zip, slice::Iter<'a, BasicBlock>>,
+ inner: iter::Zip, slice::Iter<'a, BasicBlock>>,
}
impl<'a> Iterator for SwitchTargetsIter<'a> {
@@ -83,7 +85,7 @@ impl<'a> Iterator for SwitchTargetsIter<'a> {
#[inline]
fn next(&mut self) -> Option {
- self.inner.next().map(|(val, bb)| (*val, *bb))
+ self.inner.next().map(|(val, bb)| (val.get(), *bb))
}
#[inline]
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 6807eacb7f17..0d53870a0baf 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -7,7 +7,7 @@ pub mod tls;
use crate::arena::Arena;
use crate::dep_graph::{DepGraph, DepKindStruct};
use crate::infer::canonical::{CanonicalParamEnvCache, CanonicalVarInfo, CanonicalVarInfos};
-use crate::lint::struct_lint_level;
+use crate::lint::lint_level;
use crate::metadata::ModChild;
use crate::middle::codegen_fn_attrs::CodegenFnAttrs;
use crate::middle::resolve_bound_vars;
@@ -745,7 +745,7 @@ impl<'tcx> TyCtxt<'tcx> {
],
) = attr.meta_item_list().as_deref()
{
- Bound::Included(a)
+ Bound::Included(a.get())
} else {
self.dcx().span_delayed_bug(
attr.span,
@@ -1416,6 +1416,7 @@ nop_lift! {const_; Const<'a> => Const<'tcx>}
nop_lift! {const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx>}
nop_lift! {predicate; Predicate<'a> => Predicate<'tcx>}
nop_lift! {predicate; Clause<'a> => Clause<'tcx>}
+nop_lift! {layout; Layout<'a> => Layout<'tcx>}
nop_list_lift! {type_lists; Ty<'a> => Ty<'tcx>}
nop_list_lift! {poly_existential_predicates; PolyExistentialPredicate<'a> => PolyExistentialPredicate<'tcx>}
@@ -1424,8 +1425,28 @@ nop_list_lift! {bound_variable_kinds; ty::BoundVariableKind => ty::BoundVariable
// This is the impl for `&'a GenericArgs<'a>`.
nop_list_lift! {args; GenericArg<'a> => GenericArg<'tcx>}
+macro_rules! nop_slice_lift {
+ ($ty:ty => $lifted:ty) => {
+ impl<'a, 'tcx> Lift<'tcx> for &'a [$ty] {
+ type Lifted = &'tcx [$lifted];
+ fn lift_to_tcx(self, tcx: TyCtxt<'tcx>) -> Option {
+ if self.is_empty() {
+ return Some(&[]);
+ }
+ tcx.interners
+ .arena
+ .dropless
+ .contains_slice(self)
+ .then(|| unsafe { mem::transmute(self) })
+ }
+ }
+ };
+}
+
+nop_slice_lift! {ty::ValTree<'a> => ty::ValTree<'tcx>}
+
TrivialLiftImpls! {
- ImplPolarity,
+ ImplPolarity, Promoted
}
macro_rules! sty_debug_print {
@@ -2056,7 +2077,7 @@ impl<'tcx> TyCtxt<'tcx> {
/// Emit a lint at `span` from a lint struct (some type that implements `DecorateLint`,
/// typically generated by `#[derive(LintDiagnostic)]`).
#[track_caller]
- pub fn emit_spanned_lint(
+ pub fn emit_node_span_lint(
self,
lint: &'static Lint,
hir_id: HirId,
@@ -2065,17 +2086,17 @@ impl<'tcx> TyCtxt<'tcx> {
) {
let msg = decorator.msg();
let (level, src) = self.lint_level_at_node(lint, hir_id);
- struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
+ lint_level(self.sess, lint, level, src, Some(span.into()), msg, |diag| {
decorator.decorate_lint(diag);
})
}
/// Emit a lint at the appropriate level for a hir node, with an associated span.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
- pub fn struct_span_lint_hir(
+ pub fn node_span_lint(
self,
lint: &'static Lint,
hir_id: HirId,
@@ -2084,29 +2105,29 @@ impl<'tcx> TyCtxt<'tcx> {
decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
let (level, src) = self.lint_level_at_node(lint, hir_id);
- struct_lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
+ lint_level(self.sess, lint, level, src, Some(span.into()), msg, decorate);
}
/// Emit a lint from a lint struct (some type that implements `DecorateLint`, typically
/// generated by `#[derive(LintDiagnostic)]`).
#[track_caller]
- pub fn emit_lint(
+ pub fn emit_node_lint(
self,
lint: &'static Lint,
id: HirId,
decorator: impl for<'a> DecorateLint<'a, ()>,
) {
- self.struct_lint_node(lint, id, decorator.msg(), |diag| {
+ self.node_lint(lint, id, decorator.msg(), |diag| {
decorator.decorate_lint(diag);
})
}
/// Emit a lint at the appropriate level for a hir node.
///
- /// [`struct_lint_level`]: rustc_middle::lint::struct_lint_level#decorate-signature
+ /// [`lint_level`]: rustc_middle::lint::lint_level#decorate-signature
#[rustc_lint_diagnostics]
#[track_caller]
- pub fn struct_lint_node(
+ pub fn node_lint(
self,
lint: &'static Lint,
id: HirId,
@@ -2114,7 +2135,7 @@ impl<'tcx> TyCtxt<'tcx> {
decorate: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>),
) {
let (level, src) = self.lint_level_at_node(lint, id);
- struct_lint_level(self.sess, lint, level, src, None, msg, decorate);
+ lint_level(self.sess, lint, level, src, None, msg, decorate);
}
pub fn in_scope_traits(self, id: HirId) -> Option<&'tcx [TraitCandidate]> {
diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs
index dd41cb5a61f4..b6c3c34078f7 100644
--- a/compiler/rustc_middle/src/ty/instance.rs
+++ b/compiler/rustc_middle/src/ty/instance.rs
@@ -3,6 +3,7 @@ use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::{self, Ty, TyCtxt, TypeFoldable, TypeSuperFoldable};
use crate::ty::{EarlyBinder, GenericArgs, GenericArgsRef, TypeVisitableExt};
use rustc_errors::ErrorGuaranteed;
+use rustc_hir as hir;
use rustc_hir::def::Namespace;
use rustc_hir::def_id::{CrateNum, DefId};
use rustc_hir::lang_items::LangItem;
@@ -11,6 +12,7 @@ use rustc_macros::HashStable;
use rustc_middle::ty::normalize_erasing_regions::NormalizationError;
use rustc_span::Symbol;
+use std::assert_matches::assert_matches;
use std::fmt;
/// A monomorphized `InstanceDef`.
@@ -572,6 +574,54 @@ impl<'tcx> Instance<'tcx> {
Some(Instance { def, args })
}
+ pub fn try_resolve_item_for_coroutine(
+ tcx: TyCtxt<'tcx>,
+ trait_item_id: DefId,
+ trait_id: DefId,
+ rcvr_args: ty::GenericArgsRef<'tcx>,
+ ) -> Option> {
+ let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
+ return None;
+ };
+ let coroutine_kind = tcx.coroutine_kind(coroutine_def_id).unwrap();
+
+ let lang_items = tcx.lang_items();
+ let coroutine_callable_item = if Some(trait_id) == lang_items.future_trait() {
+ assert_matches!(
+ coroutine_kind,
+ hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Async, _)
+ );
+ hir::LangItem::FuturePoll
+ } else if Some(trait_id) == lang_items.iterator_trait() {
+ assert_matches!(
+ coroutine_kind,
+ hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::Gen, _)
+ );
+ hir::LangItem::IteratorNext
+ } else if Some(trait_id) == lang_items.async_iterator_trait() {
+ assert_matches!(
+ coroutine_kind,
+ hir::CoroutineKind::Desugared(hir::CoroutineDesugaring::AsyncGen, _)
+ );
+ hir::LangItem::AsyncIteratorPollNext
+ } else if Some(trait_id) == lang_items.coroutine_trait() {
+ assert_matches!(coroutine_kind, hir::CoroutineKind::Coroutine(_));
+ hir::LangItem::CoroutineResume
+ } else {
+ return None;
+ };
+
+ if tcx.lang_items().get(coroutine_callable_item) == Some(trait_item_id) {
+ Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
+ } else {
+ // All other methods should be defaulted methods of the built-in trait.
+ // This is important for `Iterator`'s combinators, but also useful for
+ // adding future default methods to `Future`, for instance.
+ debug_assert!(tcx.defaultness(trait_item_id).has_value());
+ Some(Instance::new(trait_item_id, rcvr_args))
+ }
+ }
+
/// Depending on the kind of `InstanceDef`, the MIR body associated with an
/// instance is expressed in terms of the generic parameters of `self.def_id()`, and in other
/// cases the MIR body is expressed in terms of the types found in the substitution array.
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index 4028de27cae1..a06f4c6ba12e 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -3072,8 +3072,6 @@ fn for_each_def(tcx: TyCtxt<'_>, mut collect_fn: impl for<'b> FnMut(&'b Ident, N
/// See also [`DelayDm`](rustc_error_messages::DelayDm) and [`with_no_trimmed_paths!`].
// this is pub to be able to intra-doc-link it
pub fn trimmed_def_paths(tcx: TyCtxt<'_>, (): ()) -> DefIdMap {
- assert!(tcx.sess.opts.trimmed_def_paths);
-
// Trimming paths is expensive and not optimized, since we expect it to only be used for error
// reporting.
//
diff --git a/compiler/rustc_middle/src/ty/visit.rs b/compiler/rustc_middle/src/ty/visit.rs
index 1f8978aa8633..a750a86d2570 100644
--- a/compiler/rustc_middle/src/ty/visit.rs
+++ b/compiler/rustc_middle/src/ty/visit.rs
@@ -55,10 +55,13 @@ pub trait TypeVisitableExt<'tcx>: TypeVisitable> {
}
fn error_reported(&self) -> Result<(), ErrorGuaranteed> {
if self.references_error() {
- if let Some(reported) = ty::tls::with(|tcx| tcx.dcx().is_compilation_going_to_fail()) {
+ // We must include lint errors and span delayed bugs here.
+ if let Some(reported) =
+ ty::tls::with(|tcx| tcx.dcx().has_errors_or_lint_errors_or_delayed_bugs())
+ {
Err(reported)
} else {
- bug!("expect tcx.sess.is_compilation_going_to_fail return `Some`");
+ bug!("expected some kind of error in `error_reported`");
}
} else {
Ok(())
diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
index 5721957037e8..6636f75d9981 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs
@@ -153,7 +153,7 @@ fn lit_to_mir_constant<'tcx>(
ConstValue::Scalar(Scalar::from_uint(*n, Size::from_bytes(1)))
}
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
- trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?
+ trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() })?
}
(ast::LitKind::Float(n, _), ty::Float(fty)) => parse_float_into_constval(*n, *fty, neg)
.ok_or_else(|| {
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index b4a02fae4544..ac147afaab31 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -599,7 +599,7 @@ impl UnsafeOpKind {
// FIXME: ideally we would want to trim the def paths, but this is not
// feasible with the current lint emission API (see issue #106126).
match self {
- CallToUnsafeFunction(Some(did)) => tcx.emit_spanned_lint(
+ CallToUnsafeFunction(Some(did)) => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -609,7 +609,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- CallToUnsafeFunction(None) => tcx.emit_spanned_lint(
+ CallToUnsafeFunction(None) => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -618,7 +618,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- UseOfInlineAssembly => tcx.emit_spanned_lint(
+ UseOfInlineAssembly => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -627,7 +627,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- InitializingTypeWith => tcx.emit_spanned_lint(
+ InitializingTypeWith => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -636,7 +636,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- UseOfMutableStatic => tcx.emit_spanned_lint(
+ UseOfMutableStatic => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -645,7 +645,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- UseOfExternStatic => tcx.emit_spanned_lint(
+ UseOfExternStatic => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -654,7 +654,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- DerefOfRawPointer => tcx.emit_spanned_lint(
+ DerefOfRawPointer => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -663,7 +663,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- AccessToUnionField => tcx.emit_spanned_lint(
+ AccessToUnionField => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -672,7 +672,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- MutationOfLayoutConstrainedField => tcx.emit_spanned_lint(
+ MutationOfLayoutConstrainedField => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -681,7 +681,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- BorrowOfLayoutConstrainedField => tcx.emit_spanned_lint(
+ BorrowOfLayoutConstrainedField => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -690,7 +690,7 @@ impl UnsafeOpKind {
unsafe_not_inherited_note,
},
),
- CallToFunctionWith { function, missing, build_enabled } => tcx.emit_spanned_lint(
+ CallToFunctionWith { function, missing, build_enabled } => tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
hir_id,
span,
@@ -941,7 +941,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
warnings.sort_by_key(|w| w.block_span);
for UnusedUnsafeWarning { hir_id, block_span, enclosing_unsafe } in warnings {
let block_span = tcx.sess.source_map().guess_head_span(block_span);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNUSED_UNSAFE,
hir_id,
block_span,
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index e3cc21cef11c..e1b998b24718 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -430,7 +430,7 @@ impl AddToDiagnostic for UnsafeNotInheritedLintNote {
diag.tool_only_multipart_suggestion(
fluent::mir_build_wrap_suggestion,
vec![(body_start, "{ unsafe ".into()), (body_end, "}".into())],
- Applicability::MaybeIncorrect,
+ Applicability::MachineApplicable,
);
}
}
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 167b65328d11..337493d15dec 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -53,7 +53,7 @@ fn check_recursion<'tcx>(
let sp = tcx.def_span(def_id);
let hir_id = tcx.local_def_id_to_hir_id(def_id);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNCONDITIONAL_RECURSION,
hir_id,
sp,
diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs
index 8d5e6cd4f410..71aebd13003b 100644
--- a/compiler/rustc_mir_build/src/thir/constant.rs
+++ b/compiler/rustc_mir_build/src/thir/constant.rs
@@ -54,7 +54,7 @@ pub(crate) fn lit_to_const<'tcx>(
}
(ast::LitKind::Int(n, _), ty::Uint(_)) | (ast::LitKind::Int(n, _), ty::Int(_)) => {
let scalar_int =
- trunc(if neg { (*n as i128).overflowing_neg().0 as u128 } else { *n })?;
+ trunc(if neg { (n.get() as i128).overflowing_neg().0 as u128 } else { n.get() })?;
ty::ValTree::from_scalar_int(scalar_int)
}
(ast::LitKind::Bool(b), ty::Bool) => ty::ValTree::from_scalar_int((*b).into()),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index 693dc49c6e8f..ce75a2831a51 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -1,9 +1,8 @@
use rustc_pattern_analysis::errors::Uncovered;
use rustc_pattern_analysis::rustc::{
- Constructor, DeconstructedPat, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
+ Constructor, DeconstructedPat, MatchArm, RustcMatchCheckCtxt as MatchCheckCtxt, Usefulness,
UsefulnessReport, WitnessPat,
};
-use rustc_pattern_analysis::{analyze_match, MatchArm};
use crate::errors::*;
@@ -390,6 +389,34 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
}
}
+ fn analyze_patterns(
+ &mut self,
+ cx: &MatchCheckCtxt<'p, 'tcx>,
+ arms: &[MatchArm<'p, 'tcx>],
+ scrut_ty: Ty<'tcx>,
+ ) -> Result, ErrorGuaranteed> {
+ let report =
+ rustc_pattern_analysis::analyze_match(&cx, &arms, scrut_ty).map_err(|err| {
+ self.error = Err(err);
+ err
+ })?;
+
+ // Warn unreachable subpatterns.
+ for (arm, is_useful) in report.arm_usefulness.iter() {
+ if let Usefulness::Useful(redundant_subpats) = is_useful
+ && !redundant_subpats.is_empty()
+ {
+ let mut redundant_subpats = redundant_subpats.clone();
+ // Emit lints in the order in which they occur in the file.
+ redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
+ for pat in redundant_subpats {
+ report_unreachable_pattern(cx, arm.arm_data, pat.data().unwrap().span, None)
+ }
+ }
+ }
+ Ok(report)
+ }
+
#[instrument(level = "trace", skip(self))]
fn check_let(&mut self, pat: &'p Pat<'tcx>, scrutinee: Option, span: Span) {
assert!(self.let_source != LetSource::None);
@@ -435,14 +462,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
}
}
- let scrut_ty = scrut.ty;
- let report = match analyze_match(&cx, &tarms, scrut_ty) {
- Ok(report) => report,
- Err(err) => {
- self.error = Err(err);
- return;
- }
- };
+ let Ok(report) = self.analyze_patterns(&cx, &tarms, scrut.ty) else { return };
match source {
// Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
@@ -474,7 +494,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
);
} else {
self.error = Err(report_non_exhaustive_match(
- &cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
+ &cx, self.thir, scrut.ty, scrut.span, witnesses, arms, expr_span,
));
}
}
@@ -519,7 +539,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
let span_end = prefix.last().unwrap().unwrap().0;
let span = span_start.to(span_end);
let count = prefix.len();
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
IRREFUTABLE_LET_PATTERNS,
self.lint_level,
span,
@@ -538,7 +558,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
let span_end = suffix.last().unwrap().unwrap().0;
let span = span_start.to(span_end);
let count = suffix.len();
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
IRREFUTABLE_LET_PATTERNS,
self.lint_level,
span,
@@ -556,7 +576,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
let cx = self.new_cx(refutability, None, scrut, pat.span);
let pat = self.lower_pattern(&cx, pat)?;
let arms = [MatchArm { pat, arm_data: self.lint_level, has_guard: false }];
- let report = analyze_match(&cx, &arms, pat.ty().inner())?;
+ let report = self.analyze_patterns(&cx, &arms, pat.ty().inner())?;
Ok((cx, report))
}
@@ -567,7 +587,6 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
) -> Result {
let (cx, report) = self.analyze_binding(pat, Refutable, scrut)?;
// Report if the pattern is unreachable, which can only occur when the type is uninhabited.
- // This also reports unreachable sub-patterns.
report_arm_reachability(&cx, &report);
// If the list of witnesses is empty, the match is exhaustive, i.e. the `if let` pattern is
// irrefutable.
@@ -795,7 +814,7 @@ fn check_for_bindings_named_same_as_variants(
{
let variant_count = edef.variants().len();
let ty_path = with_no_trimmed_paths!(cx.tcx.def_path_str(edef.did()));
- cx.tcx.emit_spanned_lint(
+ cx.tcx.emit_node_span_lint(
BINDINGS_WITH_VARIANT_NAME,
cx.lint_level,
pat.span,
@@ -837,7 +856,7 @@ fn report_irrefutable_let_patterns(
) {
macro_rules! emit_diag {
($lint:tt) => {{
- tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count });
+ tcx.emit_node_span_lint(IRREFUTABLE_LET_PATTERNS, id, span, $lint { count });
}};
}
@@ -850,39 +869,30 @@ fn report_irrefutable_let_patterns(
}
}
+/// Report unreachable arms, if any.
+fn report_unreachable_pattern<'p, 'tcx>(
+ cx: &MatchCheckCtxt<'p, 'tcx>,
+ hir_id: HirId,
+ span: Span,
+ catchall: Option,
+) {
+ cx.tcx.emit_node_span_lint(
+ UNREACHABLE_PATTERNS,
+ hir_id,
+ span,
+ UnreachablePattern { span: if catchall.is_some() { Some(span) } else { None }, catchall },
+ );
+}
+
/// Report unreachable arms, if any.
fn report_arm_reachability<'p, 'tcx>(
cx: &MatchCheckCtxt<'p, 'tcx>,
report: &UsefulnessReport<'p, 'tcx>,
) {
- let report_unreachable_pattern = |span, hir_id, catchall: Option| {
- cx.tcx.emit_spanned_lint(
- UNREACHABLE_PATTERNS,
- hir_id,
- span,
- UnreachablePattern {
- span: if catchall.is_some() { Some(span) } else { None },
- catchall,
- },
- );
- };
-
let mut catchall = None;
for (arm, is_useful) in report.arm_usefulness.iter() {
- match is_useful {
- Usefulness::Redundant => {
- report_unreachable_pattern(arm.pat.data().unwrap().span, arm.arm_data, catchall)
- }
- Usefulness::Useful(redundant_subpats) if redundant_subpats.is_empty() => {}
- // The arm is reachable, but contains redundant subpatterns (from or-patterns).
- Usefulness::Useful(redundant_subpats) => {
- let mut redundant_subpats = redundant_subpats.clone();
- // Emit lints in the order in which they occur in the file.
- redundant_subpats.sort_unstable_by_key(|pat| pat.data().unwrap().span);
- for pat in redundant_subpats {
- report_unreachable_pattern(pat.data().unwrap().span, arm.arm_data, None);
- }
- }
+ if matches!(is_useful, Usefulness::Redundant) {
+ report_unreachable_pattern(cx, arm.arm_data, arm.pat.data().unwrap().span, catchall)
}
if !arm.has_guard && catchall.is_none() && pat_is_catchall(arm.pat) {
catchall = Some(arm.pat.data().unwrap().span);
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 5631a38d0f0d..22305f03a769 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -214,7 +214,7 @@ impl<'tcx> ConstToPat<'tcx> {
if let Some(mir_structural_match_violation) = mir_structural_match_violation {
match non_sm_ty.kind() {
ty::Adt(..) if mir_structural_match_violation => {
- self.tcx().emit_spanned_lint(
+ self.tcx().emit_node_span_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id,
self.span,
@@ -233,7 +233,7 @@ impl<'tcx> ConstToPat<'tcx> {
} else if !have_valtree && !self.saw_const_match_lint.get() {
// The only way valtree construction can fail without the structural match
// checker finding a violation is if there is a pointer somewhere.
- self.tcx().emit_spanned_lint(
+ self.tcx().emit_node_span_lint(
lint::builtin::POINTER_STRUCTURAL_MATCH,
self.id,
self.span,
@@ -244,7 +244,7 @@ impl<'tcx> ConstToPat<'tcx> {
// Always check for `PartialEq`, even if we emitted other lints. (But not if there were
// any errors.) This ensures it shows up in cargo's future-compat reports as well.
if !self.type_has_partial_eq_impl(cv.ty()) {
- self.tcx().emit_spanned_lint(
+ self.tcx().emit_node_span_lint(
lint::builtin::CONST_PATTERNS_WITHOUT_PARTIAL_EQ,
self.id,
self.span,
@@ -319,7 +319,7 @@ impl<'tcx> ConstToPat<'tcx> {
let kind = match ty.kind() {
ty::Float(_) => {
self.saw_const_match_lint.set(true);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
id,
span,
@@ -339,7 +339,7 @@ impl<'tcx> ConstToPat<'tcx> {
ty::Adt(..) if !self.type_marked_structural(ty) && self.behind_reference.get() => {
if self.saw_const_match_error.get().is_none() && !self.saw_const_match_lint.get() {
self.saw_const_match_lint.set(true);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
id,
span,
@@ -435,7 +435,7 @@ impl<'tcx> ConstToPat<'tcx> {
&& !self.saw_const_match_lint.get()
{
self.saw_const_match_lint.set(true);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint::builtin::INDIRECT_STRUCTURAL_MATCH,
self.id,
span,
@@ -516,7 +516,7 @@ impl<'tcx> ConstToPat<'tcx> {
&& let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, ty)
{
self.saw_const_match_lint.set(true);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
id,
span,
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index b805f8ca23eb..8d189babee89 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -16,15 +16,17 @@ extern crate rustc_middle;
use rustc_middle::ty;
+// Please change the public `use` directives cautiously, as they might be used by external tools.
+// See issue #120130.
pub use self::drop_flag_effects::{
drop_flag_effects_for_function_entry, drop_flag_effects_for_location,
move_path_children_matching, on_all_children_bits, on_lookup_result_bits,
};
pub use self::framework::{
- fmt, lattice, visit_results, Analysis, AnalysisDomain, Direction, GenKill, GenKillAnalysis,
- JoinSemiLattice, MaybeReachable, Results, ResultsCursor, ResultsVisitable, ResultsVisitor,
+ fmt, graphviz, lattice, visit_results, Analysis, AnalysisDomain, Backward, Direction, Engine,
+ Forward, GenKill, GenKillAnalysis, JoinSemiLattice, MaybeReachable, Results, ResultsCursor,
+ ResultsVisitable, ResultsVisitor, SwitchIntEdgeEffects,
};
-use self::framework::{Backward, SwitchIntEdgeEffects};
use self::move_paths::MoveData;
pub mod debuginfo;
diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
index 3195cd3622dc..1f615c9d8d1a 100644
--- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
+++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs
@@ -100,7 +100,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
&& let Some((lint_root, span, item)) =
self.should_lint_const_item_usage(lhs, def_id, loc)
{
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
CONST_ITEM_MUTATION,
lint_root,
span,
@@ -145,7 +145,7 @@ impl<'tcx> Visitor<'tcx> for ConstMutationChecker<'_, 'tcx> {
if let Some((lint_root, span, item)) =
self.should_lint_const_item_usage(place, def_id, lint_loc)
{
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
CONST_ITEM_MUTATION,
lint_root,
span,
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 582c2c0c6b60..6c4c3917cb5e 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -527,7 +527,7 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
} else {
None
};
- tcx.emit_spanned_lint(UNUSED_UNSAFE, id, span, errors::UnusedUnsafe { span, nested_parent });
+ tcx.emit_node_span_lint(UNUSED_UNSAFE, id, span, errors::UnusedUnsafe { span, nested_parent });
}
pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
@@ -577,7 +577,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
});
}
UnsafetyViolationKind::UnsafeFn => {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNSAFE_OP_IN_UNSAFE_FN,
lint_root,
source_info.span,
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index d0bbca08a406..b8fecaf635aa 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -278,7 +278,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
fn report_assert_as_lint(&self, source_info: &SourceInfo, lint: AssertLint) {
if let Some(lint_root) = self.lint_root(*source_info) {
- self.tcx.emit_spanned_lint(lint.lint(), lint_root, source_info.span, lint);
+ self.tcx.emit_node_span_lint(lint.lint(), lint_root, source_info.span, lint);
}
}
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index eaa36e0cc91e..347f9b49efe8 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -2071,7 +2071,7 @@ fn check_must_not_suspend_def(
span: data.source_span,
reason: s.as_str().to_string(),
});
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
rustc_session::lint::builtin::MUST_NOT_SUSPEND,
hir_id,
data.source_span,
diff --git a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
index 26fcfad82877..c47abb4fcb47 100644
--- a/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
+++ b/compiler/rustc_mir_transform/src/ffi_unwind_calls.rs
@@ -112,7 +112,7 @@ fn has_ffi_unwind_calls(tcx: TyCtxt<'_>, local_def_id: LocalDefId) -> bool {
let span = terminator.source_info.span;
let foreign = fn_def_id.is_some();
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
FFI_UNWIND_CALLS,
lint_root,
span,
diff --git a/compiler/rustc_mir_transform/src/function_item_references.rs b/compiler/rustc_mir_transform/src/function_item_references.rs
index 61d99f1f018b..f413bd9b3116 100644
--- a/compiler/rustc_mir_transform/src/function_item_references.rs
+++ b/compiler/rustc_mir_transform/src/function_item_references.rs
@@ -185,7 +185,7 @@ impl<'tcx> FunctionItemRefChecker<'_, 'tcx> {
ret,
);
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
FUNCTION_ITEM_REFERENCES,
lint_root,
span,
diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs
index 19bfed4333c0..a78a3fd594d9 100644
--- a/compiler/rustc_mir_transform/src/lib.rs
+++ b/compiler/rustc_mir_transform/src/lib.rs
@@ -2,9 +2,11 @@
#![deny(rustc::diagnostic_outside_of_impl)]
#![feature(assert_matches)]
#![feature(box_patterns)]
+#![feature(const_type_name)]
#![feature(cow_is_borrowed)]
#![feature(decl_macro)]
#![feature(impl_trait_in_assoc_type)]
+#![feature(inline_const)]
#![feature(is_sorted)]
#![feature(let_chains)]
#![feature(map_try_insert)]
diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs
index f4c572aec128..c1ef2b9f887f 100644
--- a/compiler/rustc_mir_transform/src/pass_manager.rs
+++ b/compiler/rustc_mir_transform/src/pass_manager.rs
@@ -7,8 +7,20 @@ use crate::{lint::lint_body, validate, MirPass};
/// Just like `MirPass`, except it cannot mutate `Body`.
pub trait MirLint<'tcx> {
fn name(&self) -> &'static str {
- let name = std::any::type_name::();
- if let Some((_, tail)) = name.rsplit_once(':') { tail } else { name }
+ // FIXME Simplify the implementation once more `str` methods get const-stable.
+ const {
+ let name = std::any::type_name::();
+ let bytes = name.as_bytes();
+ let mut i = bytes.len();
+ while i > 0 && bytes[i - 1] != b':' {
+ i = i - 1;
+ }
+ let (_, bytes) = bytes.split_at(i);
+ match std::str::from_utf8(bytes) {
+ Ok(name) => name,
+ Err(_) => name,
+ }
+ }
}
fn is_enabled(&self, _sess: &Session) -> bool {
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 20e70f87b75e..3e0906614145 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -714,7 +714,7 @@ impl<'a, 'tcx> MirUsedCollector<'a, 'tcx> {
// but correct span? This would make the lint at least accept crate-level lint attributes.
return;
};
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
LARGE_ASSIGNMENTS,
lint_root,
span,
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 1e1d45d6f702..625764876a6b 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -11,8 +11,9 @@
)]
#![deny(rustc::untranslatable_diagnostic)]
#![deny(rustc::diagnostic_outside_of_impl)]
-// WARNING: We want to be able to build this crate with a stable compiler,
-// so no `#![feature]` attributes should be added!
+// We want to be able to build this crate with a stable compiler,
+// so no `#![feature]` attributes should be added.
+#![deny(unstable_features)]
use rustc_lexer::unescape;
pub use Alignment::*;
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 20ed2573e3a7..9d9741bbe894 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -246,13 +246,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
attr.ident().and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
{
match attr.style {
- ast::AttrStyle::Outer => self.tcx.emit_spanned_lint(
+ ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::OuterCrateLevelAttr,
),
- ast::AttrStyle::Inner => self.tcx.emit_spanned_lint(
+ ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -274,7 +274,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
fn inline_attr_str_error_with_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -283,7 +283,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
fn inline_attr_str_error_without_macro_def(&self, hir_id: HirId, attr: &Attribute, sym: &str) {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -304,7 +304,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
/// Checks if `#[diagnostic::on_unimplemented]` is applied to a trait definition
fn check_diagnostic_on_unimplemented(&self, attr_span: Span, hir_id: HirId, target: Target) {
if !matches!(target, Target::Trait) {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
hir_id,
attr_span,
@@ -320,7 +320,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| Target::Closure
| Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => true,
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -333,7 +333,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// accidentally, to be compatible with crates depending on them, we can't throw an
// error here.
Target::AssocConst => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -366,7 +366,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// function prototypes can't be covered
Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -376,7 +376,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
Target::Mod | Target::ForeignMod | Target::Impl | Target::Trait => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -386,7 +386,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
Target::Expression | Target::Statement | Target::Arm => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -413,7 +413,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
allowed_target: Target,
) {
if target != allowed_target {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -630,7 +630,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// FIXME: #[target_feature] was previously erroneously allowed on statements and some
// crates used this, so only emit a warning.
Target::Statement => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -769,7 +769,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
return false;
}
if let Err(entry) = aliases.try_insert(doc_alias_str.to_owned(), span) {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
span,
@@ -914,7 +914,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
_ => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -937,7 +937,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
target: Target,
) -> bool {
if target != Target::ExternCrate {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -951,7 +951,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
if self.tcx.extern_mod_stmt_cnum(hir_id.owner).is_none() {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -996,7 +996,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
.then_some(errors::AttrCrateLevelOnlySugg {
attr: attr.span.with_lo(bang_span).with_hi(bang_span),
});
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -1016,7 +1016,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
match (i_meta.name_or_empty(), i_meta.meta_item()) {
(sym::attr | sym::no_crate_inject, _) => {}
(_, Some(m)) => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
i_meta.span(),
@@ -1027,7 +1027,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
is_valid = false;
}
(_, None) => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
i_meta.span(),
@@ -1038,7 +1038,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
} else {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -1055,7 +1055,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
if meta.meta_item_list().is_some() {
true
} else {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -1188,7 +1188,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
_ => {
let path = rustc_ast_pretty::pprust::path_to_string(&i_meta.path);
if i_meta.has_name(sym::spotlight) {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
i_meta.span,
@@ -1204,7 +1204,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
};
// If there are multiple attributes, the suggestion would suggest
// deleting all of them, which is incorrect.
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
i_meta.span,
@@ -1219,7 +1219,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
},
);
} else {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
i_meta.span,
@@ -1230,7 +1230,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
} else {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_DOC_ATTRIBUTES,
hir_id,
meta.span(),
@@ -1343,7 +1343,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
_ => "a",
};
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1380,7 +1380,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
_ => {
// FIXME: #[cold] was previously allowed on non-functions and some crates used
// this, so only emit a warning.
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1400,7 +1400,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
return;
}
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1424,14 +1424,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// used this, so only emit a warning.
let attr_span = matches!(target, Target::ForeignMod).then_some(attr.span);
if let Some(s) = attr.value_str() {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
errors::LinkName { span, attr_span, value: s.as_str() },
);
} else {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1710,7 +1710,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
_ => {
// FIXME: #[link_section] was previously allowed on non-functions/statics and some
// crates used this, so only emit a warning.
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1741,7 +1741,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Target::ForeignStatic => "static",
_ => unreachable!(),
};
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1751,7 +1751,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
_ => {
// FIXME: #[no_mangle] was previously allowed on non-functions/statics and some
// crates used this, so only emit a warning.
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -1929,7 +1929,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
return false;
}))
{
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
CONFLICTING_REPR_HINTS,
hir_id,
hint_spans.collect::>(),
@@ -2171,7 +2171,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_deprecated(&self, hir_id: HirId, attr: &Attribute, _span: Span, target: Target) {
match target {
Target::Closure | Target::Expression | Target::Statement | Target::Arm => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -2187,7 +2187,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
match target {
Target::ExternCrate | Target::Mod => {}
_ => {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -2199,7 +2199,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
fn check_macro_export(&self, hir_id: HirId, attr: &Attribute, target: Target) {
if target != Target::MacroDef {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -2209,7 +2209,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
&& !meta_item_list.is_empty()
{
if meta_item_list.len() > 1 {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_MACRO_EXPORT_ARGUMENTS,
hir_id,
attr.span,
@@ -2217,7 +2217,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
);
} else {
if meta_item_list[0].name_or_empty() != sym::local_inner_macros {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INVALID_MACRO_EXPORT_ARGUMENTS,
hir_id,
meta_item_list[0].span(),
@@ -2234,7 +2234,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
let is_decl_macro = !macro_definition.macro_rules;
if is_decl_macro {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -2276,7 +2276,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
return;
};
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr.span,
@@ -2609,7 +2609,7 @@ fn check_duplicates(
} else {
(attr.span, *entry.get())
};
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
this,
diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs
index d7f17ac4547a..d3909ce3a1c1 100644
--- a/compiler/rustc_passes/src/dead.rs
+++ b/compiler/rustc_passes/src/dead.rs
@@ -199,7 +199,7 @@ impl<'tcx> MarkSymbolVisitor<'tcx> {
&& !assign.span.from_expansion()
{
let is_field_assign = matches!(lhs.kind, hir::ExprKind::Field(..));
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
lint::builtin::DEAD_CODE,
assign.hir_id,
assign.span,
@@ -899,7 +899,7 @@ impl<'tcx> DeadVisitor<'tcx> {
};
let hir_id = tcx.local_def_id_to_hir_id(first_item.def_id);
- self.tcx.emit_spanned_lint(DEAD_CODE, hir_id, MultiSpan::from_spans(spans), diag);
+ self.tcx.emit_node_span_lint(DEAD_CODE, hir_id, MultiSpan::from_spans(spans), diag);
}
fn warn_multiple(
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 92687c705aee..99f8186d5543 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1285,7 +1285,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
// that we do not emit the same warning twice if the uninhabited type
// is indeed `!`.
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNREACHABLE_CODE,
expr_id,
expr_span,
@@ -1446,7 +1446,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
if self.used_on_entry(entry_ln, var) {
if !self.live_on_entry(entry_ln, var) {
if let Some(name) = self.should_warn(var) {
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_ASSIGNMENTS,
var_hir_id,
vec![span],
@@ -1456,7 +1456,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
}
} else {
if let Some(name) = self.should_warn(var) {
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_VARIABLES,
var_hir_id,
vec![span],
@@ -1478,7 +1478,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
if !self.live_on_entry(ln, var)
&& let Some(name) = self.should_warn(var)
{
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
@@ -1552,7 +1552,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
if ln == self.exit_ln { false } else { self.assigned_on_exit(ln, var) };
if is_assigned {
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans
@@ -1574,7 +1574,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
span.with_hi(BytePos(span.hi().0 + 1))
})
.collect();
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans.iter().map(|(_, pat_span, _)| *pat_span).collect::>(),
@@ -1599,7 +1599,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
let non_shorthands =
non_shorthands.into_iter().map(|(_, pat_span, _)| pat_span).collect();
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans
@@ -1638,7 +1638,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
}
};
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_VARIABLES,
first_hir_id,
hir_ids_and_spans
@@ -1690,7 +1690,7 @@ impl<'tcx> Liveness<'_, 'tcx> {
if !self.live_on_exit(ln, var)
&& let Some(name) = self.should_warn(var)
{
- self.ir.tcx.emit_spanned_lint(
+ self.ir.tcx.emit_node_span_lint(
lint::builtin::UNUSED_ASSIGNMENTS,
hir_id,
spans,
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index d2cfdb7bf477..0455d6d4acba 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -70,7 +70,7 @@ fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
if abi == Abi::Rust {
let hir_id = tcx.local_def_id_to_hir_id(def_id);
let span = tcx.def_span(def_id);
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNDEFINED_NAKED_FUNCTION_ABI,
hir_id,
span,
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 18b9ba0f042d..c1fe8c2133b7 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -122,7 +122,7 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
if matches!(kind, AnnotationKind::Prohibited | AnnotationKind::DeprecationProhibited) {
let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
USELESS_DEPRECATED,
hir_id,
*span,
@@ -739,7 +739,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
// do not lint when the trait isn't resolved, since resolution error should
// be fixed first
if t.path.res != Res::Err && c.fully_stable {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
INEFFECTIVE_UNSTABLE_TRAIT_IMPL,
item.hir_id(),
span,
@@ -1073,7 +1073,7 @@ fn unnecessary_partially_stable_feature_lint(
implies: Symbol,
since: Symbol,
) {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint::builtin::STABLE_FEATURES,
hir::CRATE_HIR_ID,
span,
@@ -1096,7 +1096,7 @@ fn unnecessary_stable_feature_lint(
if since.as_str() == VERSION_PLACEHOLDER {
since = sym::env_CFG_RELEASE;
}
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
lint::builtin::STABLE_FEATURES,
hir::CRATE_HIR_ID,
span,
diff --git a/compiler/rustc_pattern_analysis/src/lints.rs b/compiler/rustc_pattern_analysis/src/lints.rs
index f9f065fbe8b1..4bfe7dfb072c 100644
--- a/compiler/rustc_pattern_analysis/src/lints.rs
+++ b/compiler/rustc_pattern_analysis/src/lints.rs
@@ -158,7 +158,7 @@ pub(crate) fn lint_nonexhaustive_missing_variants<'a, 'p, 'tcx>(
// is not exhaustive enough.
//
// NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
- rcx.tcx.emit_spanned_lint(
+ rcx.tcx.emit_node_span_lint(
NON_EXHAUSTIVE_OMITTED_PATTERNS,
rcx.match_lint_level,
rcx.scrut_span,
diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs
index 27b258024271..d8c3c010a2a9 100644
--- a/compiler/rustc_pattern_analysis/src/rustc.rs
+++ b/compiler/rustc_pattern_analysis/src/rustc.rs
@@ -1001,7 +1001,7 @@ impl<'p, 'tcx> TypeCx for RustcMatchCheckCtxt<'p, 'tcx> {
.map(|span| errors::Overlap { range: overlap_as_pat.clone(), span })
.collect();
let pat_span = pat.data().unwrap().span;
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
self.match_lint_level,
pat_span,
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 519303fc3aa9..0d4ee1e8dcaa 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -1399,7 +1399,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
fn check_def_id(&mut self, def_id: DefId, kind: &str, descr: &dyn fmt::Display) -> bool {
if self.leaks_private_dep(def_id) {
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
lint::builtin::EXPORTED_PRIVATE_DEPENDENCIES,
self.tcx.local_def_id_to_hir_id(self.item_def_id),
self.tcx.def_span(self.item_def_id.to_def_id()),
@@ -1456,7 +1456,7 @@ impl SearchInterfaceForPrivateItemsVisitor<'_> {
} else {
lint::builtin::PRIVATE_BOUNDS
};
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
lint,
self.tcx.local_def_id_to_hir_id(self.item_def_id),
span,
@@ -1543,7 +1543,7 @@ impl<'tcx> PrivateItemsInPublicInterfacesChecker<'tcx, '_> {
if reachable_at_vis.is_public() && reexported_at_vis != reachable_at_vis {
let hir_id = self.tcx.local_def_id_to_hir_id(def_id);
let span = self.tcx.def_span(def_id.to_def_id());
- self.tcx.emit_spanned_lint(
+ self.tcx.emit_node_span_lint(
lint::builtin::UNNAMEABLE_TYPES,
hir_id,
span,
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 0f57688063e0..2faa4876798e 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -818,7 +818,7 @@ impl DepGraphData {
None => {}
}
- if let None = qcx.dep_context().sess().dcx().has_errors_or_span_delayed_bugs() {
+ if let None = qcx.dep_context().sess().dcx().has_errors_or_lint_errors_or_delayed_bugs() {
panic!("try_mark_previous_green() - Forcing the DepNode should have set its color")
}
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index a4e2f9e3ff8c..b855ec8f920b 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -1029,9 +1029,9 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
}
}
- let macro_use_import = |this: &Self, span| {
+ let macro_use_import = |this: &Self, span, warn_private| {
this.r.arenas.alloc_import(ImportData {
- kind: ImportKind::MacroUse,
+ kind: ImportKind::MacroUse { warn_private },
root_id: item.id,
parent_scope: this.parent_scope,
imported_module: Cell::new(Some(ModuleOrUniformRoot::Module(module))),
@@ -1048,11 +1048,25 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
let allow_shadowing = self.parent_scope.expansion == LocalExpnId::ROOT;
if let Some(span) = import_all {
- let import = macro_use_import(self, span);
+ let import = macro_use_import(self, span, false);
self.r.potentially_unused_imports.push(import);
module.for_each_child(self, |this, ident, ns, binding| {
if ns == MacroNS {
- let imported_binding = this.r.import(binding, import);
+ let imported_binding =
+ if this.r.is_accessible_from(binding.vis, this.parent_scope.module) {
+ this.r.import(binding, import)
+ } else if !this.r.is_builtin_macro(binding.res())
+ && !this.r.macro_use_prelude.contains_key(&ident.name)
+ {
+ // - `!r.is_builtin_macro(res)` excluding the built-in macros such as `Debug` or `Hash`.
+ // - `!r.macro_use_prelude.contains_key(name)` excluding macros defined in other extern
+ // crates such as `std`.
+ // FIXME: This branch should eventually be removed.
+ let import = macro_use_import(this, span, true);
+ this.r.import(binding, import)
+ } else {
+ return;
+ };
this.add_macro_use_binding(ident.name, imported_binding, span, allow_shadowing);
}
});
@@ -1065,7 +1079,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
&self.parent_scope,
);
if let Ok(binding) = result {
- let import = macro_use_import(self, ident.span);
+ let import = macro_use_import(self, ident.span, false);
self.r.potentially_unused_imports.push(import);
let imported_binding = self.r.import(binding, import);
self.add_macro_use_binding(
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 0e43a35ce738..fc72d76c3a79 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -290,7 +290,7 @@ impl Resolver<'_, '_> {
|| import.expect_vis().is_public()
|| import.span.is_dummy() =>
{
- if let ImportKind::MacroUse = import.kind {
+ if let ImportKind::MacroUse { .. } = import.kind {
if !import.span.is_dummy() {
self.lint_buffer.buffer_lint(
MACRO_USE_EXTERN_CRATE,
@@ -315,7 +315,7 @@ impl Resolver<'_, '_> {
maybe_unused_extern_crates.insert(id, import.span);
}
}
- ImportKind::MacroUse => {
+ ImportKind::MacroUse { .. } => {
let msg = "unused `#[macro_use]` import";
self.lint_buffer.buffer_lint(UNUSED_IMPORTS, import.root_id, import.span, msg);
}
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index 4a0c522b6ec5..66dfee6c062d 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -285,7 +285,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
use NameBindingKind::Import;
let can_suggest = |binding: NameBinding<'_>, import: self::Import<'_>| {
!binding.span.is_dummy()
- && !matches!(import.kind, ImportKind::MacroUse | ImportKind::MacroExport)
+ && !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
};
let import = match (&new_binding.kind, &old_binding.kind) {
// If there are two imports where one or both have attributes then prefer removing the
@@ -1819,9 +1819,9 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
next_ident = source;
Some(binding)
}
- ImportKind::Glob { .. } | ImportKind::MacroUse | ImportKind::MacroExport => {
- Some(binding)
- }
+ ImportKind::Glob { .. }
+ | ImportKind::MacroUse { .. }
+ | ImportKind::MacroExport => Some(binding),
ImportKind::ExternCrate { .. } => None,
},
_ => None,
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index f846dbec2c69..ad60caed354f 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -80,7 +80,11 @@ pub(crate) enum ImportKind<'a> {
target: Ident,
id: NodeId,
},
- MacroUse,
+ MacroUse {
+ /// A field has been added indicating whether it should be reported as a lint,
+ /// addressing issue#119301.
+ warn_private: bool,
+ },
MacroExport,
}
@@ -127,7 +131,7 @@ impl<'a> std::fmt::Debug for ImportKind<'a> {
.field("target", target)
.field("id", id)
.finish(),
- MacroUse => f.debug_struct("MacroUse").finish(),
+ MacroUse { .. } => f.debug_struct("MacroUse").finish(),
MacroExport => f.debug_struct("MacroExport").finish(),
}
}
@@ -197,7 +201,7 @@ impl<'a> ImportData<'a> {
ImportKind::Single { id, .. }
| ImportKind::Glob { id, .. }
| ImportKind::ExternCrate { id, .. } => Some(id),
- ImportKind::MacroUse | ImportKind::MacroExport => None,
+ ImportKind::MacroUse { .. } | ImportKind::MacroExport => None,
}
}
@@ -207,7 +211,7 @@ impl<'a> ImportData<'a> {
ImportKind::Single { id, .. } => Reexport::Single(to_def_id(id)),
ImportKind::Glob { id, .. } => Reexport::Glob(to_def_id(id)),
ImportKind::ExternCrate { id, .. } => Reexport::ExternCrate(to_def_id(id)),
- ImportKind::MacroUse => Reexport::MacroUse,
+ ImportKind::MacroUse { .. } => Reexport::MacroUse,
ImportKind::MacroExport => Reexport::MacroExport,
}
}
@@ -1482,7 +1486,7 @@ fn import_kind_to_string(import_kind: &ImportKind<'_>) -> String {
ImportKind::Single { source, .. } => source.to_string(),
ImportKind::Glob { .. } => "*".to_string(),
ImportKind::ExternCrate { .. } => "".to_string(),
- ImportKind::MacroUse => "#[macro_use]".to_string(),
+ ImportKind::MacroUse { .. } => "#[macro_use]".to_string(),
ImportKind::MacroExport => "#[macro_export]".to_string(),
}
}
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 341c566d97fc..1c00f545eb82 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -55,6 +55,7 @@ use rustc_middle::span_bug;
use rustc_middle::ty::{self, MainDefinition, RegisteredTools, TyCtxt};
use rustc_middle::ty::{ResolverGlobalCtxt, ResolverOutputs};
use rustc_query_system::ich::StableHashingContext;
+use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
use rustc_session::lint::LintBuffer;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -1799,6 +1800,10 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
}
}
if let NameBindingKind::Import { import, binding, ref used } = used_binding.kind {
+ if let ImportKind::MacroUse { warn_private: true } = import.kind {
+ let msg = format!("macro `{ident}` is private");
+ self.lint_buffer().buffer_lint(PRIVATE_MACRO_USE, import.root_id, ident.span, msg);
+ }
// Avoid marking `extern crate` items that refer to a name from extern prelude,
// but not introduce it, as used if they are accessed from lexical scope.
if is_lexical_scope {
@@ -2069,7 +2074,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
let mut ret = Vec::new();
for meta in attr.meta_item_list()? {
match meta.lit()?.kind {
- LitKind::Int(a, _) => ret.push(a as usize),
+ LitKind::Int(a, _) => ret.push(a.get() as usize),
_ => panic!("invalid arg index"),
}
}
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 1337ade62c01..486b6d4bf2e1 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -224,7 +224,7 @@ top_level_options!(
working_dir: RealFileName [TRACKED],
color: ColorConfig [UNTRACKED],
- verbose: bool [UNTRACKED],
+ verbose: bool [TRACKED_NO_CRATE_HASH],
}
);
@@ -1986,7 +1986,7 @@ written to standard error output)"),
validate_mir: bool = (false, parse_bool, [UNTRACKED],
"validate MIR after each transformation"),
#[rustc_lint_opt_deny_field_access("use `Session::verbose_internals` instead of this field")]
- verbose_internals: bool = (false, parse_bool, [UNTRACKED],
+ verbose_internals: bool = (false, parse_bool, [TRACKED_NO_CRATE_HASH],
"in general, enable more debug printouts (default: no)"),
#[rustc_lint_opt_deny_field_access("use `Session::verify_llvm_ir` instead of this field")]
verify_llvm_ir: bool = (false, parse_bool, [TRACKED],
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 16036e5be38c..1cfaa49401da 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -144,7 +144,7 @@ pub fn feature_warn_issue(
let mut err = sess.parse_sess.dcx.struct_span_warn(span, explain);
add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
- // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
+ // Decorate this as a future-incompatibility lint as in rustc_middle::lint::lint_level
let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
let future_incompatible = lint.future_incompatible.as_ref().unwrap();
err.is_lint(lint.name_lower(), /* has_future_breakage */ false);
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index cba6ce0d235e..24aa336c68fe 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -323,6 +323,7 @@ impl Session {
}
pub fn compile_status(&self) -> Result<(), ErrorGuaranteed> {
+ // We must include lint errors here.
if let Some(reported) = self.dcx().has_errors_or_lint_errors() {
let _ = self.dcx().emit_stashed_diagnostics();
Err(reported)
diff --git a/compiler/rustc_smir/src/rustc_internal/internal.rs b/compiler/rustc_smir/src/rustc_internal/internal.rs
index 5689e8f3b3d9..fa52f52d60b9 100644
--- a/compiler/rustc_smir/src/rustc_internal/internal.rs
+++ b/compiler/rustc_smir/src/rustc_internal/internal.rs
@@ -5,7 +5,7 @@
// Prefer importing stable_mir over internal rustc constructs to make this file more readable.
use crate::rustc_smir::Tables;
-use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy};
+use rustc_middle::ty::{self as rustc_ty, Ty as InternalTy, TyCtxt};
use rustc_span::Symbol;
use stable_mir::abi::Layout;
use stable_mir::mir::alloc::AllocId;
@@ -21,118 +21,120 @@ use stable_mir::{CrateItem, CrateNum, DefId};
use super::RustcInternal;
-impl<'tcx> RustcInternal<'tcx> for CrateItem {
- type T = rustc_span::def_id::DefId;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- self.0.internal(tables)
+impl RustcInternal for CrateItem {
+ type T<'tcx> = rustc_span::def_id::DefId;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ self.0.internal(tables, tcx)
}
}
-impl<'tcx> RustcInternal<'tcx> for CrateNum {
- type T = rustc_span::def_id::CrateNum;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+impl RustcInternal for CrateNum {
+ type T<'tcx> = rustc_span::def_id::CrateNum;
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
rustc_span::def_id::CrateNum::from_usize(*self)
}
}
-impl<'tcx> RustcInternal<'tcx> for DefId {
- type T = rustc_span::def_id::DefId;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.def_ids[*self]
+impl RustcInternal for DefId {
+ type T<'tcx> = rustc_span::def_id::DefId;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.lift(tables.def_ids[*self]).unwrap()
}
}
-impl<'tcx> RustcInternal<'tcx> for GenericArgs {
- type T = rustc_ty::GenericArgsRef<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables)))
+impl RustcInternal for GenericArgs {
+ type T<'tcx> = rustc_ty::GenericArgsRef<'tcx>;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.mk_args_from_iter(self.0.iter().map(|arg| arg.internal(tables, tcx)))
}
}
-impl<'tcx> RustcInternal<'tcx> for GenericArgKind {
- type T = rustc_ty::GenericArg<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- match self {
- GenericArgKind::Lifetime(reg) => reg.internal(tables).into(),
- GenericArgKind::Type(ty) => ty.internal(tables).into(),
- GenericArgKind::Const(cnst) => ty_const(cnst, tables).into(),
- }
+impl RustcInternal for GenericArgKind {
+ type T<'tcx> = rustc_ty::GenericArg<'tcx>;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ let arg: rustc_ty::GenericArg<'tcx> = match self {
+ GenericArgKind::Lifetime(reg) => reg.internal(tables, tcx).into(),
+ GenericArgKind::Type(ty) => ty.internal(tables, tcx).into(),
+ GenericArgKind::Const(cnst) => ty_const(cnst, tables, tcx).into(),
+ };
+ tcx.lift(arg).unwrap()
}
}
-impl<'tcx> RustcInternal<'tcx> for Region {
- type T = rustc_ty::Region<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- // Cannot recover region. Use erased instead.
- tables.tcx.lifetimes.re_erased
+impl RustcInternal for Region {
+ type T<'tcx> = rustc_ty::Region<'tcx>;
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ // Cannot recover region. Use erased for now.
+ tcx.lifetimes.re_erased
}
}
-impl<'tcx> RustcInternal<'tcx> for Ty {
- type T = InternalTy<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.types[*self]
+impl RustcInternal for Ty {
+ type T<'tcx> = InternalTy<'tcx>;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.lift(tables.types[*self]).unwrap()
}
}
-impl<'tcx> RustcInternal<'tcx> for RigidTy {
- type T = rustc_ty::TyKind<'tcx>;
+impl RustcInternal for RigidTy {
+ type T<'tcx> = rustc_ty::TyKind<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
RigidTy::Bool => rustc_ty::TyKind::Bool,
RigidTy::Char => rustc_ty::TyKind::Char,
- RigidTy::Int(int_ty) => rustc_ty::TyKind::Int(int_ty.internal(tables)),
- RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables)),
- RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables)),
+ RigidTy::Int(int_ty) => rustc_ty::TyKind::Int(int_ty.internal(tables, tcx)),
+ RigidTy::Uint(uint_ty) => rustc_ty::TyKind::Uint(uint_ty.internal(tables, tcx)),
+ RigidTy::Float(float_ty) => rustc_ty::TyKind::Float(float_ty.internal(tables, tcx)),
RigidTy::Never => rustc_ty::TyKind::Never,
RigidTy::Array(ty, cnst) => {
- rustc_ty::TyKind::Array(ty.internal(tables), ty_const(cnst, tables))
+ rustc_ty::TyKind::Array(ty.internal(tables, tcx), ty_const(cnst, tables, tcx))
}
RigidTy::Adt(def, args) => {
- rustc_ty::TyKind::Adt(def.internal(tables), args.internal(tables))
+ rustc_ty::TyKind::Adt(def.internal(tables, tcx), args.internal(tables, tcx))
}
RigidTy::Str => rustc_ty::TyKind::Str,
- RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables)),
+ RigidTy::Slice(ty) => rustc_ty::TyKind::Slice(ty.internal(tables, tcx)),
RigidTy::RawPtr(ty, mutability) => rustc_ty::TyKind::RawPtr(rustc_ty::TypeAndMut {
- ty: ty.internal(tables),
- mutbl: mutability.internal(tables),
+ ty: ty.internal(tables, tcx),
+ mutbl: mutability.internal(tables, tcx),
}),
RigidTy::Ref(region, ty, mutability) => rustc_ty::TyKind::Ref(
- region.internal(tables),
- ty.internal(tables),
- mutability.internal(tables),
+ region.internal(tables, tcx),
+ ty.internal(tables, tcx),
+ mutability.internal(tables, tcx),
),
- RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables)),
+ RigidTy::Foreign(def) => rustc_ty::TyKind::Foreign(def.0.internal(tables, tcx)),
RigidTy::FnDef(def, args) => {
- rustc_ty::TyKind::FnDef(def.0.internal(tables), args.internal(tables))
+ rustc_ty::TyKind::FnDef(def.0.internal(tables, tcx), args.internal(tables, tcx))
}
- RigidTy::FnPtr(sig) => rustc_ty::TyKind::FnPtr(sig.internal(tables)),
+ RigidTy::FnPtr(sig) => rustc_ty::TyKind::FnPtr(sig.internal(tables, tcx)),
RigidTy::Closure(def, args) => {
- rustc_ty::TyKind::Closure(def.0.internal(tables), args.internal(tables))
+ rustc_ty::TyKind::Closure(def.0.internal(tables, tcx), args.internal(tables, tcx))
}
RigidTy::Coroutine(def, args, _mov) => {
- rustc_ty::TyKind::Coroutine(def.0.internal(tables), args.internal(tables))
- }
- RigidTy::CoroutineWitness(def, args) => {
- rustc_ty::TyKind::CoroutineWitness(def.0.internal(tables), args.internal(tables))
+ rustc_ty::TyKind::Coroutine(def.0.internal(tables, tcx), args.internal(tables, tcx))
}
+ RigidTy::CoroutineWitness(def, args) => rustc_ty::TyKind::CoroutineWitness(
+ def.0.internal(tables, tcx),
+ args.internal(tables, tcx),
+ ),
RigidTy::Dynamic(predicate, region, dyn_kind) => rustc_ty::TyKind::Dynamic(
- tables.tcx.mk_poly_existential_predicates(&predicate.internal(tables)),
- region.internal(tables),
- dyn_kind.internal(tables),
+ tcx.mk_poly_existential_predicates(&predicate.internal(tables, tcx)),
+ region.internal(tables, tcx),
+ dyn_kind.internal(tables, tcx),
),
RigidTy::Tuple(tys) => {
- rustc_ty::TyKind::Tuple(tables.tcx.mk_type_list(&tys.internal(tables)))
+ rustc_ty::TyKind::Tuple(tcx.mk_type_list(&tys.internal(tables, tcx)))
}
}
}
}
-impl<'tcx> RustcInternal<'tcx> for IntTy {
- type T = rustc_ty::IntTy;
+impl RustcInternal for IntTy {
+ type T<'tcx> = rustc_ty::IntTy;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
IntTy::Isize => rustc_ty::IntTy::Isize,
IntTy::I8 => rustc_ty::IntTy::I8,
@@ -144,10 +146,10 @@ impl<'tcx> RustcInternal<'tcx> for IntTy {
}
}
-impl<'tcx> RustcInternal<'tcx> for UintTy {
- type T = rustc_ty::UintTy;
+impl RustcInternal for UintTy {
+ type T<'tcx> = rustc_ty::UintTy;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
UintTy::Usize => rustc_ty::UintTy::Usize,
UintTy::U8 => rustc_ty::UintTy::U8,
@@ -159,10 +161,10 @@ impl<'tcx> RustcInternal<'tcx> for UintTy {
}
}
-impl<'tcx> RustcInternal<'tcx> for FloatTy {
- type T = rustc_ty::FloatTy;
+impl RustcInternal for FloatTy {
+ type T<'tcx> = rustc_ty::FloatTy;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
FloatTy::F32 => rustc_ty::FloatTy::F32,
FloatTy::F64 => rustc_ty::FloatTy::F64,
@@ -170,10 +172,10 @@ impl<'tcx> RustcInternal<'tcx> for FloatTy {
}
}
-impl<'tcx> RustcInternal<'tcx> for Mutability {
- type T = rustc_ty::Mutability;
+impl RustcInternal for Mutability {
+ type T<'tcx> = rustc_ty::Mutability;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
Mutability::Not => rustc_ty::Mutability::Not,
Mutability::Mut => rustc_ty::Mutability::Mut,
@@ -181,10 +183,10 @@ impl<'tcx> RustcInternal<'tcx> for Mutability {
}
}
-impl<'tcx> RustcInternal<'tcx> for Movability {
- type T = rustc_ty::Movability;
+impl RustcInternal for Movability {
+ type T<'tcx> = rustc_ty::Movability;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
Movability::Static => rustc_ty::Movability::Static,
Movability::Movable => rustc_ty::Movability::Movable,
@@ -192,37 +194,42 @@ impl<'tcx> RustcInternal<'tcx> for Movability {
}
}
-impl<'tcx> RustcInternal<'tcx> for FnSig {
- type T = rustc_ty::FnSig<'tcx>;
+impl RustcInternal for FnSig {
+ type T<'tcx> = rustc_ty::FnSig<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- rustc_ty::FnSig {
- inputs_and_output: tables.tcx.mk_type_list(&self.inputs_and_output.internal(tables)),
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.lift(rustc_ty::FnSig {
+ inputs_and_output: tcx.mk_type_list(&self.inputs_and_output.internal(tables, tcx)),
c_variadic: self.c_variadic,
- unsafety: self.unsafety.internal(tables),
- abi: self.abi.internal(tables),
- }
+ unsafety: self.unsafety.internal(tables, tcx),
+ abi: self.abi.internal(tables, tcx),
+ })
+ .unwrap()
}
}
-impl<'tcx> RustcInternal<'tcx> for VariantIdx {
- type T = rustc_target::abi::VariantIdx;
+impl RustcInternal for VariantIdx {
+ type T<'tcx> = rustc_target::abi::VariantIdx;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
rustc_target::abi::VariantIdx::from(self.to_index())
}
}
-impl<'tcx> RustcInternal<'tcx> for VariantDef {
- type T = &'tcx rustc_ty::VariantDef;
+impl RustcInternal for VariantDef {
+ type T<'tcx> = &'tcx rustc_ty::VariantDef;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- self.adt_def.internal(tables).variant(self.idx.internal(tables))
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ self.adt_def.internal(tables, tcx).variant(self.idx.internal(tables, tcx))
}
}
-fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Const<'tcx> {
- match constant.internal(tables) {
+fn ty_const<'tcx>(
+ constant: &Const,
+ tables: &mut Tables<'_>,
+ tcx: TyCtxt<'tcx>,
+) -> rustc_ty::Const<'tcx> {
+ match constant.internal(tables, tcx) {
rustc_middle::mir::Const::Ty(c) => c,
cnst => {
panic!("Trying to convert constant `{constant:?}` to type constant, but found {cnst:?}")
@@ -230,21 +237,33 @@ fn ty_const<'tcx>(constant: &Const, tables: &mut Tables<'tcx>) -> rustc_ty::Cons
}
}
-impl<'tcx> RustcInternal<'tcx> for Const {
- type T = rustc_middle::mir::Const<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.constants[self.id]
+impl RustcInternal for Const {
+ type T<'tcx> = rustc_middle::mir::Const<'tcx>;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ let constant = tables.constants[self.id];
+ match constant {
+ rustc_middle::mir::Const::Ty(ty) => rustc_middle::mir::Const::Ty(tcx.lift(ty).unwrap()),
+ rustc_middle::mir::Const::Unevaluated(uneval, ty) => {
+ rustc_middle::mir::Const::Unevaluated(
+ tcx.lift(uneval).unwrap(),
+ tcx.lift(ty).unwrap(),
+ )
+ }
+ rustc_middle::mir::Const::Val(const_val, ty) => {
+ rustc_middle::mir::Const::Val(tcx.lift(const_val).unwrap(), tcx.lift(ty).unwrap())
+ }
+ }
}
}
-impl<'tcx> RustcInternal<'tcx> for MonoItem {
- type T = rustc_middle::mir::mono::MonoItem<'tcx>;
+impl RustcInternal for MonoItem {
+ type T<'tcx> = rustc_middle::mir::mono::MonoItem<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
use rustc_middle::mir::mono as rustc_mono;
match self {
- MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables)),
- MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables)),
+ MonoItem::Fn(instance) => rustc_mono::MonoItem::Fn(instance.internal(tables, tcx)),
+ MonoItem::Static(def) => rustc_mono::MonoItem::Static(def.internal(tables, tcx)),
MonoItem::GlobalAsm(_) => {
unimplemented!()
}
@@ -252,55 +271,56 @@ impl<'tcx> RustcInternal<'tcx> for MonoItem {
}
}
-impl<'tcx> RustcInternal<'tcx> for Instance {
- type T = rustc_ty::Instance<'tcx>;
+impl RustcInternal for Instance {
+ type T<'tcx> = rustc_ty::Instance<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.instances[self.def]
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.lift(tables.instances[self.def]).unwrap()
}
}
-impl<'tcx> RustcInternal<'tcx> for StaticDef {
- type T = rustc_span::def_id::DefId;
+impl RustcInternal for StaticDef {
+ type T<'tcx> = rustc_span::def_id::DefId;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- self.0.internal(tables)
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ self.0.internal(tables, tcx)
}
}
#[allow(rustc::usage_of_qualified_ty)]
-impl<'tcx, T> RustcInternal<'tcx> for Binder
+impl RustcInternal for Binder
where
- T: RustcInternal<'tcx>,
- T::T: rustc_ty::TypeVisitable>,
+ T: RustcInternal,
+ for<'tcx> T::T<'tcx>: rustc_ty::TypeVisitable>,
{
- type T = rustc_ty::Binder<'tcx, T::T>;
+ type T<'tcx> = rustc_ty::Binder<'tcx, T::T<'tcx>>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
rustc_ty::Binder::bind_with_vars(
- self.value.internal(tables),
- tables.tcx.mk_bound_variable_kinds_from_iter(
- self.bound_vars.iter().map(|bound| bound.internal(tables)),
+ self.value.internal(tables, tcx),
+ tcx.mk_bound_variable_kinds_from_iter(
+ self.bound_vars.iter().map(|bound| bound.internal(tables, tcx)),
),
)
}
}
-impl<'tcx> RustcInternal<'tcx> for BoundVariableKind {
- type T = rustc_ty::BoundVariableKind;
+impl RustcInternal for BoundVariableKind {
+ type T<'tcx> = rustc_ty::BoundVariableKind;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
BoundVariableKind::Ty(kind) => rustc_ty::BoundVariableKind::Ty(match kind {
BoundTyKind::Anon => rustc_ty::BoundTyKind::Anon,
- BoundTyKind::Param(def, symbol) => {
- rustc_ty::BoundTyKind::Param(def.0.internal(tables), Symbol::intern(symbol))
- }
+ BoundTyKind::Param(def, symbol) => rustc_ty::BoundTyKind::Param(
+ def.0.internal(tables, tcx),
+ Symbol::intern(symbol),
+ ),
}),
BoundVariableKind::Region(kind) => rustc_ty::BoundVariableKind::Region(match kind {
BoundRegionKind::BrAnon => rustc_ty::BoundRegionKind::BrAnon,
BoundRegionKind::BrNamed(def, symbol) => rustc_ty::BoundRegionKind::BrNamed(
- def.0.internal(tables),
+ def.0.internal(tables, tcx),
Symbol::intern(symbol),
),
BoundRegionKind::BrEnv => rustc_ty::BoundRegionKind::BrEnv,
@@ -310,10 +330,10 @@ impl<'tcx> RustcInternal<'tcx> for BoundVariableKind {
}
}
-impl<'tcx> RustcInternal<'tcx> for DynKind {
- type T = rustc_ty::DynKind;
+impl RustcInternal for DynKind {
+ type T<'tcx> = rustc_ty::DynKind;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
DynKind::Dyn => rustc_ty::DynKind::Dyn,
DynKind::DynStar => rustc_ty::DynKind::DynStar,
@@ -321,81 +341,81 @@ impl<'tcx> RustcInternal<'tcx> for DynKind {
}
}
-impl<'tcx> RustcInternal<'tcx> for ExistentialPredicate {
- type T = rustc_ty::ExistentialPredicate<'tcx>;
+impl RustcInternal for ExistentialPredicate {
+ type T<'tcx> = rustc_ty::ExistentialPredicate<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
ExistentialPredicate::Trait(trait_ref) => {
- rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables))
+ rustc_ty::ExistentialPredicate::Trait(trait_ref.internal(tables, tcx))
}
ExistentialPredicate::Projection(proj) => {
- rustc_ty::ExistentialPredicate::Projection(proj.internal(tables))
+ rustc_ty::ExistentialPredicate::Projection(proj.internal(tables, tcx))
}
ExistentialPredicate::AutoTrait(trait_def) => {
- rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables))
+ rustc_ty::ExistentialPredicate::AutoTrait(trait_def.0.internal(tables, tcx))
}
}
}
}
-impl<'tcx> RustcInternal<'tcx> for ExistentialProjection {
- type T = rustc_ty::ExistentialProjection<'tcx>;
+impl RustcInternal for ExistentialProjection {
+ type T<'tcx> = rustc_ty::ExistentialProjection<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
rustc_ty::ExistentialProjection {
- def_id: self.def_id.0.internal(tables),
- args: self.generic_args.internal(tables),
- term: self.term.internal(tables),
+ def_id: self.def_id.0.internal(tables, tcx),
+ args: self.generic_args.internal(tables, tcx),
+ term: self.term.internal(tables, tcx),
}
}
}
-impl<'tcx> RustcInternal<'tcx> for TermKind {
- type T = rustc_ty::Term<'tcx>;
+impl RustcInternal for TermKind {
+ type T<'tcx> = rustc_ty::Term<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
- TermKind::Type(ty) => ty.internal(tables).into(),
- TermKind::Const(const_) => ty_const(const_, tables).into(),
+ TermKind::Type(ty) => ty.internal(tables, tcx).into(),
+ TermKind::Const(const_) => ty_const(const_, tables, tcx).into(),
}
}
}
-impl<'tcx> RustcInternal<'tcx> for ExistentialTraitRef {
- type T = rustc_ty::ExistentialTraitRef<'tcx>;
+impl RustcInternal for ExistentialTraitRef {
+ type T<'tcx> = rustc_ty::ExistentialTraitRef<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
rustc_ty::ExistentialTraitRef {
- def_id: self.def_id.0.internal(tables),
- args: self.generic_args.internal(tables),
+ def_id: self.def_id.0.internal(tables, tcx),
+ args: self.generic_args.internal(tables, tcx),
}
}
}
-impl<'tcx> RustcInternal<'tcx> for TraitRef {
- type T = rustc_ty::TraitRef<'tcx>;
+impl RustcInternal for TraitRef {
+ type T<'tcx> = rustc_ty::TraitRef<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
rustc_ty::TraitRef::new(
- tables.tcx,
- self.def_id.0.internal(tables),
- self.args().internal(tables),
+ tcx,
+ self.def_id.0.internal(tables, tcx),
+ self.args().internal(tables, tcx),
)
}
}
-impl<'tcx> RustcInternal<'tcx> for AllocId {
- type T = rustc_middle::mir::interpret::AllocId;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.alloc_ids[*self]
+impl RustcInternal for AllocId {
+ type T<'tcx> = rustc_middle::mir::interpret::AllocId;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.lift(tables.alloc_ids[*self]).unwrap()
}
}
-impl<'tcx> RustcInternal<'tcx> for ClosureKind {
- type T = rustc_ty::ClosureKind;
+impl RustcInternal for ClosureKind {
+ type T<'tcx> = rustc_ty::ClosureKind;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
ClosureKind::Fn => rustc_ty::ClosureKind::Fn,
ClosureKind::FnMut => rustc_ty::ClosureKind::FnMut,
@@ -404,17 +424,17 @@ impl<'tcx> RustcInternal<'tcx> for ClosureKind {
}
}
-impl<'tcx> RustcInternal<'tcx> for AdtDef {
- type T = rustc_ty::AdtDef<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.tcx.adt_def(self.0.internal(&mut *tables))
+impl RustcInternal for AdtDef {
+ type T<'tcx> = rustc_ty::AdtDef<'tcx>;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.adt_def(self.0.internal(tables, tcx))
}
}
-impl<'tcx> RustcInternal<'tcx> for Abi {
- type T = rustc_target::spec::abi::Abi;
+impl RustcInternal for Abi {
+ type T<'tcx> = rustc_target::spec::abi::Abi;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match *self {
Abi::Rust => rustc_target::spec::abi::Abi::Rust,
Abi::C { unwind } => rustc_target::spec::abi::Abi::C { unwind },
@@ -447,10 +467,10 @@ impl<'tcx> RustcInternal<'tcx> for Abi {
}
}
-impl<'tcx> RustcInternal<'tcx> for Safety {
- type T = rustc_hir::Unsafety;
+impl RustcInternal for Safety {
+ type T<'tcx> = rustc_hir::Unsafety;
- fn internal(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, _tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
match self {
Safety::Unsafe => rustc_hir::Unsafety::Unsafe,
Safety::Normal => rustc_hir::Unsafety::Normal,
@@ -458,51 +478,51 @@ impl<'tcx> RustcInternal<'tcx> for Safety {
}
}
-impl<'tcx> RustcInternal<'tcx> for Span {
- type T = rustc_span::Span;
+impl RustcInternal for Span {
+ type T<'tcx> = rustc_span::Span;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, _tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
tables[*self]
}
}
-impl<'tcx> RustcInternal<'tcx> for Layout {
- type T = rustc_target::abi::Layout<'tcx>;
+impl RustcInternal for Layout {
+ type T<'tcx> = rustc_target::abi::Layout<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.layouts[*self]
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ tcx.lift(tables.layouts[*self]).unwrap()
}
}
-impl<'tcx, T> RustcInternal<'tcx> for &T
+impl RustcInternal for &T
where
- T: RustcInternal<'tcx>,
+ T: RustcInternal,
{
- type T = T::T;
+ type T<'tcx> = T::T<'tcx>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- (*self).internal(tables)
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ (*self).internal(tables, tcx)
}
}
-impl<'tcx, T> RustcInternal<'tcx> for Option
+impl RustcInternal for Option
where
- T: RustcInternal<'tcx>,
+ T: RustcInternal,
{
- type T = Option;
+ type T<'tcx> = Option>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- self.as_ref().map(|inner| inner.internal(tables))
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ self.as_ref().map(|inner| inner.internal(tables, tcx))
}
}
-impl<'tcx, T> RustcInternal<'tcx> for Vec
+impl RustcInternal for Vec
where
- T: RustcInternal<'tcx>,
+ T: RustcInternal,
{
- type T = Vec;
+ type T<'tcx> = Vec>;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T {
- self.iter().map(|e| e.internal(tables)).collect()
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx> {
+ self.iter().map(|e| e.internal(tables, tcx)).collect()
}
}
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index b99640d2f2d6..43987fcf10fc 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -24,12 +24,38 @@ use std::ops::Index;
mod internal;
pub mod pretty;
+/// Convert an internal Rust compiler item into its stable counterpart, if one exists.
+///
+/// # Warning
+///
+/// This function is unstable, and its behavior may change at any point.
+/// E.g.: Items that were previously supported, may no longer be supported, or its translation may
+/// change.
+///
+/// # Panics
+///
+/// This function will panic if StableMIR has not been properly initialized.
pub fn stable<'tcx, S: Stable<'tcx>>(item: S) -> S::T {
with_tables(|tables| item.stable(tables))
}
-pub fn internal<'tcx, S: RustcInternal<'tcx>>(item: S) -> S::T {
- with_tables(|tables| item.internal(tables))
+/// Convert a stable item into its internal Rust compiler counterpart, if one exists.
+///
+/// # Warning
+///
+/// This function is unstable, and it's behavior may change at any point.
+/// Not every stable item can be converted to an internal one.
+/// Furthermore, items that were previously supported, may no longer be supported in newer versions.
+///
+/// # Panics
+///
+/// This function will panic if StableMIR has not been properly initialized.
+pub fn internal<'tcx, S>(tcx: TyCtxt<'tcx>, item: S) -> S::T<'tcx>
+where
+ S: RustcInternal,
+{
+ // The tcx argument ensures that the item won't outlive the type context.
+ with_tables(|tables| item.internal(tables, tcx))
}
impl<'tcx> Index for Tables<'tcx> {
@@ -162,12 +188,12 @@ where
/// Loads the current context and calls a function with it.
/// Do not nest these, as that will ICE.
-pub(crate) fn with_tables<'tcx, R>(f: impl FnOnce(&mut Tables<'tcx>) -> R) -> R {
+pub(crate) fn with_tables(f: impl for<'tcx> FnOnce(&mut Tables<'tcx>) -> R) -> R {
assert!(TLV.is_set());
TLV.with(|tlv| {
let ptr = tlv.get();
assert!(!ptr.is_null());
- let wrapper = ptr as *const TablesWrapper<'tcx>;
+ let wrapper = ptr as *const TablesWrapper<'_>;
let mut tables = unsafe { (*wrapper).0.borrow_mut() };
f(&mut *tables)
})
@@ -393,7 +419,7 @@ impl Index {
- type T;
- fn internal(&self, tables: &mut Tables<'tcx>) -> Self::T;
+pub trait RustcInternal {
+ type T<'tcx>;
+ fn internal<'tcx>(&self, tables: &mut Tables<'_>, tcx: TyCtxt<'tcx>) -> Self::T<'tcx>;
}
diff --git a/compiler/rustc_smir/src/rustc_smir/alloc.rs b/compiler/rustc_smir/src/rustc_smir/alloc.rs
index 48cb164c308a..5d02e3d6e921 100644
--- a/compiler/rustc_smir/src/rustc_smir/alloc.rs
+++ b/compiler/rustc_smir/src/rustc_smir/alloc.rs
@@ -27,7 +27,8 @@ pub fn new_allocation<'tcx>(
const_value: ConstValue<'tcx>,
tables: &mut Tables<'tcx>,
) -> Allocation {
- try_new_allocation(ty, const_value, tables).unwrap()
+ try_new_allocation(ty, const_value, tables)
+ .expect(&format!("Failed to convert: {const_value:?} to {ty:?}"))
}
#[allow(rustc::usage_of_qualified_ty)]
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index fffc454804d2..10085f659b37 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -29,7 +29,7 @@ use stable_mir::{Crate, CrateItem, CrateNum, DefId, Error, Filename, ItemKind, S
use std::cell::RefCell;
use std::iter;
-use crate::rustc_internal::{internal, RustcInternal};
+use crate::rustc_internal::RustcInternal;
use crate::rustc_smir::builder::BodyBuilder;
use crate::rustc_smir::{alloc, new_item_kind, smir_crate, Stable, Tables};
@@ -74,9 +74,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn trait_decls(&self, crate_num: CrateNum) -> stable_mir::TraitDecls {
let mut tables = self.0.borrow_mut();
- tables
- .tcx
- .traits(crate_num.internal(&mut *tables))
+ let tcx = tables.tcx;
+ tcx.traits(crate_num.internal(&mut *tables, tcx))
.iter()
.map(|trait_def_id| tables.trait_def(*trait_def_id))
.collect()
@@ -101,9 +100,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn trait_impls(&self, crate_num: CrateNum) -> stable_mir::ImplTraitDecls {
let mut tables = self.0.borrow_mut();
- tables
- .tcx
- .trait_impls_in_crate(crate_num.internal(&mut *tables))
+ let tcx = tables.tcx;
+ tcx.trait_impls_in_crate(crate_num.internal(&mut *tables, tcx))
.iter()
.map(|impl_def_id| tables.impl_def(*impl_def_id))
.collect()
@@ -229,57 +227,68 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn adt_kind(&self, def: AdtDef) -> AdtKind {
let mut tables = self.0.borrow_mut();
- def.internal(&mut *tables).adt_kind().stable(&mut *tables)
+ let tcx = tables.tcx;
+ def.internal(&mut *tables, tcx).adt_kind().stable(&mut *tables)
}
fn adt_is_box(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
- def.internal(&mut *tables).is_box()
+ let tcx = tables.tcx;
+ def.internal(&mut *tables, tcx).is_box()
}
fn adt_is_simd(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
- def.internal(&mut *tables).repr().simd()
+ let tcx = tables.tcx;
+ def.internal(&mut *tables, tcx).repr().simd()
}
fn adt_is_cstr(&self, def: AdtDef) -> bool {
let mut tables = self.0.borrow_mut();
- let def_id = def.0.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let def_id = def.0.internal(&mut *tables, tcx);
tables.tcx.lang_items().c_str() == Some(def_id)
}
fn fn_sig(&self, def: FnDef, args: &GenericArgs) -> PolyFnSig {
let mut tables = self.0.borrow_mut();
- let def_id = def.0.internal(&mut *tables);
- let sig = tables.tcx.fn_sig(def_id).instantiate(tables.tcx, args.internal(&mut *tables));
+ let tcx = tables.tcx;
+ let def_id = def.0.internal(&mut *tables, tcx);
+ let sig =
+ tables.tcx.fn_sig(def_id).instantiate(tables.tcx, args.internal(&mut *tables, tcx));
sig.stable(&mut *tables)
}
fn closure_sig(&self, args: &GenericArgs) -> PolyFnSig {
let mut tables = self.0.borrow_mut();
- let args_ref = args.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let args_ref = args.internal(&mut *tables, tcx);
let sig = args_ref.as_closure().sig();
sig.stable(&mut *tables)
}
fn adt_variants_len(&self, def: AdtDef) -> usize {
let mut tables = self.0.borrow_mut();
- def.internal(&mut *tables).variants().len()
+ let tcx = tables.tcx;
+ def.internal(&mut *tables, tcx).variants().len()
}
fn variant_name(&self, def: VariantDef) -> Symbol {
let mut tables = self.0.borrow_mut();
- def.internal(&mut *tables).name.to_string()
+ let tcx = tables.tcx;
+ def.internal(&mut *tables, tcx).name.to_string()
}
fn variant_fields(&self, def: VariantDef) -> Vec {
let mut tables = self.0.borrow_mut();
- def.internal(&mut *tables).fields.iter().map(|f| f.stable(&mut *tables)).collect()
+ let tcx = tables.tcx;
+ def.internal(&mut *tables, tcx).fields.iter().map(|f| f.stable(&mut *tables)).collect()
}
fn eval_target_usize(&self, cnst: &Const) -> Result {
let mut tables = self.0.borrow_mut();
- let mir_const = cnst.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let mir_const = cnst.internal(&mut *tables, tcx);
mir_const
.try_eval_target_usize(tables.tcx, ParamEnv::empty())
.ok_or_else(|| Error::new(format!("Const `{cnst:?}` cannot be encoded as u64")))
@@ -299,30 +308,36 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn new_rigid_ty(&self, kind: RigidTy) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
- let internal_kind = kind.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let internal_kind = kind.internal(&mut *tables, tcx);
tables.tcx.mk_ty_from_kind(internal_kind).stable(&mut *tables)
}
fn new_box_ty(&self, ty: stable_mir::ty::Ty) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
- let inner = ty.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let inner = ty.internal(&mut *tables, tcx);
ty::Ty::new_box(tables.tcx, inner).stable(&mut *tables)
}
fn def_ty(&self, item: stable_mir::DefId) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
- tables.tcx.type_of(item.internal(&mut *tables)).instantiate_identity().stable(&mut *tables)
+ let tcx = tables.tcx;
+ tcx.type_of(item.internal(&mut *tables, tcx)).instantiate_identity().stable(&mut *tables)
}
fn def_ty_with_args(&self, item: stable_mir::DefId, args: &GenericArgs) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
- let args = args.internal(&mut *tables);
- let def_ty = tables.tcx.type_of(item.internal(&mut *tables));
+ let tcx = tables.tcx;
+ let args = args.internal(&mut *tables, tcx);
+ let def_ty = tables.tcx.type_of(item.internal(&mut *tables, tcx));
def_ty.instantiate(tables.tcx, args).stable(&mut *tables)
}
fn const_literal(&self, cnst: &stable_mir::ty::Const) -> String {
- internal(cnst).to_string()
+ let mut tables = self.0.borrow_mut();
+ let tcx = tables.tcx;
+ cnst.internal(&mut *tables, tcx).to_string()
}
fn span_of_an_item(&self, def_id: stable_mir::DefId) -> Span {
@@ -337,7 +352,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn rigid_ty_discriminant_ty(&self, ty: &RigidTy) -> stable_mir::ty::Ty {
let mut tables = self.0.borrow_mut();
- let internal_kind = ty.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let internal_kind = ty.internal(&mut *tables, tcx);
let internal_ty = tables.tcx.mk_ty_from_kind(internal_kind);
internal_ty.discriminant_ty(tables.tcx).stable(&mut *tables)
}
@@ -407,8 +423,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
args: &stable_mir::ty::GenericArgs,
) -> Option {
let mut tables = self.0.borrow_mut();
- let def_id = def.0.internal(&mut *tables);
- let args_ref = args.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let def_id = def.0.internal(&mut *tables, tcx);
+ let args_ref = args.internal(&mut *tables, tcx);
match Instance::resolve(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref) {
Ok(Some(instance)) => Some(instance.stable(&mut *tables)),
Ok(None) | Err(_) => None,
@@ -417,7 +434,8 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn resolve_drop_in_place(&self, ty: stable_mir::ty::Ty) -> stable_mir::mir::mono::Instance {
let mut tables = self.0.borrow_mut();
- let internal_ty = ty.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let internal_ty = ty.internal(&mut *tables, tcx);
let instance = Instance::resolve_drop_in_place(tables.tcx, internal_ty);
instance.stable(&mut *tables)
}
@@ -428,8 +446,9 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
args: &GenericArgs,
) -> Option {
let mut tables = self.0.borrow_mut();
- let def_id = def.0.internal(&mut *tables);
- let args_ref = args.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let def_id = def.0.internal(&mut *tables, tcx);
+ let args_ref = args.internal(&mut *tables, tcx);
Instance::resolve_for_fn_ptr(tables.tcx, ParamEnv::reveal_all(), def_id, args_ref)
.stable(&mut *tables)
}
@@ -441,36 +460,44 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
kind: ClosureKind,
) -> Option {
let mut tables = self.0.borrow_mut();
- let def_id = def.0.internal(&mut *tables);
- let args_ref = args.internal(&mut *tables);
- let closure_kind = kind.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let def_id = def.0.internal(&mut *tables, tcx);
+ let args_ref = args.internal(&mut *tables, tcx);
+ let closure_kind = kind.internal(&mut *tables, tcx);
Instance::resolve_closure(tables.tcx, def_id, args_ref, closure_kind).stable(&mut *tables)
}
fn eval_instance(&self, def: InstanceDef, const_ty: Ty) -> Result {
let mut tables = self.0.borrow_mut();
let instance = tables.instances[def];
- let result = tables.tcx.const_eval_instance(
+ let tcx = tables.tcx;
+ let result = tcx.const_eval_instance(
ParamEnv::reveal_all(),
instance,
- Some(tables.tcx.def_span(instance.def_id())),
+ Some(tcx.def_span(instance.def_id())),
);
result
.map(|const_val| {
- alloc::try_new_allocation(const_ty.internal(&mut *tables), const_val, &mut *tables)
+ alloc::try_new_allocation(
+ const_ty.internal(&mut *tables, tcx),
+ const_val,
+ &mut *tables,
+ )
})
.map_err(|e| e.stable(&mut *tables))?
}
fn eval_static_initializer(&self, def: StaticDef) -> Result {
let mut tables = self.0.borrow_mut();
- let def_id = def.0.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let def_id = def.0.internal(&mut *tables, tcx);
tables.tcx.eval_static_initializer(def_id).stable(&mut *tables)
}
fn global_alloc(&self, alloc: stable_mir::mir::alloc::AllocId) -> GlobalAlloc {
let mut tables = self.0.borrow_mut();
- let alloc_id = alloc.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let alloc_id = alloc.internal(&mut *tables, tcx);
tables.tcx.global_alloc(alloc_id).stable(&mut *tables)
}
@@ -480,9 +507,11 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
) -> Option {
let mut tables = self.0.borrow_mut();
let GlobalAlloc::VTable(ty, trait_ref) = global_alloc else { return None };
- let alloc_id = tables
- .tcx
- .vtable_allocation((ty.internal(&mut *tables), trait_ref.internal(&mut *tables)));
+ let tcx = tables.tcx;
+ let alloc_id = tables.tcx.vtable_allocation((
+ ty.internal(&mut *tables, tcx),
+ trait_ref.internal(&mut *tables, tcx),
+ ));
Some(alloc_id.stable(&mut *tables))
}
@@ -510,14 +539,16 @@ impl<'tcx> Context for TablesWrapper<'tcx> {
fn ty_layout(&self, ty: Ty) -> Result {
let mut tables = self.0.borrow_mut();
- let ty = ty.internal(&mut *tables);
+ let tcx = tables.tcx;
+ let ty = ty.internal(&mut *tables, tcx);
let layout = tables.layout_of(ty)?.layout;
Ok(layout.stable(&mut *tables))
}
fn layout_shape(&self, id: Layout) -> LayoutShape {
let mut tables = self.0.borrow_mut();
- id.internal(&mut *tables).0.stable(&mut *tables)
+ let tcx = tables.tcx;
+ id.internal(&mut *tables, tcx).0.stable(&mut *tables)
}
}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
index 632e97b32f52..68b564741dc1 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/abi.rs
@@ -14,7 +14,7 @@ use stable_mir::{opaque, Opaque};
impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
type T = VariantIdx;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
VariantIdx::to_val(self.as_usize())
}
}
@@ -22,7 +22,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::VariantIdx {
impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
type T = stable_mir::target::Endian;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
match self {
rustc_abi::Endian::Little => stable_mir::target::Endian::Little,
rustc_abi::Endian::Big => stable_mir::target::Endian::Big,
@@ -33,7 +33,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
impl<'tcx> Stable<'tcx> for rustc_target::abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
type T = TyAndLayout;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
TyAndLayout { ty: self.ty.stable(tables), layout: self.layout.stable(tables) }
}
}
@@ -41,8 +41,8 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
impl<'tcx> Stable<'tcx> for rustc_target::abi::Layout<'tcx> {
type T = Layout;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.layout_id(*self)
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+ tables.layout_id(tables.tcx.lift(*self).unwrap())
}
}
@@ -51,7 +51,7 @@ impl<'tcx> Stable<'tcx>
{
type T = LayoutShape;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
LayoutShape {
fields: self.fields.stable(tables),
variants: self.variants.stable(tables),
@@ -65,7 +65,7 @@ impl<'tcx> Stable<'tcx>
impl<'tcx> Stable<'tcx> for rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>> {
type T = FnAbi;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
assert!(self.args.len() >= self.fixed_count as usize);
assert!(!self.c_variadic || matches!(self.conv, Conv::C));
FnAbi {
@@ -81,7 +81,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::FnAbi<'tcx, ty::Ty<'tcx>> {
impl<'tcx> Stable<'tcx> for rustc_target::abi::call::ArgAbi<'tcx, ty::Ty<'tcx>> {
type T = ArgAbi;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
ArgAbi {
ty: self.layout.ty.stable(tables),
layout: self.layout.layout.stable(tables),
@@ -93,7 +93,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::ArgAbi<'tcx, ty::Ty<'tcx>>
impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
type T = CallConvention;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
match self {
Conv::C => CallConvention::C,
Conv::Rust => CallConvention::Rust,
@@ -122,7 +122,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::Conv {
impl<'tcx> Stable<'tcx> for rustc_target::abi::call::PassMode {
type T = PassMode;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
match self {
rustc_target::abi::call::PassMode::Ignore => PassMode::Ignore,
rustc_target::abi::call::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
@@ -146,7 +146,7 @@ impl<'tcx> Stable<'tcx> for rustc_target::abi::call::PassMode {
impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape {
type T = FieldsShape;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive,
rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count),
@@ -165,7 +165,7 @@ impl<'tcx> Stable<'tcx>
{
type T = VariantsShape;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
rustc_abi::Variants::Single { index } => {
VariantsShape::Single { index: index.stable(tables) }
@@ -185,7 +185,7 @@ impl<'tcx> Stable<'tcx>
impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding {
type T = TagEncoding;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
rustc_abi::TagEncoding::Direct => TagEncoding::Direct,
rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => {
@@ -202,7 +202,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding Stable<'tcx> for rustc_abi::Abi {
type T = ValueAbi;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match *self {
rustc_abi::Abi::Uninhabited => ValueAbi::Uninhabited,
rustc_abi::Abi::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
@@ -220,7 +220,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Abi {
impl<'tcx> Stable<'tcx> for rustc_abi::Size {
type T = Size;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
self.bytes_usize()
}
}
@@ -228,7 +228,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Size {
impl<'tcx> Stable<'tcx> for rustc_abi::Align {
type T = Align;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
self.bytes()
}
}
@@ -236,7 +236,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Align {
impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
type T = Opaque;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
opaque(self)
}
}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/error.rs b/compiler/rustc_smir/src/rustc_smir/convert/error.rs
index 6c582b799f86..8298450f741f 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/error.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/error.rs
@@ -8,7 +8,7 @@ use rustc_middle::ty::layout::LayoutError;
impl<'tcx> Stable<'tcx> for LayoutError<'tcx> {
type T = stable_mir::Error;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
stable_mir::Error::new(format!("{self:?}"))
}
}
@@ -16,7 +16,7 @@ impl<'tcx> Stable<'tcx> for LayoutError<'tcx> {
impl<'tcx> Stable<'tcx> for AllocError {
type T = stable_mir::Error;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
stable_mir::Error::new(format!("{self:?}"))
}
}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
index 2f3d9d69b858..e433460e2ad9 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mir.rs
@@ -13,7 +13,7 @@ use crate::rustc_smir::{alloc, Stable, Tables};
impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
type T = stable_mir::mir::Body;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::mir::Body::new(
self.basic_blocks
.iter()
@@ -44,7 +44,7 @@ impl<'tcx> Stable<'tcx> for mir::Body<'tcx> {
impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
type T = stable_mir::mir::VarDebugInfo;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::mir::VarDebugInfo {
name: self.name.to_string(),
source_info: self.source_info.stable(tables),
@@ -57,21 +57,21 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfo<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Statement<'tcx> {
type T = stable_mir::mir::Statement;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
Statement { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
}
}
impl<'tcx> Stable<'tcx> for mir::SourceInfo {
type T = stable_mir::mir::SourceInfo;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::mir::SourceInfo { span: self.span.stable(tables), scope: self.scope.into() }
}
}
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
type T = stable_mir::mir::VarDebugInfoFragment;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
VarDebugInfoFragment {
ty: self.ty.stable(tables),
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
@@ -81,7 +81,7 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoFragment<'tcx> {
impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
type T = stable_mir::mir::VarDebugInfoContents;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
mir::VarDebugInfoContents::Place(place) => {
stable_mir::mir::VarDebugInfoContents::Place(place.stable(tables))
@@ -100,7 +100,7 @@ impl<'tcx> Stable<'tcx> for mir::VarDebugInfoContents<'tcx> {
impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
type T = stable_mir::mir::StatementKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
mir::StatementKind::Assign(assign) => stable_mir::mir::StatementKind::Assign(
assign.0.stable(tables),
@@ -158,7 +158,7 @@ impl<'tcx> Stable<'tcx> for mir::StatementKind<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
type T = stable_mir::mir::Rvalue;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::Rvalue::*;
match self {
Use(op) => stable_mir::mir::Rvalue::Use(op.stable(tables)),
@@ -214,7 +214,7 @@ impl<'tcx> Stable<'tcx> for mir::Rvalue<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Mutability {
type T = stable_mir::mir::Mutability;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_hir::Mutability::*;
match *self {
Not => stable_mir::mir::Mutability::Not,
@@ -225,7 +225,7 @@ impl<'tcx> Stable<'tcx> for mir::Mutability {
impl<'tcx> Stable<'tcx> for mir::BorrowKind {
type T = stable_mir::mir::BorrowKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::BorrowKind::*;
match *self {
Shared => stable_mir::mir::BorrowKind::Shared,
@@ -237,7 +237,7 @@ impl<'tcx> Stable<'tcx> for mir::BorrowKind {
impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
type T = stable_mir::mir::MutBorrowKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::MutBorrowKind::*;
match *self {
Default => stable_mir::mir::MutBorrowKind::Default,
@@ -249,7 +249,7 @@ impl<'tcx> Stable<'tcx> for mir::MutBorrowKind {
impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
type T = stable_mir::mir::NullOp;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::NullOp::*;
match self {
SizeOf => stable_mir::mir::NullOp::SizeOf,
@@ -263,7 +263,7 @@ impl<'tcx> Stable<'tcx> for mir::NullOp<'tcx> {
impl<'tcx> Stable<'tcx> for mir::CastKind {
type T = stable_mir::mir::CastKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::CastKind::*;
match self {
PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
@@ -283,7 +283,7 @@ impl<'tcx> Stable<'tcx> for mir::CastKind {
impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
type T = stable_mir::mir::FakeReadCause;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::FakeReadCause::*;
match self {
ForMatchGuard => stable_mir::mir::FakeReadCause::ForMatchGuard,
@@ -299,7 +299,7 @@ impl<'tcx> Stable<'tcx> for mir::FakeReadCause {
impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
type T = stable_mir::mir::Operand;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::Operand::*;
match self {
Copy(place) => stable_mir::mir::Operand::Copy(place.stable(tables)),
@@ -312,7 +312,7 @@ impl<'tcx> Stable<'tcx> for mir::Operand<'tcx> {
impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
type T = stable_mir::mir::Constant;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::mir::Constant {
span: self.span.stable(tables),
user_ty: self.user_ty.map(|u| u.as_usize()).or(None),
@@ -323,7 +323,7 @@ impl<'tcx> Stable<'tcx> for mir::ConstOperand<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
type T = stable_mir::mir::Place;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::mir::Place {
local: self.local.as_usize(),
projection: self.projection.iter().map(|e| e.stable(tables)).collect(),
@@ -333,7 +333,7 @@ impl<'tcx> Stable<'tcx> for mir::Place<'tcx> {
impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
type T = stable_mir::mir::ProjectionElem;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::ProjectionElem::*;
match self {
Deref => stable_mir::mir::ProjectionElem::Deref,
@@ -368,21 +368,21 @@ impl<'tcx> Stable<'tcx> for mir::PlaceElem<'tcx> {
impl<'tcx> Stable<'tcx> for mir::UserTypeProjection {
type T = stable_mir::mir::UserTypeProjection;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
UserTypeProjection { base: self.base.as_usize(), projection: opaque(&self.projs) }
}
}
impl<'tcx> Stable<'tcx> for mir::Local {
type T = stable_mir::mir::Local;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
self.as_usize()
}
}
impl<'tcx> Stable<'tcx> for mir::RetagKind {
type T = stable_mir::mir::RetagKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::RetagKind;
match self {
RetagKind::FnEntry => stable_mir::mir::RetagKind::FnEntry,
@@ -395,7 +395,7 @@ impl<'tcx> Stable<'tcx> for mir::RetagKind {
impl<'tcx> Stable<'tcx> for mir::UnwindAction {
type T = stable_mir::mir::UnwindAction;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::UnwindAction;
match self {
UnwindAction::Continue => stable_mir::mir::UnwindAction::Continue,
@@ -409,7 +409,7 @@ impl<'tcx> Stable<'tcx> for mir::UnwindAction {
impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
type T = stable_mir::mir::NonDivergingIntrinsic;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::NonDivergingIntrinsic;
use stable_mir::mir::CopyNonOverlapping;
match self {
@@ -429,7 +429,7 @@ impl<'tcx> Stable<'tcx> for mir::NonDivergingIntrinsic<'tcx> {
impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
type T = stable_mir::mir::AssertMessage;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::AssertKind;
match self {
AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
@@ -468,7 +468,7 @@ impl<'tcx> Stable<'tcx> for mir::AssertMessage<'tcx> {
impl<'tcx> Stable<'tcx> for mir::BinOp {
type T = stable_mir::mir::BinOp;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::BinOp;
match self {
BinOp::Add => stable_mir::mir::BinOp::Add,
@@ -499,7 +499,7 @@ impl<'tcx> Stable<'tcx> for mir::BinOp {
impl<'tcx> Stable<'tcx> for mir::UnOp {
type T = stable_mir::mir::UnOp;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::UnOp;
match self {
UnOp::Not => stable_mir::mir::UnOp::Not,
@@ -510,7 +510,7 @@ impl<'tcx> Stable<'tcx> for mir::UnOp {
impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
type T = stable_mir::mir::AggregateKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
mir::AggregateKind::Array(ty) => {
stable_mir::mir::AggregateKind::Array(ty.stable(tables))
@@ -544,7 +544,7 @@ impl<'tcx> Stable<'tcx> for mir::AggregateKind<'tcx> {
impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
type T = stable_mir::mir::InlineAsmOperand;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::mir::InlineAsmOperand;
let (in_value, out_place) = match self {
@@ -564,7 +564,7 @@ impl<'tcx> Stable<'tcx> for mir::InlineAsmOperand<'tcx> {
impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
type T = stable_mir::mir::Terminator;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::mir::Terminator;
Terminator { kind: self.kind.stable(tables), span: self.source_info.span.stable(tables) }
}
@@ -572,7 +572,7 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
type T = stable_mir::mir::TerminatorKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::mir::TerminatorKind;
match self {
mir::TerminatorKind::Goto { target } => {
@@ -649,7 +649,7 @@ impl<'tcx> Stable<'tcx> for mir::TerminatorKind<'tcx> {
impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
type T = Allocation;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
self.inner().stable(tables)
}
}
@@ -657,7 +657,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::ConstAllocation<'tcx> {
impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
type T = stable_mir::ty::Allocation;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
alloc::allocation_filter(
self,
alloc_range(rustc_target::abi::Size::ZERO, self.size()),
@@ -668,7 +668,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::Allocation {
impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
type T = stable_mir::mir::alloc::AllocId;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
tables.create_alloc_id(*self)
}
}
@@ -676,7 +676,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::AllocId {
impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
type T = GlobalAlloc;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
mir::interpret::GlobalAlloc::Function(instance) => {
GlobalAlloc::Function(instance.stable(tables))
@@ -695,7 +695,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::GlobalAlloc<'tcx> {
impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
type T = stable_mir::ty::Const;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match *self {
mir::Const::Ty(c) => c.stable(tables),
mir::Const::Unevaluated(unev_const, ty) => {
@@ -706,18 +706,20 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
promoted: unev_const.promoted.map(|u| u.as_u32()),
});
let ty = ty.stable(tables);
- let id = tables.intern_const(*self);
+ let id = tables.intern_const(tables.tcx.lift(*self).unwrap());
Const::new(kind, ty, id)
}
mir::Const::Val(mir::ConstValue::ZeroSized, ty) => {
let ty = ty.stable(tables);
- let id = tables.intern_const(*self);
+ let id = tables.intern_const(tables.tcx.lift(*self).unwrap());
Const::new(ConstantKind::ZeroSized, ty, id)
}
mir::Const::Val(val, ty) => {
+ let ty = tables.tcx.lift(ty).unwrap();
+ let val = tables.tcx.lift(val).unwrap();
let kind = ConstantKind::Allocated(alloc::new_allocation(ty, val, tables));
let ty = ty.stable(tables);
- let id = tables.intern_const(*self);
+ let id = tables.intern_const(tables.tcx.lift(*self).unwrap());
Const::new(kind, ty, id)
}
}
@@ -727,7 +729,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::mir::Const<'tcx> {
impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
type T = Error;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
Error::new(format!("{self:?}"))
}
}
@@ -735,7 +737,7 @@ impl<'tcx> Stable<'tcx> for mir::interpret::ErrorHandled {
impl<'tcx> Stable<'tcx> for MonoItem<'tcx> {
type T = stable_mir::mir::mono::MonoItem;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::mir::mono::MonoItem as StableMonoItem;
match self {
MonoItem::Fn(instance) => StableMonoItem::Fn(instance.stable(tables)),
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
index 2446671770ec..41b0a84dd80f 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/mod.rs
@@ -11,7 +11,7 @@ mod ty;
impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety {
type T = stable_mir::mir::Safety;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
@@ -21,14 +21,14 @@ impl<'tcx> Stable<'tcx> for rustc_hir::Unsafety {
impl<'tcx> Stable<'tcx> for FieldIdx {
type T = usize;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
self.as_usize()
}
}
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
type T = stable_mir::mir::CoroutineSource;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_hir::CoroutineSource;
match self {
CoroutineSource::Block => stable_mir::mir::CoroutineSource::Block,
@@ -40,7 +40,7 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineSource {
impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
type T = stable_mir::mir::CoroutineKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_hir::{CoroutineDesugaring, CoroutineKind};
match *self {
CoroutineKind::Desugared(CoroutineDesugaring::Async, source) => {
@@ -71,7 +71,7 @@ impl<'tcx> Stable<'tcx> for rustc_hir::CoroutineKind {
impl<'tcx> Stable<'tcx> for rustc_span::Symbol {
type T = stable_mir::Symbol;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
self.to_string()
}
}
@@ -79,7 +79,7 @@ impl<'tcx> Stable<'tcx> for rustc_span::Symbol {
impl<'tcx> Stable<'tcx> for rustc_span::Span {
type T = stable_mir::ty::Span;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
tables.create_span(*self)
}
}
diff --git a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
index c0ecbfb99141..cffbdc376f1f 100644
--- a/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
+++ b/compiler/rustc_smir/src/rustc_smir/convert/ty.rs
@@ -11,7 +11,7 @@ use crate::rustc_smir::{alloc, Stable, Tables};
impl<'tcx> Stable<'tcx> for ty::AliasKind {
type T = stable_mir::ty::AliasKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::Projection => stable_mir::ty::AliasKind::Projection,
ty::Inherent => stable_mir::ty::AliasKind::Inherent,
@@ -23,7 +23,7 @@ impl<'tcx> Stable<'tcx> for ty::AliasKind {
impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
type T = stable_mir::ty::AliasTy;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::AliasTy { args, def_id, .. } = self;
stable_mir::ty::AliasTy { def_id: tables.alias_def(*def_id), args: args.stable(tables) }
}
@@ -32,7 +32,7 @@ impl<'tcx> Stable<'tcx> for ty::AliasTy<'tcx> {
impl<'tcx> Stable<'tcx> for ty::DynKind {
type T = stable_mir::ty::DynKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::Dyn => stable_mir::ty::DynKind::Dyn,
ty::DynStar => stable_mir::ty::DynKind::DynStar,
@@ -43,7 +43,7 @@ impl<'tcx> Stable<'tcx> for ty::DynKind {
impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
type T = stable_mir::ty::ExistentialPredicate;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::ExistentialPredicate::*;
match self {
ty::ExistentialPredicate::Trait(existential_trait_ref) => {
@@ -60,7 +60,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialPredicate<'tcx> {
impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
type T = stable_mir::ty::ExistentialTraitRef;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::ExistentialTraitRef { def_id, args } = self;
stable_mir::ty::ExistentialTraitRef {
def_id: tables.trait_def(*def_id),
@@ -72,7 +72,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialTraitRef<'tcx> {
impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
type T = stable_mir::ty::TermKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::TermKind;
match self {
ty::TermKind::Ty(ty) => TermKind::Type(ty.stable(tables)),
@@ -87,7 +87,7 @@ impl<'tcx> Stable<'tcx> for ty::TermKind<'tcx> {
impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
type T = stable_mir::ty::ExistentialProjection;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::ExistentialProjection { def_id, args, term } = self;
stable_mir::ty::ExistentialProjection {
def_id: tables.trait_def(*def_id),
@@ -99,7 +99,7 @@ impl<'tcx> Stable<'tcx> for ty::ExistentialProjection<'tcx> {
impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
type T = stable_mir::mir::PointerCoercion;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::ty::adjustment::PointerCoercion;
match self {
PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
@@ -118,7 +118,7 @@ impl<'tcx> Stable<'tcx> for ty::adjustment::PointerCoercion {
impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex {
type T = usize;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
self.as_usize()
}
}
@@ -126,7 +126,7 @@ impl<'tcx> Stable<'tcx> for ty::UserTypeAnnotationIndex {
impl<'tcx> Stable<'tcx> for ty::AdtKind {
type T = AdtKind;
- fn stable(&self, _tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
match self {
ty::AdtKind::Struct => AdtKind::Struct,
ty::AdtKind::Union => AdtKind::Union,
@@ -138,7 +138,7 @@ impl<'tcx> Stable<'tcx> for ty::AdtKind {
impl<'tcx> Stable<'tcx> for ty::FieldDef {
type T = stable_mir::ty::FieldDef;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
stable_mir::ty::FieldDef {
def: tables.create_def_id(self.did),
name: self.name.stable(tables),
@@ -148,7 +148,7 @@ impl<'tcx> Stable<'tcx> for ty::FieldDef {
impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
type T = stable_mir::ty::GenericArgs;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
GenericArgs(self.iter().map(|arg| arg.unpack().stable(tables)).collect())
}
}
@@ -156,7 +156,7 @@ impl<'tcx> Stable<'tcx> for ty::GenericArgs<'tcx> {
impl<'tcx> Stable<'tcx> for ty::GenericArgKind<'tcx> {
type T = stable_mir::ty::GenericArgKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::GenericArgKind;
match self {
ty::GenericArgKind::Lifetime(region) => GenericArgKind::Lifetime(region.stable(tables)),
@@ -172,7 +172,7 @@ where
{
type T = stable_mir::ty::Binder;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::Binder;
Binder {
@@ -192,7 +192,7 @@ where
{
type T = stable_mir::ty::EarlyBinder;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::EarlyBinder;
EarlyBinder { value: self.as_ref().skip_binder().stable(tables) }
@@ -201,7 +201,7 @@ where
impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
type T = stable_mir::ty::FnSig;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_target::spec::abi;
use stable_mir::ty::{Abi, FnSig};
@@ -245,7 +245,7 @@ impl<'tcx> Stable<'tcx> for ty::FnSig<'tcx> {
impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
type T = stable_mir::ty::BoundTyKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::BoundTyKind;
match self {
@@ -260,7 +260,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundTyKind {
impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
type T = stable_mir::ty::BoundRegionKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::BoundRegionKind;
match self {
@@ -276,7 +276,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundRegionKind {
impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
type T = stable_mir::ty::BoundVariableKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::BoundVariableKind;
match self {
@@ -294,7 +294,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundVariableKind {
impl<'tcx> Stable<'tcx> for ty::IntTy {
type T = IntTy;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::IntTy::Isize => IntTy::Isize,
ty::IntTy::I8 => IntTy::I8,
@@ -309,7 +309,7 @@ impl<'tcx> Stable<'tcx> for ty::IntTy {
impl<'tcx> Stable<'tcx> for ty::UintTy {
type T = UintTy;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::UintTy::Usize => UintTy::Usize,
ty::UintTy::U8 => UintTy::U8,
@@ -324,7 +324,7 @@ impl<'tcx> Stable<'tcx> for ty::UintTy {
impl<'tcx> Stable<'tcx> for ty::FloatTy {
type T = FloatTy;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::FloatTy::F32 => FloatTy::F32,
ty::FloatTy::F64 => FloatTy::F64,
@@ -334,14 +334,14 @@ impl<'tcx> Stable<'tcx> for ty::FloatTy {
impl<'tcx> Stable<'tcx> for Ty<'tcx> {
type T = stable_mir::ty::Ty;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
- tables.intern_ty(*self)
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+ tables.intern_ty(tables.tcx.lift(*self).unwrap())
}
}
impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
type T = stable_mir::ty::TyKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
ty::Bool => TyKind::RigidTy(RigidTy::Bool),
ty::Char => TyKind::RigidTy(RigidTy::Char),
@@ -414,17 +414,22 @@ impl<'tcx> Stable<'tcx> for ty::TyKind<'tcx> {
impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
type T = stable_mir::ty::Const;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let kind = match self.kind() {
ty::Value(val) => {
- let const_val = tables.tcx.valtree_to_const_val((self.ty(), val));
+ let val = match val {
+ ty::ValTree::Leaf(scalar) => ty::ValTree::Leaf(scalar),
+ ty::ValTree::Branch(branch) => {
+ ty::ValTree::Branch(tables.tcx.lift(branch).unwrap())
+ }
+ };
+ let ty = tables.tcx.lift(self.ty()).unwrap();
+ let const_val = tables.tcx.valtree_to_const_val((ty, val));
if matches!(const_val, mir::ConstValue::ZeroSized) {
ConstantKind::ZeroSized
} else {
stable_mir::ty::ConstantKind::Allocated(alloc::new_allocation(
- self.ty(),
- const_val,
- tables,
+ ty, const_val, tables,
))
}
}
@@ -443,14 +448,14 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> {
ty::ExprCt(_) => unimplemented!(),
};
let ty = self.ty().stable(tables);
- let id = tables.intern_const(mir::Const::Ty(*self));
+ let id = tables.intern_const(mir::Const::Ty(tables.tcx.lift(*self).unwrap()));
Const::new(kind, ty, id)
}
}
impl<'tcx> Stable<'tcx> for ty::ParamConst {
type T = stable_mir::ty::ParamConst;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::ParamConst;
ParamConst { index: self.index, name: self.name.to_string() }
}
@@ -458,7 +463,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamConst {
impl<'tcx> Stable<'tcx> for ty::ParamTy {
type T = stable_mir::ty::ParamTy;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::ParamTy;
ParamTy { index: self.index, name: self.name.to_string() }
}
@@ -466,7 +471,7 @@ impl<'tcx> Stable<'tcx> for ty::ParamTy {
impl<'tcx> Stable<'tcx> for ty::BoundTy {
type T = stable_mir::ty::BoundTy;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::BoundTy;
BoundTy { var: self.var.as_usize(), kind: self.kind.stable(tables) }
}
@@ -474,7 +479,7 @@ impl<'tcx> Stable<'tcx> for ty::BoundTy {
impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
type T = stable_mir::ty::TraitSpecializationKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::TraitSpecializationKind;
match self {
@@ -489,7 +494,7 @@ impl<'tcx> Stable<'tcx> for ty::trait_def::TraitSpecializationKind {
impl<'tcx> Stable<'tcx> for ty::TraitDef {
type T = stable_mir::ty::TraitDecl;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::opaque;
use stable_mir::ty::TraitDecl;
@@ -514,7 +519,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitDef {
impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
type T = stable_mir::ty::TraitRef;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::TraitRef;
TraitRef::try_new(tables.trait_def(self.def_id), self.args.stable(tables)).unwrap()
@@ -524,7 +529,7 @@ impl<'tcx> Stable<'tcx> for ty::TraitRef<'tcx> {
impl<'tcx> Stable<'tcx> for ty::Generics {
type T = stable_mir::ty::Generics;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::Generics;
let params: Vec<_> = self.params.iter().map(|param| param.stable(tables)).collect();
@@ -549,7 +554,7 @@ impl<'tcx> Stable<'tcx> for ty::Generics {
impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
type T = stable_mir::ty::GenericParamDefKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::GenericParamDefKind;
match self {
ty::GenericParamDefKind::Lifetime => GenericParamDefKind::Lifetime,
@@ -566,7 +571,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDefKind {
impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
type T = stable_mir::ty::GenericParamDef;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
GenericParamDef {
name: self.name.to_string(),
def_id: tables.generic_def(self.def_id),
@@ -580,7 +585,7 @@ impl<'tcx> Stable<'tcx> for rustc_middle::ty::GenericParamDef {
impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
type T = stable_mir::ty::PredicateKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::ty::PredicateKind;
match self {
PredicateKind::Clause(clause_kind) => {
@@ -614,7 +619,7 @@ impl<'tcx> Stable<'tcx> for ty::PredicateKind<'tcx> {
impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
type T = stable_mir::ty::ClauseKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use rustc_middle::ty::ClauseKind;
match *self {
ClauseKind::Trait(trait_object) => {
@@ -650,7 +655,7 @@ impl<'tcx> Stable<'tcx> for ty::ClauseKind<'tcx> {
impl<'tcx> Stable<'tcx> for ty::ClosureKind {
type T = stable_mir::ty::ClosureKind;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::ty::ClosureKind::*;
match self {
Fn => stable_mir::ty::ClosureKind::Fn,
@@ -663,7 +668,7 @@ impl<'tcx> Stable<'tcx> for ty::ClosureKind {
impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> {
type T = stable_mir::ty::SubtypePredicate;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::SubtypePredicate { a, b, a_is_expected: _ } = self;
stable_mir::ty::SubtypePredicate { a: a.stable(tables), b: b.stable(tables) }
}
@@ -672,7 +677,7 @@ impl<'tcx> Stable<'tcx> for ty::SubtypePredicate<'tcx> {
impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> {
type T = stable_mir::ty::CoercePredicate;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::CoercePredicate { a, b } = self;
stable_mir::ty::CoercePredicate { a: a.stable(tables), b: b.stable(tables) }
}
@@ -681,7 +686,7 @@ impl<'tcx> Stable<'tcx> for ty::CoercePredicate<'tcx> {
impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection {
type T = stable_mir::ty::AliasRelationDirection;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::ty::AliasRelationDirection::*;
match self {
Equate => stable_mir::ty::AliasRelationDirection::Equate,
@@ -693,7 +698,7 @@ impl<'tcx> Stable<'tcx> for ty::AliasRelationDirection {
impl<'tcx> Stable<'tcx> for ty::TraitPredicate<'tcx> {
type T = stable_mir::ty::TraitPredicate;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::TraitPredicate { trait_ref, polarity } = self;
stable_mir::ty::TraitPredicate {
trait_ref: trait_ref.stable(tables),
@@ -709,7 +714,7 @@ where
{
type T = stable_mir::ty::OutlivesPredicate;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::OutlivesPredicate(a, b) = self;
stable_mir::ty::OutlivesPredicate(a.stable(tables), b.stable(tables))
}
@@ -718,7 +723,7 @@ where
impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
type T = stable_mir::ty::ProjectionPredicate;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
let ty::ProjectionPredicate { projection_ty, term } = self;
stable_mir::ty::ProjectionPredicate {
projection_ty: projection_ty.stable(tables),
@@ -730,7 +735,7 @@ impl<'tcx> Stable<'tcx> for ty::ProjectionPredicate<'tcx> {
impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
type T = stable_mir::ty::ImplPolarity;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
use rustc_middle::ty::ImplPolarity::*;
match self {
Positive => stable_mir::ty::ImplPolarity::Positive,
@@ -743,7 +748,7 @@ impl<'tcx> Stable<'tcx> for ty::ImplPolarity {
impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
type T = stable_mir::ty::Region;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
Region { kind: self.kind().stable(tables) }
}
}
@@ -751,7 +756,7 @@ impl<'tcx> Stable<'tcx> for ty::Region<'tcx> {
impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
type T = stable_mir::ty::RegionKind;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
use stable_mir::ty::{BoundRegion, EarlyParamRegion, RegionKind};
match self {
ty::ReEarlyParam(early_reg) => RegionKind::ReEarlyParam(EarlyParamRegion {
@@ -782,8 +787,8 @@ impl<'tcx> Stable<'tcx> for ty::RegionKind<'tcx> {
impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
type T = stable_mir::mir::mono::Instance;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
- let def = tables.instance_def(*self);
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
+ let def = tables.instance_def(tables.tcx.lift(*self).unwrap());
let kind = match self.def {
ty::InstanceDef::Item(..) => stable_mir::mir::mono::InstanceKind::Item,
ty::InstanceDef::Intrinsic(..) => stable_mir::mir::mono::InstanceKind::Intrinsic,
@@ -805,7 +810,7 @@ impl<'tcx> Stable<'tcx> for ty::Instance<'tcx> {
impl<'tcx> Stable<'tcx> for ty::Variance {
type T = stable_mir::mir::Variance;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::Variance::Bivariant => stable_mir::mir::Variance::Bivariant,
ty::Variance::Contravariant => stable_mir::mir::Variance::Contravariant,
@@ -818,7 +823,7 @@ impl<'tcx> Stable<'tcx> for ty::Variance {
impl<'tcx> Stable<'tcx> for ty::Movability {
type T = stable_mir::ty::Movability;
- fn stable(&self, _: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, _: &mut Tables<'_>) -> Self::T {
match self {
ty::Movability::Static => stable_mir::ty::Movability::Static,
ty::Movability::Movable => stable_mir::ty::Movability::Movable,
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index e1ee40c0b60e..bd02e52794c0 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -102,11 +102,11 @@ pub(crate) fn new_item_kind(kind: DefKind) -> ItemKind {
}
/// Trait used to convert between an internal MIR type to a Stable MIR type.
-pub trait Stable<'tcx> {
+pub trait Stable<'cx> {
/// The stable representation of the type implementing Stable.
type T;
/// Converts an object to the equivalent Stable MIR representation.
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T;
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T;
}
impl<'tcx, T> Stable<'tcx> for &T
@@ -115,7 +115,7 @@ where
{
type T = T::T;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
(*self).stable(tables)
}
}
@@ -126,7 +126,7 @@ where
{
type T = Option;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
self.as_ref().map(|value| value.stable(tables))
}
}
@@ -138,7 +138,7 @@ where
{
type T = Result;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
match self {
Ok(val) => Ok(val.stable(tables)),
Err(error) => Err(error.stable(tables)),
@@ -151,7 +151,7 @@ where
T: Stable<'tcx>,
{
type T = Vec;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
self.iter().map(|e| e.stable(tables)).collect()
}
}
@@ -162,7 +162,7 @@ where
U: Stable<'tcx>,
{
type T = (T::T, U::T);
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
(self.0.stable(tables), self.1.stable(tables))
}
}
@@ -172,7 +172,7 @@ where
T: Stable<'tcx>,
{
type T = RangeInclusive;
- fn stable(&self, tables: &mut Tables<'tcx>) -> Self::T {
+ fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
RangeInclusive::new(self.start().stable(tables), self.end().stable(tables))
}
}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 7b0138d50bae..6c39a38750ec 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -600,6 +600,7 @@ symbols! {
core_panic_macro,
coroutine,
coroutine_clone,
+ coroutine_resume,
coroutine_state,
coroutines,
cosf32,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index 532e2cb36e3c..bb1b6ec13902 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -359,7 +359,7 @@ impl IgnoredDiagnosticOption {
option_name: &'static str,
) {
if let (Some(new_item), Some(old_item)) = (new, old) {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
new_item,
@@ -491,7 +491,7 @@ impl<'tcx> OnUnimplementedDirective {
}
if is_diagnostic_namespace_variant {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
vec![item.span()],
@@ -629,7 +629,7 @@ impl<'tcx> OnUnimplementedDirective {
AttrArgs::Eq(span, AttrArgsEq::Hir(expr)) => span.to(expr.span),
};
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
report_span,
@@ -640,14 +640,14 @@ impl<'tcx> OnUnimplementedDirective {
} else if is_diagnostic_namespace_variant {
match &attr.kind {
AttrKind::Normal(p) if !matches!(p.item.args, AttrArgs::Empty) => {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
attr.span,
MalformedOnUnimplementedAttrLint::new(attr.span),
);
}
- _ => tcx.emit_spanned_lint(
+ _ => tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
attr.span,
@@ -776,7 +776,7 @@ impl<'tcx> OnUnimplementedFormatString {
s if generics.params.iter().any(|param| param.name == s) => (),
s => {
if self.is_diagnostic_namespace_variant {
- tcx.emit_spanned_lint(
+ tcx.emit_node_span_lint(
UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
tcx.local_def_id_to_hir_id(item_def_id.expect_local()),
self.span,
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index 6e68dee76a24..3289dfe343e1 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -161,7 +161,7 @@ fn lint_object_unsafe_trait(
) {
// Using `CRATE_NODE_ID` is wrong, but it's hard to get a more precise id.
// It's also hard to get a use site span, so we use the method definition span.
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
WHERE_CLAUSES_OBJECT_SAFETY,
hir::CRATE_HIR_ID,
span,
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 342b12ba4984..12aea88e9b6a 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -9,10 +9,13 @@
use hir::def_id::DefId;
use hir::LangItem;
use rustc_hir as hir;
+use rustc_infer::traits::ObligationCause;
use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams};
use rustc_middle::ty::{self, Ty, TypeVisitableExt};
+use crate::traits;
+use crate::traits::query::evaluate_obligation::InferCtxtExt;
use crate::traits::util;
use super::BuiltinImplConditions;
@@ -723,6 +726,45 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
})
}
+ /// Temporary migration for #89190
+ fn need_migrate_deref_output_trait_object(
+ &mut self,
+ ty: Ty<'tcx>,
+ param_env: ty::ParamEnv<'tcx>,
+ cause: &ObligationCause<'tcx>,
+ ) -> Option> {
+ let tcx = self.tcx();
+ if tcx.features().trait_upcasting {
+ return None;
+ }
+
+ //
+ let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
+
+ let obligation =
+ traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
+ if !self.infcx.predicate_may_hold(&obligation) {
+ return None;
+ }
+
+ self.infcx.probe(|_| {
+ let ty = traits::normalize_projection_type(
+ self,
+ param_env,
+ ty::AliasTy::new(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
+ cause.clone(),
+ 0,
+ // We're *intentionally* throwing these away,
+ // since we don't actually use them.
+ &mut vec![],
+ )
+ .ty()
+ .unwrap();
+
+ if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
+ })
+ }
+
/// Searches for unsizing that might apply to `obligation`.
fn assemble_candidates_for_unsizing(
&mut self,
@@ -780,6 +822,15 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let principal_a = a_data.principal().unwrap();
let target_trait_did = principal_def_id_b.unwrap();
let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
+ if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
+ source,
+ obligation.param_env,
+ &obligation.cause,
+ ) {
+ if deref_trait_ref.def_id() == target_trait_did {
+ return;
+ }
+ }
for (idx, upcast_trait_ref) in
util::supertraits(self.tcx(), source_trait_ref).enumerate()
diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
index b37d9714ddd8..bfc6937a3eb3 100644
--- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs
@@ -387,7 +387,7 @@ fn report_conflicting_impls<'tcx>(
let impl_span = tcx.def_span(impl_def_id);
// Work to be done after we've built the DiagnosticBuilder. We have to define it
- // now because the struct_lint methods don't return back the DiagnosticBuilder
+ // now because the lint emit methods don't return back the DiagnosticBuilder
// that's passed in.
fn decorate<'tcx>(
tcx: TyCtxt<'tcx>,
@@ -462,7 +462,7 @@ fn report_conflicting_impls<'tcx>(
FutureCompatOverlapErrorKind::Issue33140 => ORDER_DEPENDENT_TRAIT_OBJECTS,
FutureCompatOverlapErrorKind::LeakCheck => COHERENCE_LEAK_CHECK,
};
- tcx.struct_span_lint_hir(
+ tcx.node_span_lint(
lint,
tcx.local_def_id_to_hir_id(impl_def_id),
impl_span,
diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs
index 81d5304b8126..e5e31f7caaa2 100644
--- a/compiler/rustc_ty_utils/src/instance.rs
+++ b/compiler/rustc_ty_utils/src/instance.rs
@@ -245,63 +245,6 @@ fn resolve_associated_item<'tcx>(
span: tcx.def_span(trait_item_id),
})
}
- } else if Some(trait_ref.def_id) == lang_items.future_trait() {
- let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
- bug!()
- };
- if Some(trait_item_id) == tcx.lang_items().future_poll_fn() {
- // `Future::poll` is generated by the compiler.
- Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args: args })
- } else {
- // All other methods are default methods of the `Future` trait.
- // (this assumes that `ImplSource::Builtin` is only used for methods on `Future`)
- debug_assert!(tcx.defaultness(trait_item_id).has_value());
- Some(Instance::new(trait_item_id, rcvr_args))
- }
- } else if Some(trait_ref.def_id) == lang_items.iterator_trait() {
- let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
- bug!()
- };
- if Some(trait_item_id) == tcx.lang_items().next_fn() {
- // `Iterator::next` is generated by the compiler.
- Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
- } else {
- // All other methods are default methods of the `Iterator` trait.
- // (this assumes that `ImplSource::Builtin` is only used for methods on `Iterator`)
- debug_assert!(tcx.defaultness(trait_item_id).has_value());
- Some(Instance::new(trait_item_id, rcvr_args))
- }
- } else if Some(trait_ref.def_id) == lang_items.async_iterator_trait() {
- let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
- bug!()
- };
-
- if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::poll_next {
- span_bug!(
- tcx.def_span(coroutine_def_id),
- "no definition for `{trait_ref}::{}` for built-in coroutine type",
- tcx.item_name(trait_item_id)
- )
- }
-
- // `AsyncIterator::poll_next` is generated by the compiler.
- Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
- } else if Some(trait_ref.def_id) == lang_items.coroutine_trait() {
- let ty::Coroutine(coroutine_def_id, args) = *rcvr_args.type_at(0).kind() else {
- bug!()
- };
- if cfg!(debug_assertions) && tcx.item_name(trait_item_id) != sym::resume {
- // For compiler developers who'd like to add new items to `Coroutine`,
- // you either need to generate a shim body, or perhaps return
- // `InstanceDef::Item` pointing to a trait default method body if
- // it is given a default implementation by the trait.
- span_bug!(
- tcx.def_span(coroutine_def_id),
- "no definition for `{trait_ref}::{}` for built-in coroutine type",
- tcx.item_name(trait_item_id)
- )
- }
- Some(Instance { def: ty::InstanceDef::Item(coroutine_def_id), args })
} else if tcx.fn_trait_kind_from_def_id(trait_ref.def_id).is_some() {
// FIXME: This doesn't check for malformed libcore that defines, e.g.,
// `trait Fn { fn call_once(&self) { .. } }`. This is mostly for extension
@@ -334,7 +277,7 @@ fn resolve_associated_item<'tcx>(
),
}
} else {
- None
+ Instance::try_resolve_item_for_coroutine(tcx, trait_item_id, trait_id, rcvr_args)
}
}
traits::ImplSource::Param(..)
diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs
index 263b1449de15..f986df058467 100644
--- a/library/alloc/src/rc.rs
+++ b/library/alloc/src/rc.rs
@@ -1924,7 +1924,7 @@ impl Rc {
// Free the allocation without dropping its contents
let (bptr, alloc) = Box::into_raw_with_allocator(src);
- let src = Box::from_raw(bptr as *mut mem::ManuallyDrop);
+ let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop, alloc.by_ref());
drop(src);
Self::from_ptr_in(ptr, alloc)
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index 5273b3cb2daf..dc82c9c41111 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -1869,7 +1869,7 @@ impl Arc {
// Free the allocation without dropping its contents
let (bptr, alloc) = Box::into_raw_with_allocator(src);
- let src = Box::from_raw(bptr as *mut mem::ManuallyDrop);
+ let src = Box::from_raw_in(bptr as *mut mem::ManuallyDrop, alloc.by_ref());
drop(src);
Self::from_ptr_in(ptr, alloc)
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index 5a783e667521..5dc3c69e4932 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -72,7 +72,7 @@
//! This is handled by the [`InPlaceDrop`] guard for sink items (`U`) and by
//! [`vec::IntoIter::forget_allocation_drop_remaining()`] for remaining source items (`T`).
//!
-//! If dropping any remaining source item (`T`) panics then [`InPlaceDstBufDrop`] will handle dropping
+//! If dropping any remaining source item (`T`) panics then [`InPlaceDstDataSrcBufDrop`] will handle dropping
//! the already collected sink items (`U`) and freeing the allocation.
//!
//! [`vec::IntoIter::forget_allocation_drop_remaining()`]: super::IntoIter::forget_allocation_drop_remaining()
@@ -158,11 +158,12 @@ use crate::alloc::{handle_alloc_error, Global};
use core::alloc::Allocator;
use core::alloc::Layout;
use core::iter::{InPlaceIterable, SourceIter, TrustedRandomAccessNoCoerce};
+use core::marker::PhantomData;
use core::mem::{self, ManuallyDrop, SizedTypeProperties};
use core::num::NonZeroUsize;
use core::ptr::{self, NonNull};
-use super::{InPlaceDrop, InPlaceDstBufDrop, SpecFromIter, SpecFromIterNested, Vec};
+use super::{InPlaceDrop, InPlaceDstDataSrcBufDrop, SpecFromIter, SpecFromIterNested, Vec};
const fn in_place_collectible(
step_merge: Option,
@@ -265,7 +266,7 @@ where
);
}
- // The ownership of the allocation and the new `T` values is temporarily moved into `dst_guard`.
+ // The ownership of the source allocation and the new `T` values is temporarily moved into `dst_guard`.
// This is safe because
// * `forget_allocation_drop_remaining` immediately forgets the allocation
// before any panic can occur in order to avoid any double free, and then proceeds to drop
@@ -276,7 +277,8 @@ where
// Note: This access to the source wouldn't be allowed by the TrustedRandomIteratorNoCoerce
// contract (used by SpecInPlaceCollect below). But see the "O(1) collect" section in the
// module documentation why this is ok anyway.
- let dst_guard = InPlaceDstBufDrop { ptr: dst_buf, len, cap: dst_cap };
+ let dst_guard =
+ InPlaceDstDataSrcBufDrop { ptr: dst_buf, len, src_cap, src: PhantomData:: };
src.forget_allocation_drop_remaining();
// Adjust the allocation if the source had a capacity in bytes that wasn't a multiple
diff --git a/library/alloc/src/vec/in_place_drop.rs b/library/alloc/src/vec/in_place_drop.rs
index 25ca33c6a7bf..40a540b57fc2 100644
--- a/library/alloc/src/vec/in_place_drop.rs
+++ b/library/alloc/src/vec/in_place_drop.rs
@@ -1,6 +1,10 @@
-use core::ptr::{self};
+use core::marker::PhantomData;
+use core::ptr::{self, drop_in_place};
use core::slice::{self};
+use crate::alloc::Global;
+use crate::raw_vec::RawVec;
+
// A helper struct for in-place iteration that drops the destination slice of iteration,
// i.e. the head. The source slice (the tail) is dropped by IntoIter.
pub(super) struct InPlaceDrop {
@@ -23,17 +27,23 @@ impl Drop for InPlaceDrop {
}
}
-// A helper struct for in-place collection that drops the destination allocation and elements,
-// to avoid leaking them if some other destructor panics.
-pub(super) struct InPlaceDstBufDrop {
- pub(super) ptr: *mut T,
+// A helper struct for in-place collection that drops the destination items together with
+// the source allocation - i.e. before the reallocation happened - to avoid leaking them
+// if some other destructor panics.
+pub(super) struct InPlaceDstDataSrcBufDrop {
+ pub(super) ptr: *mut Dest,
pub(super) len: usize,
- pub(super) cap: usize,
+ pub(super) src_cap: usize,
+ pub(super) src: PhantomData,
}
-impl Drop for InPlaceDstBufDrop {
+impl Drop for InPlaceDstDataSrcBufDrop {
#[inline]
fn drop(&mut self) {
- unsafe { super::Vec::from_raw_parts(self.ptr, self.len, self.cap) };
+ unsafe {
+ let _drop_allocation =
+ RawVec::::from_raw_parts_in(self.ptr.cast::(), self.src_cap, Global);
+ drop_in_place(core::ptr::slice_from_raw_parts_mut::(self.ptr, self.len));
+ };
}
}
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index 35ea97bfe609..c82e023fae1a 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -123,7 +123,7 @@ use self::set_len_on_drop::SetLenOnDrop;
mod set_len_on_drop;
#[cfg(not(no_global_oom_handling))]
-use self::in_place_drop::{InPlaceDrop, InPlaceDstBufDrop};
+use self::in_place_drop::{InPlaceDrop, InPlaceDstDataSrcBufDrop};
#[cfg(not(no_global_oom_handling))]
mod in_place_drop;
@@ -2167,6 +2167,12 @@ impl Vec {
/// `[at, len)`. After the call, the original vector will be left containing
/// the elements `[0, at)` with its previous capacity unchanged.
///
+ /// - If you want to take ownership of the entire contents and capacity of
+ /// the vector, see [`mem::take`] or [`mem::replace`].
+ /// - If you don't need the returned vector at all, see [`Vec::truncate`].
+ /// - If you want to take ownership of an arbitrary subslice, or you don't
+ /// necessarily want to store the removed items in a vector, see [`Vec::drain`].
+ ///
/// # Panics
///
/// Panics if `at > len`.
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 0f5e0d99eca1..d5ae8cdac1f4 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1166,10 +1166,14 @@ fn test_from_iter_partially_drained_in_place_specialization() {
#[test]
fn test_from_iter_specialization_with_iterator_adapters() {
fn assert_in_place_trait(_: &T) {}
- let src: Vec = vec![0usize; 256];
+ let owned: Vec = vec![0usize; 256];
+ let refd: Vec<&usize> = owned.iter().collect();
+ let src: Vec<&&usize> = refd.iter().collect();
let srcptr = src.as_ptr();
let iter = src
.into_iter()
+ .copied()
+ .cloned()
.enumerate()
.map(|i| i.0 + i.1)
.zip(std::iter::repeat(1usize))
@@ -1180,7 +1184,7 @@ fn test_from_iter_specialization_with_iterator_adapters() {
assert_in_place_trait(&iter);
let sink = iter.collect::, _>>().unwrap();
let sinkptr = sink.as_ptr();
- assert_eq!(srcptr, sinkptr as *const usize);
+ assert_eq!(srcptr as *const usize, sinkptr as *const usize);
}
#[test]
diff --git a/library/core/benches/iter.rs b/library/core/benches/iter.rs
index 05fec0c4b9d2..c1cec5e6d3c8 100644
--- a/library/core/benches/iter.rs
+++ b/library/core/benches/iter.rs
@@ -391,6 +391,19 @@ fn bench_skip_then_zip(b: &mut Bencher) {
});
}
+#[bench]
+fn bench_skip_trusted_random_access(b: &mut Bencher) {
+ let v: Vec = black_box(vec![42; 10000]);
+ let mut sink = [0; 10000];
+
+ b.iter(|| {
+ for (val, idx) in v.iter().skip(8).zip(0..10000) {
+ sink[idx] += val;
+ }
+ sink
+ });
+}
+
#[bench]
fn bench_filter_count(b: &mut Bencher) {
b.iter(|| (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count())
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index bffd3b2af971..dd0d59f6035a 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -710,7 +710,8 @@ impl Clone for Reverse {
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
/// based on the top-to-bottom declaration order of the struct's members.
///
-/// When `derive`d on enums, variants are ordered by their discriminants.
+/// When `derive`d on enums, variants are ordered primarily by their discriminants.
+/// Secondarily, they are ordered by their fields.
/// By default, the discriminant is smallest for variants at the top, and
/// largest for variants at the bottom. Here's an example:
///
@@ -963,7 +964,8 @@ pub macro Ord($item:item) {
/// [lexicographic](https://en.wikipedia.org/wiki/Lexicographic_order) ordering
/// based on the top-to-bottom declaration order of the struct's members.
///
-/// When `derive`d on enums, variants are ordered by their discriminants.
+/// When `derive`d on enums, variants are primarily ordered by their discriminants.
+/// Secondarily, they are ordered by their fields.
/// By default, the discriminant is smallest for variants at the top, and
/// largest for variants at the bottom. Here's an example:
///
diff --git a/library/core/src/iter/adapters/cloned.rs b/library/core/src/iter/adapters/cloned.rs
index d3cceb8d4ad5..3de91267cf5d 100644
--- a/library/core/src/iter/adapters/cloned.rs
+++ b/library/core/src/iter/adapters/cloned.rs
@@ -1,8 +1,9 @@
use crate::iter::adapters::{
- zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
+ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
-use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator};
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen, UncheckedIterator};
use crate::ops::Try;
+use core::num::NonZeroUsize;
/// An iterator that clones the elements of an underlying iterator.
///
@@ -167,3 +168,23 @@ impl Default for Cloned {
Self::new(Default::default())
}
}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl SourceIter for Cloned
+where
+ I: SourceIter,
+{
+ type Source = I::Source;
+
+ #[inline]
+ unsafe fn as_inner(&mut self) -> &mut I::Source {
+ // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+ unsafe { SourceIter::as_inner(&mut self.it) }
+ }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl InPlaceIterable for Cloned {
+ const EXPAND_BY: Option = I::EXPAND_BY;
+ const MERGE_BY: Option = I::MERGE_BY;
+}
diff --git a/library/core/src/iter/adapters/copied.rs b/library/core/src/iter/adapters/copied.rs
index 7a2c9d839b7e..52a5add1132a 100644
--- a/library/core/src/iter/adapters/copied.rs
+++ b/library/core/src/iter/adapters/copied.rs
@@ -1,7 +1,7 @@
use crate::iter::adapters::{
- zip::try_get_unchecked, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
+ zip::try_get_unchecked, SourceIter, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
};
-use crate::iter::{FusedIterator, TrustedLen};
+use crate::iter::{FusedIterator, InPlaceIterable, TrustedLen};
use crate::mem::MaybeUninit;
use crate::mem::SizedTypeProperties;
use crate::num::NonZeroUsize;
@@ -255,3 +255,23 @@ impl Default for Copied {
Self::new(Default::default())
}
}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl SourceIter for Copied
+where
+ I: SourceIter,
+{
+ type Source = I::Source;
+
+ #[inline]
+ unsafe fn as_inner(&mut self) -> &mut I::Source {
+ // SAFETY: unsafe function forwarding to unsafe function with the same requirements
+ unsafe { SourceIter::as_inner(&mut self.it) }
+ }
+}
+
+#[unstable(issue = "none", feature = "inplace_iteration")]
+unsafe impl InPlaceIterable for Copied {
+ const EXPAND_BY: Option = I::EXPAND_BY;
+ const MERGE_BY: Option = I::MERGE_BY;
+}
diff --git a/library/core/src/iter/adapters/skip.rs b/library/core/src/iter/adapters/skip.rs
index e6c946e7f880..f5188dd458df 100644
--- a/library/core/src/iter/adapters/skip.rs
+++ b/library/core/src/iter/adapters/skip.rs
@@ -1,6 +1,10 @@
use crate::intrinsics::unlikely;
+use crate::iter::adapters::zip::try_get_unchecked;
use crate::iter::TrustedFused;
-use crate::iter::{adapters::SourceIter, FusedIterator, InPlaceIterable};
+use crate::iter::{
+ adapters::SourceIter, FusedIterator, InPlaceIterable, TrustedLen, TrustedRandomAccess,
+ TrustedRandomAccessNoCoerce,
+};
use crate::num::NonZeroUsize;
use crate::ops::{ControlFlow, Try};
@@ -152,6 +156,32 @@ where
NonZeroUsize::new(n).map_or(Ok(()), Err)
}
+
+ #[doc(hidden)]
+ unsafe fn __iterator_get_unchecked(&mut self, idx: usize) -> Self::Item
+ where
+ Self: TrustedRandomAccessNoCoerce,
+ {
+ // SAFETY: the caller must uphold the contract for
+ // `Iterator::__iterator_get_unchecked`.
+ //
+ // Dropping the skipped prefix when index 0 is passed is safe
+ // since
+ // * the caller passing index 0 means that the inner iterator has more items than `self.n`
+ // * TRA contract requires that get_unchecked will only be called once
+ // (unless elements are copyable)
+ // * it does not conflict with in-place iteration since index 0 must be accessed
+ // before something is written into the storage used by the prefix
+ unsafe {
+ if Self::MAY_HAVE_SIDE_EFFECT && idx == 0 {
+ for skipped_idx in 0..self.n {
+ drop(try_get_unchecked(&mut self.iter, skipped_idx));
+ }
+ }
+
+ try_get_unchecked(&mut self.iter, idx + self.n)
+ }
+ }
}
#[stable(feature = "rust1", since = "1.0.0")]
@@ -237,3 +267,23 @@ unsafe impl InPlaceIterable for Skip {
const EXPAND_BY: Option = I::EXPAND_BY;
const MERGE_BY: Option = I::MERGE_BY;
}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl TrustedRandomAccess for Skip where I: TrustedRandomAccess {}
+
+#[doc(hidden)]
+#[unstable(feature = "trusted_random_access", issue = "none")]
+unsafe impl TrustedRandomAccessNoCoerce for Skip
+where
+ I: TrustedRandomAccessNoCoerce,
+{
+ const MAY_HAVE_SIDE_EFFECT: bool = I::MAY_HAVE_SIDE_EFFECT;
+}
+
+// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly.
+// These requirements can only be satisfied when the upper bound of the inner iterator's upper
+// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while
+// I: TrustedLen would not.
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl TrustedLen for Skip where I: Iterator + TrustedRandomAccess {}
diff --git a/library/core/src/iter/adapters/step_by.rs b/library/core/src/iter/adapters/step_by.rs
index 9e83584e3f3d..54ed4c952fb8 100644
--- a/library/core/src/iter/adapters/step_by.rs
+++ b/library/core/src/iter/adapters/step_by.rs
@@ -1,7 +1,7 @@
use crate::convert::TryFrom;
use crate::{
intrinsics,
- iter::{from_fn, TrustedLen},
+ iter::{from_fn, TrustedLen, TrustedRandomAccess},
ops::{Range, Try},
};
@@ -124,6 +124,14 @@ where
#[stable(feature = "iterator_step_by", since = "1.28.0")]
impl ExactSizeIterator for StepBy where I: ExactSizeIterator {}
+// SAFETY: This adapter is shortening. TrustedLen requires the upper bound to be calculated correctly.
+// These requirements can only be satisfied when the upper bound of the inner iterator's upper
+// bound is never `None`. I: TrustedRandomAccess happens to provide this guarantee while
+// I: TrustedLen would not.
+// This also covers the Range specializations since the ranges also implement TRA
+#[unstable(feature = "trusted_len", issue = "37572")]
+unsafe impl TrustedLen for StepBy where I: Iterator + TrustedRandomAccess {}
+
trait SpecRangeSetup {
fn setup(inner: T, step: usize) -> T;
}
@@ -480,12 +488,6 @@ macro_rules! spec_int_ranges {
acc
}
}
-
- /// Safety: This macro is only applied to ranges over types <= usize
- /// which means the inner length is guaranteed to fit into a usize and so
- /// the outer length calculation won't encounter clamped values
- #[unstable(feature = "trusted_len", issue = "37572")]
- unsafe impl TrustedLen for StepBy> {}
)*)
}
diff --git a/library/core/src/iter/sources/repeat_n.rs b/library/core/src/iter/sources/repeat_n.rs
index 0b0445850bf5..db2f8b7ac283 100644
--- a/library/core/src/iter/sources/repeat_n.rs
+++ b/library/core/src/iter/sources/repeat_n.rs
@@ -59,7 +59,6 @@ use crate::num::NonZeroUsize;
/// ```
#[inline]
#[unstable(feature = "iter_repeat_n", issue = "104434")]
-#[doc(hidden)] // waiting on ACP#120 to decide whether to expose publicly
pub fn repeat_n(element: T, count: usize) -> RepeatN {
let mut element = ManuallyDrop::new(element);
@@ -79,7 +78,6 @@ pub fn repeat_n(element: T, count: usize) -> RepeatN {
/// See its documentation for more.
#[derive(Clone, Debug)]
#[unstable(feature = "iter_repeat_n", issue = "104434")]
-#[doc(hidden)] // waiting on ACP#120 to decide whether to expose publicly
pub struct RepeatN {
count: usize,
// Invariant: has been dropped iff count == 0.
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 24ad78efa83b..1dc3f49df38b 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -185,6 +185,7 @@
#![feature(set_ptr_value)]
#![feature(slice_ptr_get)]
#![feature(slice_split_at_unchecked)]
+#![feature(split_at_checked)]
#![feature(str_internals)]
#![feature(str_split_inclusive_remainder)]
#![feature(str_split_remainder)]
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 451a2e14fe95..d052dcc3e6ee 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -1643,6 +1643,10 @@ macro_rules! int_impl {
/// Saturating integer division. Computes `self / rhs`, saturating at the
/// numeric bounds instead of overflowing.
///
+ /// # Panics
+ ///
+ /// This function will panic if `rhs` is 0.
+ ///
/// # Examples
///
/// Basic usage:
@@ -1653,11 +1657,6 @@ macro_rules! int_impl {
#[doc = concat!("assert_eq!(", stringify!($SelfT), "::MIN.saturating_div(-1), ", stringify!($SelfT), "::MAX);")]
///
/// ```
- ///
- /// ```should_panic
- #[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")]
- ///
- /// ```
#[stable(feature = "saturating_div", since = "1.58.0")]
#[rustc_const_stable(feature = "saturating_div", since = "1.58.0")]
#[must_use = "this returns the result of the operation, \
@@ -2435,6 +2434,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
+ #[track_caller]
pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
if unlikely!(rhs == -1) {
(0, self == Self::MIN)
@@ -2674,7 +2674,8 @@ macro_rules! int_impl {
///
/// # Panics
///
- /// This function will panic if `rhs` is 0 or the division results in overflow.
+ /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
+ /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
///
/// # Examples
///
@@ -2694,7 +2695,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn div_euclid(self, rhs: Self) -> Self {
let q = self / rhs;
if self % rhs < 0 {
@@ -2712,7 +2713,8 @@ macro_rules! int_impl {
///
/// # Panics
///
- /// This function will panic if `rhs` is 0 or the division results in overflow.
+ /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
+ /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
///
/// # Examples
///
@@ -2733,7 +2735,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn rem_euclid(self, rhs: Self) -> Self {
let r = self % rhs;
if r < 0 {
@@ -2755,12 +2757,8 @@ macro_rules! int_impl {
///
/// # Panics
///
- /// This function will panic if `rhs` is zero.
- ///
- /// ## Overflow behavior
- ///
- /// On overflow, this function will panic if overflow checks are enabled (default in debug
- /// mode) and wrap if overflow checks are disabled (default in release mode).
+ /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
+ /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
///
/// # Examples
///
@@ -2780,7 +2778,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn div_floor(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
@@ -2795,12 +2793,8 @@ macro_rules! int_impl {
///
/// # Panics
///
- /// This function will panic if `rhs` is zero.
- ///
- /// ## Overflow behavior
- ///
- /// On overflow, this function will panic if overflow checks are enabled (default in debug
- /// mode) and wrap if overflow checks are disabled (default in release mode).
+ /// This function will panic if `rhs` is 0 or if `self` is -1 and `rhs` is
+ /// `Self::MIN`. This behavior is not affected by the `overflow-checks` flag.
///
/// # Examples
///
@@ -2820,7 +2814,7 @@ macro_rules! int_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index e70d043cb2c1..fdfb24330609 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -1531,6 +1531,10 @@ macro_rules! uint_impl {
/// Saturating integer division. Computes `self / rhs`, saturating at the
/// numeric bounds instead of overflowing.
///
+ /// # Panics
+ ///
+ /// This function will panic if `rhs` is 0.
+ ///
/// # Examples
///
/// Basic usage:
@@ -1539,16 +1543,12 @@ macro_rules! uint_impl {
#[doc = concat!("assert_eq!(5", stringify!($SelfT), ".saturating_div(2), 2);")]
///
/// ```
- ///
- /// ```should_panic
- #[doc = concat!("let _ = 1", stringify!($SelfT), ".saturating_div(0);")]
- ///
- /// ```
#[stable(feature = "saturating_div", since = "1.58.0")]
#[rustc_const_stable(feature = "saturating_div", since = "1.58.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
+ #[track_caller]
pub const fn saturating_div(self, rhs: Self) -> Self {
// on unsigned types, there is no overflow in integer division
self.wrapping_div(rhs)
@@ -1683,6 +1683,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
+ #[track_caller]
pub const fn wrapping_div(self, rhs: Self) -> Self {
self / rhs
}
@@ -1712,6 +1713,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
+ #[track_caller]
pub const fn wrapping_div_euclid(self, rhs: Self) -> Self {
self / rhs
}
@@ -1739,6 +1741,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
+ #[track_caller]
pub const fn wrapping_rem(self, rhs: Self) -> Self {
self % rhs
}
@@ -1769,6 +1772,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
+ #[track_caller]
pub const fn wrapping_rem_euclid(self, rhs: Self) -> Self {
self % rhs
}
@@ -2151,6 +2155,7 @@ macro_rules! uint_impl {
#[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
+ #[track_caller]
pub const fn overflowing_div(self, rhs: Self) -> (Self, bool) {
(self / rhs, false)
}
@@ -2181,6 +2186,7 @@ macro_rules! uint_impl {
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
+ #[track_caller]
pub const fn overflowing_div_euclid(self, rhs: Self) -> (Self, bool) {
(self / rhs, false)
}
@@ -2208,6 +2214,7 @@ macro_rules! uint_impl {
#[rustc_const_stable(feature = "const_overflowing_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
+ #[track_caller]
pub const fn overflowing_rem(self, rhs: Self) -> (Self, bool) {
(self % rhs, false)
}
@@ -2238,6 +2245,7 @@ macro_rules! uint_impl {
#[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
#[must_use = "this returns the result of the operation, \
without modifying the original"]
+ #[track_caller]
pub const fn overflowing_rem_euclid(self, rhs: Self) -> (Self, bool) {
(self % rhs, false)
}
@@ -2473,7 +2481,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn div_euclid(self, rhs: Self) -> Self {
self / rhs
}
@@ -2502,7 +2510,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn rem_euclid(self, rhs: Self) -> Self {
self % rhs
}
@@ -2527,6 +2535,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline(always)]
+ #[track_caller]
pub const fn div_floor(self, rhs: Self) -> Self {
self / rhs
}
@@ -2537,11 +2546,6 @@ macro_rules! uint_impl {
///
/// This function will panic if `rhs` is zero.
///
- /// ## Overflow behavior
- ///
- /// On overflow, this function will panic if overflow checks are enabled (default in debug
- /// mode) and wrap if overflow checks are disabled (default in release mode).
- ///
/// # Examples
///
/// Basic usage:
@@ -2554,7 +2558,7 @@ macro_rules! uint_impl {
#[must_use = "this returns the result of the operation, \
without modifying the original"]
#[inline]
- #[rustc_inherit_overflow_checks]
+ #[track_caller]
pub const fn div_ceil(self, rhs: Self) -> Self {
let d = self / rhs;
let r = self % rhs;
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index e58c9068af85..6faded76a4a4 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -111,6 +111,7 @@ pub trait Coroutine {
/// been returned previously. While coroutine literals in the language are
/// guaranteed to panic on resuming after `Complete`, this is not guaranteed
/// for all implementations of the `Coroutine` trait.
+ #[cfg_attr(not(bootstrap), lang = "coroutine_resume")]
fn resume(self: Pin<&mut Self>, arg: R) -> CoroutineState;
}
diff --git a/library/core/src/option.rs b/library/core/src/option.rs
index ce29352ba195..c94e7d73a2ae 100644
--- a/library/core/src/option.rs
+++ b/library/core/src/option.rs
@@ -642,7 +642,7 @@ impl Option {
/// assert_eq!(x.is_none(), true);
/// ```
#[must_use = "if you intended to assert that this doesn't have a value, consider \
- `.and_then(|_| panic!(\"`Option` had a value when expected `None`\"))` instead"]
+ wrapping this in an `assert!()` instead"]
#[inline]
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_option_basics", since = "1.48.0")]
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index c191877c434f..6d0bb924073c 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -1842,7 +1842,8 @@ impl [T] {
///
/// # Panics
///
- /// Panics if `mid > len`.
+ /// Panics if `mid > len`. For a non-panicking alternative see
+ /// [`split_at_checked`](slice::split_at_checked).
///
/// # Examples
///
@@ -1869,14 +1870,15 @@ impl [T] {
/// ```
#[stable(feature = "rust1", since = "1.0.0")]
#[rustc_const_stable(feature = "const_slice_split_at_not_mut", since = "1.71.0")]
+ #[rustc_allow_const_fn_unstable(split_at_checked)]
#[inline]
#[track_caller]
#[must_use]
pub const fn split_at(&self, mid: usize) -> (&[T], &[T]) {
- assert!(mid <= self.len());
- // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
- // fulfills the requirements of `split_at_unchecked`.
- unsafe { self.split_at_unchecked(mid) }
+ match self.split_at_checked(mid) {
+ Some(pair) => pair,
+ None => panic!("mid > len"),
+ }
}
/// Divides one mutable slice into two at an index.
@@ -1887,7 +1889,8 @@ impl [T] {
///
/// # Panics
///
- /// Panics if `mid > len`.
+ /// Panics if `mid > len`. For a non-panicking alternative see
+ /// [`split_at_mut_checked`](slice::split_at_mut_checked).
///
/// # Examples
///
@@ -1906,10 +1909,10 @@ impl [T] {
#[must_use]
#[rustc_const_unstable(feature = "const_slice_split_at_mut", issue = "101804")]
pub const fn split_at_mut(&mut self, mid: usize) -> (&mut [T], &mut [T]) {
- assert!(mid <= self.len());
- // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
- // fulfills the requirements of `from_raw_parts_mut`.
- unsafe { self.split_at_mut_unchecked(mid) }
+ match self.split_at_mut_checked(mid) {
+ Some(pair) => pair,
+ None => panic!("mid > len"),
+ }
}
/// Divides one slice into two at an index, without doing bounds checking.
@@ -2031,6 +2034,98 @@ impl [T] {
unsafe { (from_raw_parts_mut(ptr, mid), from_raw_parts_mut(ptr.add(mid), len - mid)) }
}
+ /// Divides one slice into two at an index, returning `None` if the slice is
+ /// too short.
+ ///
+ /// If `mid ≤ len` returns a pair of slices where the first will contain all
+ /// indices from `[0, mid)` (excluding the index `mid` itself) and the
+ /// second will contain all indices from `[mid, len)` (excluding the index
+ /// `len` itself).
+ ///
+ /// Otherwise, if `mid > len`, returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(split_at_checked)]
+ ///
+ /// let v = [1, -2, 3, -4, 5, -6];
+ ///
+ /// {
+ /// let (left, right) = v.split_at_checked(0).unwrap();
+ /// assert_eq!(left, []);
+ /// assert_eq!(right, [1, -2, 3, -4, 5, -6]);
+ /// }
+ ///
+ /// {
+ /// let (left, right) = v.split_at_checked(2).unwrap();
+ /// assert_eq!(left, [1, -2]);
+ /// assert_eq!(right, [3, -4, 5, -6]);
+ /// }
+ ///
+ /// {
+ /// let (left, right) = v.split_at_checked(6).unwrap();
+ /// assert_eq!(left, [1, -2, 3, -4, 5, -6]);
+ /// assert_eq!(right, []);
+ /// }
+ ///
+ /// assert_eq!(None, v.split_at_checked(7));
+ /// ```
+ #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+ #[rustc_const_unstable(feature = "split_at_checked", issue = "119128")]
+ #[inline]
+ #[must_use]
+ pub const fn split_at_checked(&self, mid: usize) -> Option<(&[T], &[T])> {
+ if mid <= self.len() {
+ // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
+ // fulfills the requirements of `split_at_unchecked`.
+ Some(unsafe { self.split_at_unchecked(mid) })
+ } else {
+ None
+ }
+ }
+
+ /// Divides one mutable slice into two at an index, returning `None` if the
+ /// slice is too short.
+ ///
+ /// If `mid ≤ len` returns a pair of slices where the first will contain all
+ /// indices from `[0, mid)` (excluding the index `mid` itself) and the
+ /// second will contain all indices from `[mid, len)` (excluding the index
+ /// `len` itself).
+ ///
+ /// Otherwise, if `mid > len`, returns `None`.
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(split_at_checked)]
+ ///
+ /// let mut v = [1, 0, 3, 0, 5, 6];
+ ///
+ /// if let Some((left, right)) = v.split_at_mut_checked(2) {
+ /// assert_eq!(left, [1, 0]);
+ /// assert_eq!(right, [3, 0, 5, 6]);
+ /// left[1] = 2;
+ /// right[1] = 4;
+ /// }
+ /// assert_eq!(v, [1, 2, 3, 4, 5, 6]);
+ ///
+ /// assert_eq!(None, v.split_at_mut_checked(7));
+ /// ```
+ #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+ #[rustc_const_unstable(feature = "split_at_checked", issue = "119128")]
+ #[inline]
+ #[must_use]
+ pub const fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut [T], &mut [T])> {
+ if mid <= self.len() {
+ // SAFETY: `[ptr; mid]` and `[mid; len]` are inside `self`, which
+ // fulfills the requirements of `split_at_unchecked`.
+ Some(unsafe { self.split_at_mut_unchecked(mid) })
+ } else {
+ None
+ }
+ }
+
/// Returns an iterator over subslices separated by elements that match
/// `pred`. The matched element is not contained in the subslices.
///
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index a22c46edce25..80c5fe0de8da 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -641,8 +641,9 @@ impl str {
///
/// # Panics
///
- /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
- /// past the end of the last code point of the string slice.
+ /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past
+ /// the end of the last code point of the string slice. For a non-panicking
+ /// alternative see [`split_at_checked`](str::split_at_checked).
///
/// # Examples
///
@@ -658,12 +659,9 @@ impl str {
#[must_use]
#[stable(feature = "str_split_at", since = "1.4.0")]
pub fn split_at(&self, mid: usize) -> (&str, &str) {
- // is_char_boundary checks that the index is in [0, .len()]
- if self.is_char_boundary(mid) {
- // SAFETY: just checked that `mid` is on a char boundary.
- unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) }
- } else {
- slice_error_fail(self, 0, mid)
+ match self.split_at_checked(mid) {
+ None => slice_error_fail(self, 0, mid),
+ Some(pair) => pair,
}
}
@@ -681,8 +679,9 @@ impl str {
///
/// # Panics
///
- /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is
- /// past the end of the last code point of the string slice.
+ /// Panics if `mid` is not on a UTF-8 code point boundary, or if it is past
+ /// the end of the last code point of the string slice. For a non-panicking
+ /// alternative see [`split_at_mut_checked`](str::split_at_mut_checked).
///
/// # Examples
///
@@ -702,20 +701,114 @@ impl str {
pub fn split_at_mut(&mut self, mid: usize) -> (&mut str, &mut str) {
// is_char_boundary checks that the index is in [0, .len()]
if self.is_char_boundary(mid) {
- let len = self.len();
- let ptr = self.as_mut_ptr();
// SAFETY: just checked that `mid` is on a char boundary.
- unsafe {
- (
- from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
- from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
- )
- }
+ unsafe { self.split_at_mut_unchecked(mid) }
} else {
slice_error_fail(self, 0, mid)
}
}
+ /// Divide one string slice into two at an index.
+ ///
+ /// The argument, `mid`, should be a valid byte offset from the start of the
+ /// string. It must also be on the boundary of a UTF-8 code point. The
+ /// method returns `None` if that’s not the case.
+ ///
+ /// The two slices returned go from the start of the string slice to `mid`,
+ /// and from `mid` to the end of the string slice.
+ ///
+ /// To get mutable string slices instead, see the [`split_at_mut_checked`]
+ /// method.
+ ///
+ /// [`split_at_mut_checked`]: str::split_at_mut_checked
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(split_at_checked)]
+ ///
+ /// let s = "Per Martin-Löf";
+ ///
+ /// let (first, last) = s.split_at_checked(3).unwrap();
+ /// assert_eq!("Per", first);
+ /// assert_eq!(" Martin-Löf", last);
+ ///
+ /// assert_eq!(None, s.split_at_checked(13)); // Inside “ö”
+ /// assert_eq!(None, s.split_at_checked(16)); // Beyond the string length
+ /// ```
+ #[inline]
+ #[must_use]
+ #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+ pub fn split_at_checked(&self, mid: usize) -> Option<(&str, &str)> {
+ // is_char_boundary checks that the index is in [0, .len()]
+ if self.is_char_boundary(mid) {
+ // SAFETY: just checked that `mid` is on a char boundary.
+ Some(unsafe { (self.get_unchecked(0..mid), self.get_unchecked(mid..self.len())) })
+ } else {
+ None
+ }
+ }
+
+ /// Divide one mutable string slice into two at an index.
+ ///
+ /// The argument, `mid`, should be a valid byte offset from the start of the
+ /// string. It must also be on the boundary of a UTF-8 code point. The
+ /// method returns `None` if that’s not the case.
+ ///
+ /// The two slices returned go from the start of the string slice to `mid`,
+ /// and from `mid` to the end of the string slice.
+ ///
+ /// To get immutable string slices instead, see the [`split_at_checked`] method.
+ ///
+ /// [`split_at_checked`]: str::split_at_checked
+ ///
+ /// # Examples
+ ///
+ /// ```
+ /// #![feature(split_at_checked)]
+ ///
+ /// let mut s = "Per Martin-Löf".to_string();
+ /// if let Some((first, last)) = s.split_at_mut_checked(3) {
+ /// first.make_ascii_uppercase();
+ /// assert_eq!("PER", first);
+ /// assert_eq!(" Martin-Löf", last);
+ /// }
+ /// assert_eq!("PER Martin-Löf", s);
+ ///
+ /// assert_eq!(None, s.split_at_mut_checked(13)); // Inside “ö”
+ /// assert_eq!(None, s.split_at_mut_checked(16)); // Beyond the string length
+ /// ```
+ #[inline]
+ #[must_use]
+ #[unstable(feature = "split_at_checked", reason = "new API", issue = "119128")]
+ pub fn split_at_mut_checked(&mut self, mid: usize) -> Option<(&mut str, &mut str)> {
+ // is_char_boundary checks that the index is in [0, .len()]
+ if self.is_char_boundary(mid) {
+ // SAFETY: just checked that `mid` is on a char boundary.
+ Some(unsafe { self.split_at_mut_unchecked(mid) })
+ } else {
+ None
+ }
+ }
+
+ /// Divide one string slice into two at an index.
+ ///
+ /// # Safety
+ ///
+ /// The caller must ensure that `mid` is a valid byte offset from the start
+ /// of the string and falls on the boundary of a UTF-8 code point.
+ unsafe fn split_at_mut_unchecked(&mut self, mid: usize) -> (&mut str, &mut str) {
+ let len = self.len();
+ let ptr = self.as_mut_ptr();
+ // SAFETY: caller guarantees `mid` is on a char boundary.
+ unsafe {
+ (
+ from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr, mid)),
+ from_utf8_unchecked_mut(slice::from_raw_parts_mut(ptr.add(mid), len - mid)),
+ )
+ }
+ }
+
/// Returns an iterator over the [`char`]s of a string slice.
///
/// As a string slice consists of valid UTF-8, we can iterate through a
diff --git a/library/core/tests/iter/adapters/step_by.rs b/library/core/tests/iter/adapters/step_by.rs
index 70c9906163ae..b4d61d28cb2e 100644
--- a/library/core/tests/iter/adapters/step_by.rs
+++ b/library/core/tests/iter/adapters/step_by.rs
@@ -220,7 +220,8 @@ fn test_iterator_step_by_size_hint() {
assert_eq!(it.len(), 3);
// Cannot be TrustedLen as a step greater than one makes an iterator
- // with (usize::MAX, None) no longer meet the safety requirements
+ // with (usize::MAX, None) no longer meet the safety requirements.
+ // Exception: The inner iterator is known to have a len() <= usize::MAX
trait TrustedLenCheck {
fn test(self) -> bool;
}
@@ -235,7 +236,9 @@ fn test_iterator_step_by_size_hint() {
}
}
assert!(TrustedLenCheck::test(a.iter()));
- assert!(!TrustedLenCheck::test(a.iter().step_by(1)));
+ assert!(TrustedLenCheck::test(a.iter().step_by(1)));
+ assert!(TrustedLenCheck::test(a.iter().chain(a.iter())));
+ assert!(!TrustedLenCheck::test(a.iter().chain(a.iter()).step_by(1)));
}
#[test]
diff --git a/library/core/tests/iter/range.rs b/library/core/tests/iter/range.rs
index 5b87d6c1fa0e..a6b9f1cb7c88 100644
--- a/library/core/tests/iter/range.rs
+++ b/library/core/tests/iter/range.rs
@@ -474,6 +474,16 @@ fn test_range_inclusive_size_hint() {
assert_eq!((imin..=imax + 1).size_hint(), (usize::MAX, None));
}
+#[test]
+fn test_range_trusted_random_access() {
+ let mut range = 0..10;
+ unsafe {
+ assert_eq!(range.next(), Some(0));
+ assert_eq!(range.__iterator_get_unchecked(0), 1);
+ assert_eq!(range.__iterator_get_unchecked(1), 2);
+ }
+}
+
#[test]
fn test_double_ended_range() {
assert_eq!((11..14).rev().collect::>(), [13, 12, 11]);
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 13fb97fdc7f3..89d2b5ef0938 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -113,6 +113,7 @@
#![feature(slice_flatten)]
#![feature(error_generic_member_access)]
#![feature(error_in_core)]
+#![cfg_attr(not(bootstrap), feature(trait_upcasting))]
#![feature(utf8_chunks)]
#![feature(is_ascii_octdigit)]
#![feature(get_many_mut)]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index ca83e2be5c14..87e89a464bc1 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -191,6 +191,14 @@ impl ToString for TokenStream {
/// Prints the token stream as a string that is supposed to be losslessly convertible back
/// into the same token stream (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
+///
+/// Note: the exact form of the output is subject to change, e.g. there might
+/// be changes in the whitespace used between tokens. Therefore, you should
+/// *not* do any kind of simple substring matching on the output string (as
+/// produced by `to_string`) to implement a proc macro, because that matching
+/// might stop working if such changes happen. Instead, you should work at the
+/// `TokenTree` level, e.g. matching against `TokenTree::Ident`,
+/// `TokenTree::Punct`, or `TokenTree::Literal`.
#[stable(feature = "proc_macro_lib", since = "1.15.0")]
impl fmt::Display for TokenStream {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -758,6 +766,14 @@ impl ToString for TokenTree {
/// Prints the token tree as a string that is supposed to be losslessly convertible back
/// into the same token tree (modulo spans), except for possibly `TokenTree::Group`s
/// with `Delimiter::None` delimiters and negative numeric literals.
+///
+/// Note: the exact form of the output is subject to change, e.g. there might
+/// be changes in the whitespace used between tokens. Therefore, you should
+/// *not* do any kind of simple substring matching on the output string (as
+/// produced by `to_string`) to implement a proc macro, because that matching
+/// might stop working if such changes happen. Instead, you should work at the
+/// `TokenTree` level, e.g. matching against `TokenTree::Ident`,
+/// `TokenTree::Punct`, or `TokenTree::Literal`.
#[stable(feature = "proc_macro_lib2", since = "1.29.0")]
impl fmt::Display for TokenTree {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs
index 8bf1e2dca6f7..ecc0bbce5437 100644
--- a/library/std/src/os/unix/net/listener.rs
+++ b/library/std/src/os/unix/net/listener.rs
@@ -80,7 +80,12 @@ impl UnixListener {
target_os = "horizon"
))]
const backlog: libc::c_int = 128;
- #[cfg(any(target_os = "linux", target_os = "freebsd", target_os = "openbsd"))]
+ #[cfg(any(
+ target_os = "linux",
+ target_os = "freebsd",
+ target_os = "openbsd",
+ target_os = "macos"
+ ))]
const backlog: libc::c_int = -1;
#[cfg(not(any(
target_os = "windows",
@@ -88,6 +93,7 @@ impl UnixListener {
target_os = "linux",
target_os = "freebsd",
target_os = "openbsd",
+ target_os = "macos",
target_os = "espidf",
target_os = "horizon"
)))]
diff --git a/library/std/src/os/xous/ffi.rs b/library/std/src/os/xous/ffi.rs
index 8be7fbb102f3..7fe84db515c3 100644
--- a/library/std/src/os/xous/ffi.rs
+++ b/library/std/src/os/xous/ffi.rs
@@ -88,29 +88,31 @@ fn lend_impl(
let a3 = opcode;
let a4 = data.as_ptr() as usize;
let a5 = data.len();
- let mut a6 = arg1;
- let mut a7 = arg2;
+ let a6 = arg1;
+ let a7 = arg2;
+ let mut ret1;
+ let mut ret2;
unsafe {
core::arch::asm!(
"ecall",
inlateout("a0") a0,
- inlateout("a1") a1 => _,
- inlateout("a2") a2 => _,
+ inlateout("a1") a1 => ret1,
+ inlateout("a2") a2 => ret2,
inlateout("a3") a3 => _,
inlateout("a4") a4 => _,
inlateout("a5") a5 => _,
- inlateout("a6") a6,
- inlateout("a7") a7,
+ inlateout("a6") a6 => _,
+ inlateout("a7") a7 => _,
)
};
let result = a0;
if result == SyscallResult::MemoryReturned as usize {
- Ok((a6, a7))
+ Ok((ret1, ret2))
} else if result == SyscallResult::Error as usize {
- Err(a1.into())
+ Err(ret1.into())
} else {
Err(Error::InternalError)
}
@@ -405,7 +407,7 @@ pub(crate) unsafe fn map_memory(
pub(crate) unsafe fn unmap_memory(range: *mut [T]) -> Result<(), Error> {
let mut a0 = Syscall::UnmapMemory as usize;
let mut a1 = range.as_mut_ptr() as usize;
- let a2 = range.len();
+ let a2 = range.len() * core::mem::size_of::();
let a3 = 0;
let a4 = 0;
let a5 = 0;
@@ -450,7 +452,7 @@ pub(crate) unsafe fn update_memory_flags(
) -> Result<(), Error> {
let mut a0 = Syscall::UpdateMemoryFlags as usize;
let mut a1 = range.as_mut_ptr() as usize;
- let a2 = range.len();
+ let a2 = range.len() * core::mem::size_of::();
let a3 = new_flags.bits();
let a4 = 0; // Process ID is currently None
let a5 = 0;
diff --git a/library/std/src/os/xous/services.rs b/library/std/src/os/xous/services.rs
index 5c219f1fbb95..a75be1b85700 100644
--- a/library/std/src/os/xous/services.rs
+++ b/library/std/src/os/xous/services.rs
@@ -1,9 +1,15 @@
use crate::os::xous::ffi::Connection;
use core::sync::atomic::{AtomicU32, Ordering};
+mod dns;
+pub(crate) use dns::*;
+
mod log;
pub(crate) use log::*;
+mod net;
+pub(crate) use net::*;
+
mod systime;
pub(crate) use systime::*;
diff --git a/library/std/src/os/xous/services/dns.rs b/library/std/src/os/xous/services/dns.rs
new file mode 100644
index 000000000000..a7d88f4892cd
--- /dev/null
+++ b/library/std/src/os/xous/services/dns.rs
@@ -0,0 +1,28 @@
+use crate::os::xous::ffi::Connection;
+use crate::os::xous::services::connect;
+use core::sync::atomic::{AtomicU32, Ordering};
+
+#[repr(usize)]
+pub(crate) enum DnsLendMut {
+ RawLookup = 6,
+}
+
+impl Into for DnsLendMut {
+ fn into(self) -> usize {
+ self as usize
+ }
+}
+
+/// Return a `Connection` to the DNS lookup server. This server is used for
+/// querying domain name values.
+pub(crate) fn dns_server() -> Connection {
+ static DNS_CONNECTION: AtomicU32 = AtomicU32::new(0);
+ let cid = DNS_CONNECTION.load(Ordering::Relaxed);
+ if cid != 0 {
+ return cid.into();
+ }
+
+ let cid = connect("_DNS Resolver Middleware_").unwrap();
+ DNS_CONNECTION.store(cid.into(), Ordering::Relaxed);
+ cid
+}
diff --git a/library/std/src/os/xous/services/log.rs b/library/std/src/os/xous/services/log.rs
index e6bae929eac0..55a501dc7d00 100644
--- a/library/std/src/os/xous/services/log.rs
+++ b/library/std/src/os/xous/services/log.rs
@@ -45,6 +45,17 @@ impl<'a> Into<[usize; 5]> for LogScalar<'a> {
}
}
+pub(crate) enum LogLend {
+ StandardOutput = 1,
+ StandardError = 2,
+}
+
+impl Into for LogLend {
+ fn into(self) -> usize {
+ self as usize
+ }
+}
+
/// Return a `Connection` to the log server, which is used for printing messages to
/// the console and reporting panics. If the log server has not yet started, this
/// will block until the server is running. It is safe to call this multiple times,
diff --git a/library/std/src/os/xous/services/net.rs b/library/std/src/os/xous/services/net.rs
new file mode 100644
index 000000000000..26d337dcef16
--- /dev/null
+++ b/library/std/src/os/xous/services/net.rs
@@ -0,0 +1,95 @@
+use crate::os::xous::ffi::Connection;
+use crate::os::xous::services::connect;
+use core::sync::atomic::{AtomicU32, Ordering};
+
+pub(crate) enum NetBlockingScalar {
+ StdGetTtlUdp(u16 /* fd */), /* 36 */
+ StdSetTtlUdp(u16 /* fd */, u32 /* ttl */), /* 37 */
+ StdGetTtlTcp(u16 /* fd */), /* 36 */
+ StdSetTtlTcp(u16 /* fd */, u32 /* ttl */), /* 37 */
+ StdGetNodelay(u16 /* fd */), /* 38 */
+ StdSetNodelay(u16 /* fd */, bool), /* 39 */
+ StdTcpClose(u16 /* fd */), /* 34 */
+ StdUdpClose(u16 /* fd */), /* 41 */
+ StdTcpStreamShutdown(u16 /* fd */, crate::net::Shutdown /* how */), /* 46 */
+}
+
+pub(crate) enum NetLendMut {
+ StdTcpConnect, /* 30 */
+ StdTcpTx(u16 /* fd */), /* 31 */
+ StdTcpPeek(u16 /* fd */, bool /* nonblocking */), /* 32 */
+ StdTcpRx(u16 /* fd */, bool /* nonblocking */), /* 33 */
+ StdGetAddress(u16 /* fd */), /* 35 */
+ StdUdpBind, /* 40 */
+ StdUdpRx(u16 /* fd */), /* 42 */
+ StdUdpTx(u16 /* fd */), /* 43 */
+ StdTcpListen, /* 44 */
+ StdTcpAccept(u16 /* fd */), /* 45 */
+}
+
+impl Into for NetLendMut {
+ fn into(self) -> usize {
+ match self {
+ NetLendMut::StdTcpConnect => 30,
+ NetLendMut::StdTcpTx(fd) => 31 | ((fd as usize) << 16),
+ NetLendMut::StdTcpPeek(fd, blocking) => {
+ 32 | ((fd as usize) << 16) | if blocking { 0x8000 } else { 0 }
+ }
+ NetLendMut::StdTcpRx(fd, blocking) => {
+ 33 | ((fd as usize) << 16) | if blocking { 0x8000 } else { 0 }
+ }
+ NetLendMut::StdGetAddress(fd) => 35 | ((fd as usize) << 16),
+ NetLendMut::StdUdpBind => 40,
+ NetLendMut::StdUdpRx(fd) => 42 | ((fd as usize) << 16),
+ NetLendMut::StdUdpTx(fd) => 43 | ((fd as usize) << 16),
+ NetLendMut::StdTcpListen => 44,
+ NetLendMut::StdTcpAccept(fd) => 45 | ((fd as usize) << 16),
+ }
+ }
+}
+
+impl<'a> Into<[usize; 5]> for NetBlockingScalar {
+ fn into(self) -> [usize; 5] {
+ match self {
+ NetBlockingScalar::StdGetTtlTcp(fd) => [36 | ((fd as usize) << 16), 0, 0, 0, 0],
+ NetBlockingScalar::StdGetTtlUdp(fd) => [36 | ((fd as usize) << 16), 0, 0, 0, 1],
+ NetBlockingScalar::StdSetTtlTcp(fd, ttl) => {
+ [37 | ((fd as usize) << 16), ttl as _, 0, 0, 0]
+ }
+ NetBlockingScalar::StdSetTtlUdp(fd, ttl) => {
+ [37 | ((fd as usize) << 16), ttl as _, 0, 0, 1]
+ }
+ NetBlockingScalar::StdGetNodelay(fd) => [38 | ((fd as usize) << 16), 0, 0, 0, 0],
+ NetBlockingScalar::StdSetNodelay(fd, enabled) => {
+ [39 | ((fd as usize) << 16), if enabled { 1 } else { 0 }, 0, 0, 1]
+ }
+ NetBlockingScalar::StdTcpClose(fd) => [34 | ((fd as usize) << 16), 0, 0, 0, 0],
+ NetBlockingScalar::StdUdpClose(fd) => [41 | ((fd as usize) << 16), 0, 0, 0, 0],
+ NetBlockingScalar::StdTcpStreamShutdown(fd, how) => [
+ 46 | ((fd as usize) << 16),
+ match how {
+ crate::net::Shutdown::Read => 1,
+ crate::net::Shutdown::Write => 2,
+ crate::net::Shutdown::Both => 3,
+ },
+ 0,
+ 0,
+ 0,
+ ],
+ }
+ }
+}
+
+/// Return a `Connection` to the Network server. This server provides all
+/// OS-level networking functions.
+pub(crate) fn net_server() -> Connection {
+ static NET_CONNECTION: AtomicU32 = AtomicU32::new(0);
+ let cid = NET_CONNECTION.load(Ordering::Relaxed);
+ if cid != 0 {
+ return cid.into();
+ }
+
+ let cid = connect("_Middleware Network Server_").unwrap();
+ NET_CONNECTION.store(cid.into(), Ordering::Relaxed);
+ cid
+}
diff --git a/library/std/src/sys/pal/unix/cmath.rs b/library/std/src/sys/cmath/builtins.rs
similarity index 98%
rename from library/std/src/sys/pal/unix/cmath.rs
rename to library/std/src/sys/cmath/builtins.rs
index 5346d229116f..c680132efa4b 100644
--- a/library/std/src/sys/pal/unix/cmath.rs
+++ b/library/std/src/sys/cmath/builtins.rs
@@ -1,5 +1,3 @@
-#![cfg(not(test))]
-
// These symbols are all defined by `libm`,
// or by `compiler-builtins` on unsupported platforms.
diff --git a/library/std/src/sys/cmath/mod.rs b/library/std/src/sys/cmath/mod.rs
new file mode 100644
index 000000000000..79d5021dd8dc
--- /dev/null
+++ b/library/std/src/sys/cmath/mod.rs
@@ -0,0 +1,11 @@
+#![cfg(not(test))]
+
+cfg_if::cfg_if! {
+ if #[cfg(target_os = "windows")] {
+ mod windows;
+ pub use windows::*;
+ } else {
+ mod builtins;
+ pub use builtins::*;
+ }
+}
diff --git a/library/std/src/sys/pal/windows/cmath.rs b/library/std/src/sys/cmath/windows.rs
similarity index 99%
rename from library/std/src/sys/pal/windows/cmath.rs
rename to library/std/src/sys/cmath/windows.rs
index 36578d5a34e1..712097f06ff3 100644
--- a/library/std/src/sys/pal/windows/cmath.rs
+++ b/library/std/src/sys/cmath/windows.rs
@@ -1,5 +1,3 @@
-#![cfg(not(test))]
-
use core::ffi::{c_double, c_float, c_int};
extern "C" {
diff --git a/library/std/src/sys/mod.rs b/library/std/src/sys/mod.rs
index d95c0d8d0628..e03e98b18d29 100644
--- a/library/std/src/sys/mod.rs
+++ b/library/std/src/sys/mod.rs
@@ -3,9 +3,11 @@
/// descriptors.
mod pal;
-pub mod os_str;
mod personality;
+pub mod cmath;
+pub mod os_str;
+
// FIXME(117276): remove this, move feature implementations into individual
// submodules.
pub use pal::*;
diff --git a/library/std/src/sys/pal/hermit/mod.rs b/library/std/src/sys/pal/hermit/mod.rs
index 503362969196..3c83afa280be 100644
--- a/library/std/src/sys/pal/hermit/mod.rs
+++ b/library/std/src/sys/pal/hermit/mod.rs
@@ -19,8 +19,6 @@ use crate::os::raw::c_char;
pub mod alloc;
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;
diff --git a/library/std/src/sys/pal/sgx/mod.rs b/library/std/src/sys/pal/sgx/mod.rs
index 893c5f765a79..a769fc1ef593 100644
--- a/library/std/src/sys/pal/sgx/mod.rs
+++ b/library/std/src/sys/pal/sgx/mod.rs
@@ -13,8 +13,6 @@ mod waitqueue;
pub mod alloc;
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
pub mod fd;
#[path = "../unsupported/fs.rs"]
diff --git a/library/std/src/sys/pal/solid/mod.rs b/library/std/src/sys/pal/solid/mod.rs
index 5742ce9d72c6..46699e64169f 100644
--- a/library/std/src/sys/pal/solid/mod.rs
+++ b/library/std/src/sys/pal/solid/mod.rs
@@ -21,8 +21,6 @@ mod itron {
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
// `error` is `pub(crate)` so that it can be accessed by `itron/error.rs` as
// `crate::sys::error`
diff --git a/library/std/src/sys/pal/teeos/mod.rs b/library/std/src/sys/pal/teeos/mod.rs
index 764a4e6ad35e..95a5b97ea423 100644
--- a/library/std/src/sys/pal/teeos/mod.rs
+++ b/library/std/src/sys/pal/teeos/mod.rs
@@ -11,8 +11,6 @@ pub use self::rand::hashmap_random_keys;
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
#[path = "../unsupported/env.rs"]
pub mod env;
pub mod locks;
diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs
index fb1a531182a7..9ee753aa1a0c 100644
--- a/library/std/src/sys/pal/uefi/mod.rs
+++ b/library/std/src/sys/pal/uefi/mod.rs
@@ -14,8 +14,6 @@
pub mod alloc;
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;
diff --git a/library/std/src/sys/pal/unix/args.rs b/library/std/src/sys/pal/unix/args.rs
index 9f7dcc0416e5..78e82d9c194c 100644
--- a/library/std/src/sys/pal/unix/args.rs
+++ b/library/std/src/sys/pal/unix/args.rs
@@ -201,9 +201,9 @@ mod imp {
// As _NSGetArgc and _NSGetArgv aren't mentioned in iOS docs
// and use underscores in their names - they're most probably
- // are considered private and therefore should be avoided
- // Here is another way to get arguments using Objective C
- // runtime
+ // are considered private and therefore should be avoided.
+ // Here is another way to get arguments using the Objective-C
+ // runtime.
//
// In general it looks like:
// res = Vec::new()
@@ -213,53 +213,60 @@ mod imp {
// res
#[cfg(any(target_os = "ios", target_os = "tvos", target_os = "watchos"))]
pub fn args() -> Args {
- use crate::ffi::OsString;
+ use crate::ffi::{c_char, c_void, OsString};
use crate::mem;
use crate::str;
+ type Sel = *const c_void;
+ type NsId = *const c_void;
+ type NSUInteger = usize;
+
extern "C" {
- fn sel_registerName(name: *const libc::c_uchar) -> Sel;
- fn objc_getClass(class_name: *const libc::c_uchar) -> NsId;
+ fn sel_registerName(name: *const c_char) -> Sel;
+ fn objc_getClass(class_name: *const c_char) -> NsId;
+
+ // This must be transmuted to an appropriate function pointer type before being called.
+ fn objc_msgSend();
}
- #[cfg(target_arch = "aarch64")]
- extern "C" {
- fn objc_msgSend(obj: NsId, sel: Sel) -> NsId;
- #[allow(clashing_extern_declarations)]
- #[link_name = "objc_msgSend"]
- fn objc_msgSend_ul(obj: NsId, sel: Sel, i: libc::c_ulong) -> NsId;
- }
-
- #[cfg(not(target_arch = "aarch64"))]
- extern "C" {
- fn objc_msgSend(obj: NsId, sel: Sel, ...) -> NsId;
- #[allow(clashing_extern_declarations)]
- #[link_name = "objc_msgSend"]
- fn objc_msgSend_ul(obj: NsId, sel: Sel, ...) -> NsId;
- }
-
- type Sel = *const libc::c_void;
- type NsId = *const libc::c_void;
+ const MSG_SEND_PTR: unsafe extern "C" fn() = objc_msgSend;
+ const MSG_SEND_NO_ARGUMENTS_RETURN_PTR: unsafe extern "C" fn(NsId, Sel) -> *const c_void =
+ unsafe { mem::transmute(MSG_SEND_PTR) };
+ const MSG_SEND_NO_ARGUMENTS_RETURN_NSUINTEGER: unsafe extern "C" fn(
+ NsId,
+ Sel,
+ ) -> NSUInteger = unsafe { mem::transmute(MSG_SEND_PTR) };
+ const MSG_SEND_NSINTEGER_ARGUMENT_RETURN_PTR: unsafe extern "C" fn(
+ NsId,
+ Sel,
+ NSUInteger,
+ )
+ -> *const c_void = unsafe { mem::transmute(MSG_SEND_PTR) };
let mut res = Vec::new();
unsafe {
- let process_info_sel =
- sel_registerName(c"processInfo".as_ptr() as *const libc::c_uchar);
- let arguments_sel = sel_registerName(c"arguments".as_ptr() as *const libc::c_uchar);
- let utf8_sel = sel_registerName(c"UTF8String".as_ptr() as *const libc::c_uchar);
- let count_sel = sel_registerName(c"count".as_ptr() as *const libc::c_uchar);
- let object_at_sel =
- sel_registerName(c"objectAtIndex:".as_ptr() as *const libc::c_uchar);
+ let process_info_sel = sel_registerName(c"processInfo".as_ptr());
+ let arguments_sel = sel_registerName(c"arguments".as_ptr());
+ let count_sel = sel_registerName(c"count".as_ptr());
+ let object_at_index_sel = sel_registerName(c"objectAtIndex:".as_ptr());
+ let utf8string_sel = sel_registerName(c"UTF8String".as_ptr());
- let klass = objc_getClass(c"NSProcessInfo".as_ptr() as *const libc::c_uchar);
- let info = objc_msgSend(klass, process_info_sel);
- let args = objc_msgSend(info, arguments_sel);
+ let klass = objc_getClass(c"NSProcessInfo".as_ptr());
+ // `+[NSProcessInfo processInfo]` returns an object with +0 retain count, so no need to manually `retain/release`.
+ let info = MSG_SEND_NO_ARGUMENTS_RETURN_PTR(klass, process_info_sel);
- let cnt: usize = mem::transmute(objc_msgSend(args, count_sel));
+ // `-[NSProcessInfo arguments]` returns an object with +0 retain count, so no need to manually `retain/release`.
+ let args = MSG_SEND_NO_ARGUMENTS_RETURN_PTR(info, arguments_sel);
+
+ let cnt = MSG_SEND_NO_ARGUMENTS_RETURN_NSUINTEGER(args, count_sel);
for i in 0..cnt {
- let tmp = objc_msgSend_ul(args, object_at_sel, i as libc::c_ulong);
- let utf_c_str: *const libc::c_char = mem::transmute(objc_msgSend(tmp, utf8_sel));
+ // `-[NSArray objectAtIndex:]` returns an object whose lifetime is tied to the array, so no need to manually `retain/release`.
+ let ns_string =
+ MSG_SEND_NSINTEGER_ARGUMENT_RETURN_PTR(args, object_at_index_sel, i);
+ // The lifetime of this pointer is tied to the NSString, as well as the current autorelease pool, which is why we heap-allocate the string below.
+ let utf_c_str: *const c_char =
+ MSG_SEND_NO_ARGUMENTS_RETURN_PTR(ns_string, utf8string_sel).cast();
let bytes = CStr::from_ptr(utf_c_str).to_bytes();
res.push(OsString::from(str::from_utf8(bytes).unwrap()))
}
diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs
index 86027c2b0b0a..43cb9d89be9d 100644
--- a/library/std/src/sys/pal/unix/mod.rs
+++ b/library/std/src/sys/pal/unix/mod.rs
@@ -11,8 +11,6 @@ pub mod weak;
pub mod alloc;
pub mod android;
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;
diff --git a/library/std/src/sys/pal/unsupported/mod.rs b/library/std/src/sys/pal/unsupported/mod.rs
index 6254c67a2a3b..b56ded8579c4 100644
--- a/library/std/src/sys/pal/unsupported/mod.rs
+++ b/library/std/src/sys/pal/unsupported/mod.rs
@@ -2,8 +2,6 @@
pub mod alloc;
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
pub mod fs;
pub mod io;
diff --git a/library/std/src/sys/pal/wasi/mod.rs b/library/std/src/sys/pal/wasi/mod.rs
index c1fc053bf049..4ffc8ecdd67e 100644
--- a/library/std/src/sys/pal/wasi/mod.rs
+++ b/library/std/src/sys/pal/wasi/mod.rs
@@ -20,8 +20,6 @@ use crate::mem;
#[path = "../unix/alloc.rs"]
pub mod alloc;
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
pub mod fd;
pub mod fs;
diff --git a/library/std/src/sys/pal/wasm/mod.rs b/library/std/src/sys/pal/wasm/mod.rs
index d2181565887f..76306b618d82 100644
--- a/library/std/src/sys/pal/wasm/mod.rs
+++ b/library/std/src/sys/pal/wasm/mod.rs
@@ -19,8 +19,6 @@
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
pub mod env;
#[path = "../unsupported/fs.rs"]
pub mod fs;
diff --git a/library/std/src/sys/pal/windows/io.rs b/library/std/src/sys/pal/windows/io.rs
index 649826d25cef..b73d9f3ff4c4 100644
--- a/library/std/src/sys/pal/windows/io.rs
+++ b/library/std/src/sys/pal/windows/io.rs
@@ -97,20 +97,6 @@ unsafe fn handle_is_console(handle: BorrowedHandle<'_>) -> bool {
return true;
}
- // At this point, we *could* have a false negative. We can determine that this is a true
- // negative if we can detect the presence of a console on any of the standard I/O streams. If
- // another stream has a console, then we know we're in a Windows console and can therefore
- // trust the negative.
- for std_handle in [c::STD_INPUT_HANDLE, c::STD_OUTPUT_HANDLE, c::STD_ERROR_HANDLE] {
- let std_handle = c::GetStdHandle(std_handle);
- if !std_handle.is_null()
- && std_handle != handle
- && c::GetConsoleMode(std_handle, &mut out) != 0
- {
- return false;
- }
- }
-
// Otherwise, we fall back to an msys hack to see if we can detect the presence of a pty.
msys_tty_on(handle)
}
diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs
index d097a7b8bb26..364521dba40a 100644
--- a/library/std/src/sys/pal/windows/mod.rs
+++ b/library/std/src/sys/pal/windows/mod.rs
@@ -15,7 +15,6 @@ pub mod compat;
pub mod alloc;
pub mod args;
pub mod c;
-pub mod cmath;
pub mod env;
pub mod fs;
pub mod handle;
diff --git a/library/std/src/sys/pal/xous/alloc.rs b/library/std/src/sys/pal/xous/alloc.rs
index b3a3e691e0d0..0d540e955207 100644
--- a/library/std/src/sys/pal/xous/alloc.rs
+++ b/library/std/src/sys/pal/xous/alloc.rs
@@ -1,7 +1,15 @@
use crate::alloc::{GlobalAlloc, Layout, System};
+#[cfg(not(test))]
+#[export_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"]
static mut DLMALLOC: dlmalloc::Dlmalloc = dlmalloc::Dlmalloc::new();
+#[cfg(test)]
+extern "Rust" {
+ #[link_name = "_ZN16__rust_internals3std3sys4xous5alloc8DLMALLOCE"]
+ static mut DLMALLOC: dlmalloc::Dlmalloc;
+}
+
#[stable(feature = "alloc_system_type", since = "1.28.0")]
unsafe impl GlobalAlloc for System {
#[inline]
diff --git a/library/std/src/sys/pal/xous/locks/condvar.rs b/library/std/src/sys/pal/xous/locks/condvar.rs
index 1bb38dfa3415..510235046e19 100644
--- a/library/std/src/sys/pal/xous/locks/condvar.rs
+++ b/library/std/src/sys/pal/xous/locks/condvar.rs
@@ -1,14 +1,17 @@
use super::mutex::Mutex;
use crate::os::xous::ffi::{blocking_scalar, scalar};
-use crate::os::xous::services::ticktimer_server;
-use crate::sync::Mutex as StdMutex;
+use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
use crate::time::Duration;
+use core::sync::atomic::{AtomicUsize, Ordering};
// The implementation is inspired by Andrew D. Birrell's paper
// "Implementing Condition Variables with Semaphores"
+const NOTIFY_TRIES: usize = 3;
+
pub struct Condvar {
- counter: StdMutex,
+ counter: AtomicUsize,
+ timed_out: AtomicUsize,
}
unsafe impl Send for Condvar {}
@@ -18,94 +21,128 @@ impl Condvar {
#[inline]
#[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> Condvar {
- Condvar { counter: StdMutex::new(0) }
+ Condvar { counter: AtomicUsize::new(0), timed_out: AtomicUsize::new(0) }
+ }
+
+ fn notify_some(&self, to_notify: usize) {
+ // Assumption: The Mutex protecting this condvar is locked throughout the
+ // entirety of this call, preventing calls to `wait` and `wait_timeout`.
+
+ // Logic check: Ensure that there aren't any missing waiters. Remove any that
+ // timed-out, ensuring the counter doesn't underflow.
+ assert!(self.timed_out.load(Ordering::Relaxed) <= self.counter.load(Ordering::Relaxed));
+ self.counter.fetch_sub(self.timed_out.swap(0, Ordering::Relaxed), Ordering::Relaxed);
+
+ // Figure out how many threads to notify. Note that it is impossible for `counter`
+ // to increase during this operation because Mutex is locked. However, it is
+ // possible for `counter` to decrease due to a condvar timing out, in which
+ // case the corresponding `timed_out` will increase accordingly.
+ let Ok(waiter_count) =
+ self.counter.fetch_update(Ordering::Relaxed, Ordering::Relaxed, |counter| {
+ if counter == 0 {
+ return None;
+ } else {
+ Some(counter - counter.min(to_notify))
+ }
+ })
+ else {
+ // No threads are waiting on this condvar
+ return;
+ };
+
+ let mut remaining_to_wake = waiter_count.min(to_notify);
+ if remaining_to_wake == 0 {
+ return;
+ }
+ for _wake_tries in 0..NOTIFY_TRIES {
+ let result = blocking_scalar(
+ ticktimer_server(),
+ TicktimerScalar::NotifyCondition(self.index(), remaining_to_wake).into(),
+ )
+ .expect("failure to send NotifyCondition command");
+
+ // Remove the list of waiters that were notified
+ remaining_to_wake -= result[0];
+
+ // Also remove the number of waiters that timed out. Clamp it to 0 in order to
+ // ensure we don't wait forever in case the waiter woke up between the time
+ // we counted the remaining waiters and now.
+ remaining_to_wake =
+ remaining_to_wake.saturating_sub(self.timed_out.swap(0, Ordering::Relaxed));
+ if remaining_to_wake == 0 {
+ return;
+ }
+ crate::thread::yield_now();
+ }
}
pub fn notify_one(&self) {
- let mut counter = self.counter.lock().unwrap();
- if *counter <= 0 {
- return;
- } else {
- *counter -= 1;
- }
- let result = blocking_scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::NotifyCondition(self.index(), 1).into(),
- );
- drop(counter);
- result.expect("failure to send NotifyCondition command");
+ self.notify_some(1)
}
pub fn notify_all(&self) {
- let mut counter = self.counter.lock().unwrap();
- if *counter <= 0 {
- return;
- }
- let result = blocking_scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::NotifyCondition(self.index(), *counter)
- .into(),
- );
- *counter = 0;
- drop(counter);
-
- result.expect("failure to send NotifyCondition command");
+ self.notify_some(self.counter.load(Ordering::Relaxed))
}
fn index(&self) -> usize {
- self as *const Condvar as usize
+ core::ptr::from_ref(self).addr()
+ }
+
+ /// Unlock the given Mutex and wait for the notification. Wait at most
+ /// `ms` milliseconds, or pass `0` to wait forever.
+ ///
+ /// Returns `true` if the condition was received, `false` if it timed out
+ fn wait_ms(&self, mutex: &Mutex, ms: usize) -> bool {
+ self.counter.fetch_add(1, Ordering::Relaxed);
+ unsafe { mutex.unlock() };
+
+ // Threading concern: There is a chance that the `notify` thread wakes up here before
+ // we have a chance to wait for the condition. This is fine because we've recorded
+ // the fact that we're waiting by incrementing the counter.
+ let result = blocking_scalar(
+ ticktimer_server(),
+ TicktimerScalar::WaitForCondition(self.index(), ms).into(),
+ );
+ let awoken = result.expect("Ticktimer: failure to send WaitForCondition command")[0] == 0;
+
+ // If we awoke due to a timeout, increment the `timed_out` counter so that the
+ // main loop of `notify` knows there's a timeout.
+ //
+ // This is done with the Mutex still unlocked, because the Mutex might still
+ // be locked by the `notify` process above.
+ if !awoken {
+ self.timed_out.fetch_add(1, Ordering::Relaxed);
+ }
+
+ unsafe { mutex.lock() };
+ awoken
}
pub unsafe fn wait(&self, mutex: &Mutex) {
- let mut counter = self.counter.lock().unwrap();
- *counter += 1;
- unsafe { mutex.unlock() };
- drop(counter);
-
- let result = blocking_scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::WaitForCondition(self.index(), 0).into(),
- );
- unsafe { mutex.lock() };
-
- result.expect("Ticktimer: failure to send WaitForCondition command");
+ // Wait for 0 ms, which is a special case to "wait forever"
+ self.wait_ms(mutex, 0);
}
pub unsafe fn wait_timeout(&self, mutex: &Mutex, dur: Duration) -> bool {
- let mut counter = self.counter.lock().unwrap();
- *counter += 1;
- unsafe { mutex.unlock() };
- drop(counter);
-
let mut millis = dur.as_millis() as usize;
+ // Ensure we don't wait for 0 ms, which would cause us to wait forever
if millis == 0 {
millis = 1;
}
-
- let result = blocking_scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::WaitForCondition(self.index(), millis)
- .into(),
- );
- unsafe { mutex.lock() };
-
- let result = result.expect("Ticktimer: failure to send WaitForCondition command")[0] == 0;
-
- // If we awoke due to a timeout, decrement the wake count, as that would not have
- // been done in the `notify()` call.
- if !result {
- *self.counter.lock().unwrap() -= 1;
- }
- result
+ self.wait_ms(mutex, millis)
}
}
impl Drop for Condvar {
fn drop(&mut self) {
- scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::FreeCondition(self.index()).into(),
- )
- .ok();
+ let remaining_count = self.counter.load(Ordering::Relaxed);
+ let timed_out = self.timed_out.load(Ordering::Relaxed);
+ assert!(
+ remaining_count - timed_out == 0,
+ "counter was {} and timed_out was {} not 0",
+ remaining_count,
+ timed_out
+ );
+ scalar(ticktimer_server(), TicktimerScalar::FreeCondition(self.index()).into()).ok();
}
}
diff --git a/library/std/src/sys/pal/xous/locks/mutex.rs b/library/std/src/sys/pal/xous/locks/mutex.rs
index ea51776d54ec..a8c9518ff0bc 100644
--- a/library/std/src/sys/pal/xous/locks/mutex.rs
+++ b/library/std/src/sys/pal/xous/locks/mutex.rs
@@ -1,5 +1,5 @@
-use crate::os::xous::ffi::{blocking_scalar, do_yield, scalar};
-use crate::os::xous::services::ticktimer_server;
+use crate::os::xous::ffi::{blocking_scalar, do_yield};
+use crate::os::xous::services::{ticktimer_server, TicktimerScalar};
use crate::sync::atomic::{AtomicBool, AtomicUsize, Ordering::Relaxed, Ordering::SeqCst};
pub struct Mutex {
@@ -29,7 +29,7 @@ impl Mutex {
}
fn index(&self) -> usize {
- self as *const Mutex as usize
+ core::ptr::from_ref(self).addr()
}
#[inline]
@@ -83,11 +83,8 @@ impl Mutex {
}
// Unblock one thread that is waiting on this message.
- scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::UnlockMutex(self.index()).into(),
- )
- .expect("failure to send UnlockMutex command");
+ blocking_scalar(ticktimer_server(), TicktimerScalar::UnlockMutex(self.index()).into())
+ .expect("failure to send UnlockMutex command");
}
#[inline]
@@ -106,11 +103,8 @@ impl Drop for Mutex {
// If there was Mutex contention, then we involved the ticktimer. Free
// the resources associated with this Mutex as it is deallocated.
if self.contended.load(Relaxed) {
- scalar(
- ticktimer_server(),
- crate::os::xous::services::TicktimerScalar::FreeMutex(self.index()).into(),
- )
- .ok();
+ blocking_scalar(ticktimer_server(), TicktimerScalar::FreeMutex(self.index()).into())
+ .ok();
}
}
}
diff --git a/library/std/src/sys/pal/xous/locks/rwlock.rs b/library/std/src/sys/pal/xous/locks/rwlock.rs
index 618da758adfa..ab45b33e1f69 100644
--- a/library/std/src/sys/pal/xous/locks/rwlock.rs
+++ b/library/std/src/sys/pal/xous/locks/rwlock.rs
@@ -1,5 +1,5 @@
-use crate::os::xous::ffi::do_yield;
-use crate::sync::atomic::{AtomicIsize, Ordering::SeqCst};
+use crate::sync::atomic::{AtomicIsize, Ordering::Acquire};
+use crate::thread::yield_now;
pub struct RwLock {
/// The "mode" value indicates how many threads are waiting on this
@@ -14,6 +14,9 @@ pub struct RwLock {
mode: AtomicIsize,
}
+const RWLOCK_WRITING: isize = -1;
+const RWLOCK_FREE: isize = 0;
+
unsafe impl Send for RwLock {}
unsafe impl Sync for RwLock {}
@@ -21,52 +24,51 @@ impl RwLock {
#[inline]
#[rustc_const_stable(feature = "const_locks", since = "1.63.0")]
pub const fn new() -> RwLock {
- RwLock { mode: AtomicIsize::new(0) }
+ RwLock { mode: AtomicIsize::new(RWLOCK_FREE) }
}
#[inline]
pub unsafe fn read(&self) {
while !unsafe { self.try_read() } {
- do_yield();
+ yield_now();
}
}
#[inline]
pub unsafe fn try_read(&self) -> bool {
- // Non-atomically determine the current value.
- let current = self.mode.load(SeqCst);
-
- // If it's currently locked for writing, then we cannot read.
- if current < 0 {
- return false;
- }
-
- // Attempt to lock. If the `current` value has changed, then this
- // operation will fail and we will not obtain the lock even if we
- // could potentially keep it.
- let new = current + 1;
- self.mode.compare_exchange(current, new, SeqCst, SeqCst).is_ok()
+ self.mode
+ .fetch_update(
+ Acquire,
+ Acquire,
+ |v| if v == RWLOCK_WRITING { None } else { Some(v + 1) },
+ )
+ .is_ok()
}
#[inline]
pub unsafe fn write(&self) {
while !unsafe { self.try_write() } {
- do_yield();
+ yield_now();
}
}
#[inline]
pub unsafe fn try_write(&self) -> bool {
- self.mode.compare_exchange(0, -1, SeqCst, SeqCst).is_ok()
+ self.mode.compare_exchange(RWLOCK_FREE, RWLOCK_WRITING, Acquire, Acquire).is_ok()
}
#[inline]
pub unsafe fn read_unlock(&self) {
- self.mode.fetch_sub(1, SeqCst);
+ let previous = self.mode.fetch_sub(1, Acquire);
+ assert!(previous != RWLOCK_FREE);
+ assert!(previous != RWLOCK_WRITING);
}
#[inline]
pub unsafe fn write_unlock(&self) {
- assert_eq!(self.mode.compare_exchange(-1, 0, SeqCst, SeqCst), Ok(-1));
+ assert_eq!(
+ self.mode.compare_exchange(RWLOCK_WRITING, RWLOCK_FREE, Acquire, Acquire),
+ Ok(RWLOCK_WRITING)
+ );
}
}
diff --git a/library/std/src/sys/pal/xous/mod.rs b/library/std/src/sys/pal/xous/mod.rs
index 230067907c8f..b4948d7e583b 100644
--- a/library/std/src/sys/pal/xous/mod.rs
+++ b/library/std/src/sys/pal/xous/mod.rs
@@ -3,8 +3,6 @@
pub mod alloc;
#[path = "../unsupported/args.rs"]
pub mod args;
-#[path = "../unix/cmath.rs"]
-pub mod cmath;
#[path = "../unsupported/env.rs"]
pub mod env;
#[path = "../unsupported/fs.rs"]
@@ -12,10 +10,7 @@ pub mod fs;
#[path = "../unsupported/io.rs"]
pub mod io;
pub mod locks;
-#[path = "../unsupported/net.rs"]
pub mod net;
-#[path = "../unsupported/once.rs"]
-pub mod once;
pub mod os;
#[path = "../unix/path.rs"]
pub mod path;
diff --git a/library/std/src/sys/pal/xous/net/dns.rs b/library/std/src/sys/pal/xous/net/dns.rs
new file mode 100644
index 000000000000..63056324bfbd
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/dns.rs
@@ -0,0 +1,127 @@
+use crate::io;
+use crate::net::{Ipv4Addr, SocketAddr, SocketAddrV4, SocketAddrV6};
+use crate::os::xous::ffi::lend_mut;
+use crate::os::xous::services::{dns_server, DnsLendMut};
+use core::convert::{TryFrom, TryInto};
+
+pub struct DnsError {
+ pub code: u8,
+}
+
+#[repr(C, align(4096))]
+struct LookupHostQuery([u8; 4096]);
+
+pub struct LookupHost {
+ data: LookupHostQuery,
+ port: u16,
+ offset: usize,
+ count: usize,
+}
+
+impl LookupHost {
+ pub fn port(&self) -> u16 {
+ self.port
+ }
+}
+
+impl Iterator for LookupHost {
+ type Item = SocketAddr;
+ fn next(&mut self) -> Option {
+ if self.offset >= self.data.0.len() {
+ return None;
+ }
+ match self.data.0.get(self.offset) {
+ Some(&4) => {
+ self.offset += 1;
+ if self.offset + 4 > self.data.0.len() {
+ return None;
+ }
+ let result = Some(SocketAddr::V4(SocketAddrV4::new(
+ Ipv4Addr::new(
+ self.data.0[self.offset],
+ self.data.0[self.offset + 1],
+ self.data.0[self.offset + 2],
+ self.data.0[self.offset + 3],
+ ),
+ self.port,
+ )));
+ self.offset += 4;
+ result
+ }
+ Some(&6) => {
+ self.offset += 1;
+ if self.offset + 16 > self.data.0.len() {
+ return None;
+ }
+ let mut new_addr = [0u8; 16];
+ for (src, octet) in self.data.0[(self.offset + 1)..(self.offset + 16 + 1)]
+ .iter()
+ .zip(new_addr.iter_mut())
+ {
+ *octet = *src;
+ }
+ let result =
+ Some(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.port, 0, 0)));
+ self.offset += 16;
+ result
+ }
+ _ => None,
+ }
+ }
+}
+
+pub fn lookup(query: &str, port: u16) -> Result {
+ let mut result = LookupHost { data: LookupHostQuery([0u8; 4096]), offset: 0, count: 0, port };
+
+ // Copy the query into the message that gets sent to the DNS server
+ for (query_byte, result_byte) in query.as_bytes().iter().zip(result.data.0.iter_mut()) {
+ *result_byte = *query_byte;
+ }
+
+ lend_mut(
+ dns_server(),
+ DnsLendMut::RawLookup.into(),
+ &mut result.data.0,
+ 0,
+ query.as_bytes().len(),
+ )
+ .unwrap();
+ if result.data.0[0] != 0 {
+ return Err(DnsError { code: result.data.0[1] });
+ }
+ assert_eq!(result.offset, 0);
+ result.count = result.data.0[1] as usize;
+
+ // Advance the offset to the first record
+ result.offset = 2;
+ Ok(result)
+}
+
+impl TryFrom<&str> for LookupHost {
+ type Error = io::Error;
+
+ fn try_from(s: &str) -> io::Result {
+ macro_rules! try_opt {
+ ($e:expr, $msg:expr) => {
+ match $e {
+ Some(r) => r,
+ None => return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &$msg)),
+ }
+ };
+ }
+
+ // split the string by ':' and convert the second part to u16
+ let (host, port_str) = try_opt!(s.rsplit_once(':'), "invalid socket address");
+ let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
+ (host, port).try_into()
+ }
+}
+
+impl TryFrom<(&str, u16)> for LookupHost {
+ type Error = io::Error;
+
+ fn try_from(v: (&str, u16)) -> io::Result {
+ lookup(v.0, v.1)
+ .map_err(|_e| io::const_io_error!(io::ErrorKind::InvalidInput, &"DNS failure"))
+ }
+}
diff --git a/library/std/src/sys/pal/xous/net/mod.rs b/library/std/src/sys/pal/xous/net/mod.rs
new file mode 100644
index 000000000000..b5a3da136a6b
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/mod.rs
@@ -0,0 +1,84 @@
+mod dns;
+
+mod tcpstream;
+pub use tcpstream::*;
+
+mod tcplistener;
+pub use tcplistener::*;
+
+mod udp;
+pub use udp::*;
+
+// this structure needs to be synchronized with what's in net/src/api.rs
+#[repr(C)]
+#[derive(Debug)]
+enum NetError {
+ // Ok = 0,
+ Unaddressable = 1,
+ SocketInUse = 2,
+ // AccessDenied = 3,
+ Invalid = 4,
+ // Finished = 5,
+ LibraryError = 6,
+ // AlreadyUsed = 7,
+ TimedOut = 8,
+ WouldBlock = 9,
+}
+
+#[repr(C, align(4096))]
+struct ConnectRequest {
+ raw: [u8; 4096],
+}
+
+#[repr(C, align(4096))]
+struct SendData {
+ raw: [u8; 4096],
+}
+
+#[repr(C, align(4096))]
+pub struct ReceiveData {
+ raw: [u8; 4096],
+}
+
+#[repr(C, align(4096))]
+pub struct GetAddress {
+ raw: [u8; 4096],
+}
+
+pub use dns::LookupHost;
+
+#[allow(nonstandard_style)]
+pub mod netc {
+ pub const AF_INET: u8 = 0;
+ pub const AF_INET6: u8 = 1;
+ pub type sa_family_t = u8;
+
+ #[derive(Copy, Clone)]
+ pub struct in_addr {
+ pub s_addr: u32,
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct sockaddr_in {
+ pub sin_family: sa_family_t,
+ pub sin_port: u16,
+ pub sin_addr: in_addr,
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct in6_addr {
+ pub s6_addr: [u8; 16],
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct sockaddr_in6 {
+ pub sin6_family: sa_family_t,
+ pub sin6_port: u16,
+ pub sin6_addr: in6_addr,
+ pub sin6_flowinfo: u32,
+ pub sin6_scope_id: u32,
+ }
+
+ #[derive(Copy, Clone)]
+ pub struct sockaddr {}
+}
diff --git a/library/std/src/sys/pal/xous/net/tcplistener.rs b/library/std/src/sys/pal/xous/net/tcplistener.rs
new file mode 100644
index 000000000000..47305013083c
--- /dev/null
+++ b/library/std/src/sys/pal/xous/net/tcplistener.rs
@@ -0,0 +1,247 @@
+use super::*;
+use crate::fmt;
+use crate::io;
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr};
+use crate::os::xous::services;
+use crate::sync::Arc;
+use core::convert::TryInto;
+use core::sync::atomic::{AtomicBool, AtomicU16, AtomicUsize, Ordering};
+
+macro_rules! unimpl {
+ () => {
+ return Err(io::const_io_error!(
+ io::ErrorKind::Unsupported,
+ &"This function is not yet implemented",
+ ));
+ };
+}
+
+#[derive(Clone)]
+pub struct TcpListener {
+ fd: Arc,
+ local: SocketAddr,
+ handle_count: Arc,
+ nonblocking: Arc,
+}
+
+impl TcpListener {
+ pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result {
+ let mut addr = *socketaddr?;
+
+ let fd = TcpListener::bind_inner(&mut addr)?;
+ return Ok(TcpListener {
+ fd: Arc::new(AtomicU16::new(fd)),
+ local: addr,
+ handle_count: Arc::new(AtomicUsize::new(1)),
+ nonblocking: Arc::new(AtomicBool::new(false)),
+ });
+ }
+
+ /// This returns the raw fd of a Listener, so that it can also be used by the
+ /// accept routine to replenish the Listener object after its handle has been converted into
+ /// a TcpStream object.
+ fn bind_inner(addr: &mut SocketAddr) -> io::Result {
+ // Construct the request
+ let mut connect_request = ConnectRequest { raw: [0u8; 4096] };
+
+ // Serialize the StdUdpBind structure. This is done "manually" because we don't want to
+ // make an auto-serdes (like bincode or rkyv) crate a dependency of Xous.
+ let port_bytes = addr.port().to_le_bytes();
+ connect_request.raw[0] = port_bytes[0];
+ connect_request.raw[1] = port_bytes[1];
+ match addr.ip() {
+ IpAddr::V4(addr) => {
+ connect_request.raw[2] = 4;
+ for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+ *dest = src;
+ }
+ }
+ IpAddr::V6(addr) => {
+ connect_request.raw[2] = 6;
+ for (dest, src) in connect_request.raw[3..].iter_mut().zip(addr.octets()) {
+ *dest = src;
+ }
+ }
+ }
+
+ let Ok((_, valid)) = crate::os::xous::ffi::lend_mut(
+ services::net_server(),
+ services::NetLendMut::StdTcpListen.into(),
+ &mut connect_request.raw,
+ 0,
+ 4096,
+ ) else {
+ return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Invalid response"));
+ };
+
+ // The first four bytes should be zero upon success, and will be nonzero
+ // for an error.
+ let response = connect_request.raw;
+ if response[0] != 0 || valid == 0 {
+ let errcode = response[1];
+ if errcode == NetError::SocketInUse as u8 {
+ return Err(io::const_io_error!(io::ErrorKind::ResourceBusy, &"Socket in use"));
+ } else if errcode == NetError::Invalid as u8 {
+ return Err(io::const_io_error!(
+ io::ErrorKind::AddrNotAvailable,
+ &"Invalid address"
+ ));
+ } else if errcode == NetError::LibraryError as u8 {
+ return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error"));
+ } else {
+ return Err(io::const_io_error!(
+ io::ErrorKind::Other,
+ &"Unable to connect or internal error"
+ ));
+ }
+ }
+ let fd = response[1] as usize;
+ if addr.port() == 0 {
+ // oddly enough, this is a valid port and it means "give me something valid, up to you what that is"
+ let assigned_port = u16::from_le_bytes(response[2..4].try_into().unwrap());
+ addr.set_port(assigned_port);
+ }
+ // println!("TcpListening with file handle of {}\r\n", fd);
+ Ok(fd.try_into().unwrap())
+ }
+
+ pub fn socket_addr(&self) -> io::Result {
+ Ok(self.local)
+ }
+
+ pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
+ let mut receive_request = ReceiveData { raw: [0u8; 4096] };
+
+ if self.nonblocking.load(Ordering::Relaxed) {
+ // nonblocking
+ receive_request.raw[0] = 0;
+ } else {
+ // blocking
+ receive_request.raw[0] = 1;
+ }
+
+ if let Ok((_offset, _valid)) = crate::os::xous::ffi::lend_mut(
+ services::net_server(),
+ services::NetLendMut::StdTcpAccept(self.fd.load(Ordering::Relaxed)).into(),
+ &mut receive_request.raw,
+ 0,
+ 0,
+ ) {
+ if receive_request.raw[0] != 0 {
+ // error case
+ if receive_request.raw[1] == NetError::TimedOut as u8 {
+ return Err(io::const_io_error!(io::ErrorKind::TimedOut, &"accept timed out",));
+ } else if receive_request.raw[1] == NetError::WouldBlock as u8 {
+ return Err(io::const_io_error!(
+ io::ErrorKind::WouldBlock,
+ &"accept would block",
+ ));
+ } else if receive_request.raw[1] == NetError::LibraryError as u8 {
+ return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error"));
+ } else {
+ return Err(io::const_io_error!(io::ErrorKind::Other, &"library error",));
+ }
+ } else {
+ // accept successful
+ let rr = &receive_request.raw;
+ let stream_fd = u16::from_le_bytes(rr[1..3].try_into().unwrap());
+ let port = u16::from_le_bytes(rr[20..22].try_into().unwrap());
+ let addr = if rr[3] == 4 {
+ SocketAddr::new(IpAddr::V4(Ipv4Addr::new(rr[4], rr[5], rr[6], rr[7])), port)
+ } else if rr[3] == 6 {
+ SocketAddr::new(
+ IpAddr::V6(Ipv6Addr::new(
+ u16::from_be_bytes(rr[4..6].try_into().unwrap()),
+ u16::from_be_bytes(rr[6..8].try_into().unwrap()),
+ u16::from_be_bytes(rr[8..10].try_into().unwrap()),
+ u16::from_be_bytes(rr[10..12].try_into().unwrap()),
+ u16::from_be_bytes(rr[12..14].try_into().unwrap()),
+ u16::from_be_bytes(rr[14..16].try_into().unwrap()),
+ u16::from_be_bytes(rr[16..18].try_into().unwrap()),
+ u16::from_be_bytes(rr[18..20].try_into().unwrap()),
+ )),
+ port,
+ )
+ } else {
+ return Err(io::const_io_error!(io::ErrorKind::Other, &"library error",));
+ };
+
+ // replenish the listener
+ let mut local_copy = self.local.clone(); // port is non-0 by this time, but the method signature needs a mut
+ let new_fd = TcpListener::bind_inner(&mut local_copy)?;
+ self.fd.store(new_fd, Ordering::Relaxed);
+
+ // now return a stream converted from the old stream's fd
+ Ok((TcpStream::from_listener(stream_fd, self.local.port(), port, addr), addr))
+ }
+ } else {
+ Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unable to accept"))
+ }
+ }
+
+ pub fn duplicate(&self) -> io::Result {
+ self.handle_count.fetch_add(1, Ordering::Relaxed);
+ Ok(self.clone())
+ }
+
+ pub fn set_ttl(&self, ttl: u32) -> io::Result<()> {
+ if ttl > 255 {
+ return Err(io::Error::new(io::ErrorKind::InvalidInput, "TTL must be less than 256"));
+ }
+ crate::os::xous::ffi::blocking_scalar(
+ services::net_server(),
+ services::NetBlockingScalar::StdSetTtlTcp(self.fd.load(Ordering::Relaxed), ttl).into(),
+ )
+ .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+ .map(|_| ())
+ }
+
+ pub fn ttl(&self) -> io::Result {
+ Ok(crate::os::xous::ffi::blocking_scalar(
+ services::net_server(),
+ services::NetBlockingScalar::StdGetTtlTcp(self.fd.load(Ordering::Relaxed)).into(),
+ )
+ .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value")))
+ .map(|res| res[0] as _)?)
+ }
+
+ pub fn set_only_v6(&self, _: bool) -> io::Result<()> {
+ unimpl!();
+ }
+
+ pub fn only_v6(&self) -> io::Result {
+ unimpl!();
+ }
+
+ pub fn take_error(&self) -> io::Result