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> { + // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. + Ok(None) + } + + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.nonblocking.store(nonblocking, Ordering::Relaxed); + Ok(()) + } +} + +impl fmt::Debug for TcpListener { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "TCP listening on {:?}", self.local) + } +} + +impl Drop for TcpListener { + fn drop(&mut self) { + if self.handle_count.fetch_sub(1, Ordering::Relaxed) == 1 { + // only drop if we're the last clone + crate::os::xous::ffi::blocking_scalar( + services::net_server(), + crate::os::xous::services::NetBlockingScalar::StdTcpClose( + self.fd.load(Ordering::Relaxed), + ) + .into(), + ) + .unwrap(); + } + } +} diff --git a/library/std/src/sys/pal/xous/net/tcpstream.rs b/library/std/src/sys/pal/xous/net/tcpstream.rs new file mode 100644 index 000000000000..7149678118ab --- /dev/null +++ b/library/std/src/sys/pal/xous/net/tcpstream.rs @@ -0,0 +1,435 @@ +use super::*; +use crate::fmt; +use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut}; +use crate::net::{IpAddr, Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; +use crate::os::xous::services; +use crate::sync::Arc; +use crate::time::Duration; +use core::sync::atomic::{AtomicBool, AtomicU32, AtomicUsize, Ordering}; + +macro_rules! unimpl { + () => { + return Err(io::const_io_error!( + io::ErrorKind::Unsupported, + &"This function is not yet implemented", + )); + }; +} + +enum ReadOrPeek { + Read, + Peek, +} + +#[derive(Clone)] +pub struct TcpStream { + fd: u16, + local_port: u16, + remote_port: u16, + peer_addr: SocketAddr, + // milliseconds + read_timeout: Arc, + // milliseconds + write_timeout: Arc, + handle_count: Arc, + nonblocking: Arc, +} + +fn sockaddr_to_buf(duration: Duration, addr: &SocketAddr, buf: &mut [u8]) { + // Construct the request. + let port_bytes = addr.port().to_le_bytes(); + buf[0] = port_bytes[0]; + buf[1] = port_bytes[1]; + for (dest, src) in buf[2..].iter_mut().zip((duration.as_millis() as u64).to_le_bytes()) { + *dest = src; + } + match addr.ip() { + IpAddr::V4(addr) => { + buf[10] = 4; + for (dest, src) in buf[11..].iter_mut().zip(addr.octets()) { + *dest = src; + } + } + IpAddr::V6(addr) => { + buf[10] = 6; + for (dest, src) in buf[11..].iter_mut().zip(addr.octets()) { + *dest = src; + } + } + } +} + +impl TcpStream { + pub(crate) fn from_listener( + fd: u16, + local_port: u16, + remote_port: u16, + peer_addr: SocketAddr, + ) -> TcpStream { + TcpStream { + fd, + local_port, + remote_port, + peer_addr, + read_timeout: Arc::new(AtomicU32::new(0)), + write_timeout: Arc::new(AtomicU32::new(0)), + handle_count: Arc::new(AtomicUsize::new(1)), + nonblocking: Arc::new(AtomicBool::new(false)), + } + } + + pub fn connect(socketaddr: io::Result<&SocketAddr>) -> io::Result { + Self::connect_timeout(socketaddr?, Duration::ZERO) + } + + pub fn connect_timeout(addr: &SocketAddr, duration: Duration) -> io::Result { + let mut connect_request = ConnectRequest { raw: [0u8; 4096] }; + + // Construct the request. + sockaddr_to_buf(duration, &addr, &mut connect_request.raw); + + let Ok((_, valid)) = crate::os::xous::ffi::lend_mut( + services::net_server(), + services::NetLendMut::StdTcpConnect.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 { + // errcode is a u8 but stuck in a u16 where the upper byte is invalid. Mask & decode accordingly. + let errcode = response[0]; + if errcode == NetError::SocketInUse as u8 { + return Err(io::const_io_error!(io::ErrorKind::ResourceBusy, &"Socket in use",)); + } else if errcode == NetError::Unaddressable as u8 { + return Err(io::const_io_error!( + io::ErrorKind::AddrNotAvailable, + &"Invalid address", + )); + } else { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Unable to connect or internal error", + )); + } + } + let fd = u16::from_le_bytes([response[2], response[3]]); + let local_port = u16::from_le_bytes([response[4], response[5]]); + let remote_port = u16::from_le_bytes([response[6], response[7]]); + // println!( + // "Connected with local port of {}, remote port of {}, file handle of {}", + // local_port, remote_port, fd + // ); + Ok(TcpStream { + fd, + local_port, + remote_port, + peer_addr: *addr, + read_timeout: Arc::new(AtomicU32::new(0)), + write_timeout: Arc::new(AtomicU32::new(0)), + handle_count: Arc::new(AtomicUsize::new(1)), + nonblocking: Arc::new(AtomicBool::new(false)), + }) + } + + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + if let Some(to) = timeout { + if to.is_zero() { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Zero is an invalid timeout", + )); + } + } + self.read_timeout.store( + timeout.map(|t| t.as_millis().min(u32::MAX as u128) as u32).unwrap_or_default(), + Ordering::Relaxed, + ); + Ok(()) + } + + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + if let Some(to) = timeout { + if to.is_zero() { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Zero is an invalid timeout", + )); + } + } + self.write_timeout.store( + timeout.map(|t| t.as_millis().min(u32::MAX as u128) as u32).unwrap_or_default(), + Ordering::Relaxed, + ); + Ok(()) + } + + pub fn read_timeout(&self) -> io::Result> { + match self.read_timeout.load(Ordering::Relaxed) { + 0 => Ok(None), + t => Ok(Some(Duration::from_millis(t as u64))), + } + } + + pub fn write_timeout(&self) -> io::Result> { + match self.write_timeout.load(Ordering::Relaxed) { + 0 => Ok(None), + t => Ok(Some(Duration::from_millis(t as u64))), + } + } + + fn read_or_peek(&self, buf: &mut [u8], op: ReadOrPeek) -> io::Result { + let mut receive_request = ReceiveData { raw: [0u8; 4096] }; + let data_to_read = buf.len().min(receive_request.raw.len()); + + let opcode = match op { + ReadOrPeek::Read => { + services::NetLendMut::StdTcpRx(self.fd, self.nonblocking.load(Ordering::Relaxed)) + } + ReadOrPeek::Peek => { + services::NetLendMut::StdTcpPeek(self.fd, self.nonblocking.load(Ordering::Relaxed)) + } + }; + + let Ok((offset, length)) = crate::os::xous::ffi::lend_mut( + services::net_server(), + opcode.into(), + &mut receive_request.raw, + // Reuse the `offset` as the read timeout + self.read_timeout.load(Ordering::Relaxed) as usize, + data_to_read, + ) else { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Library failure: wrong message type or messaging error" + )); + }; + + if offset != 0 { + for (dest, src) in buf.iter_mut().zip(receive_request.raw[..length].iter()) { + *dest = *src; + } + Ok(length) + } else { + let result = receive_request.raw; + if result[0] != 0 { + if result[1] == 8 { + // timed out + return Err(io::const_io_error!(io::ErrorKind::TimedOut, &"Timeout",)); + } + if result[1] == 9 { + // would block + return Err(io::const_io_error!(io::ErrorKind::WouldBlock, &"Would block",)); + } + } + Err(io::const_io_error!(io::ErrorKind::Other, &"recv_slice failure")) + } + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.read_or_peek(buf, ReadOrPeek::Peek) + } + + pub fn read(&self, buf: &mut [u8]) -> io::Result { + self.read_or_peek(buf, ReadOrPeek::Read) + } + + pub fn read_vectored(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + crate::io::default_read_vectored(|b| self.read(b), bufs) + } + + pub fn read_buf(&self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + crate::io::default_read_buf(|buf| self.read(buf), cursor) + } + + pub fn is_read_vectored(&self) -> bool { + false + } + + pub fn write(&self, buf: &[u8]) -> io::Result { + let mut send_request = SendData { raw: [0u8; 4096] }; + for (dest, src) in send_request.raw.iter_mut().zip(buf) { + *dest = *src; + } + let buf_len = send_request.raw.len().min(buf.len()); + + let (_offset, _valid) = crate::os::xous::ffi::lend_mut( + services::net_server(), + services::NetLendMut::StdTcpTx(self.fd).into(), + &mut send_request.raw, + // Reuse the offset as the timeout + self.write_timeout.load(Ordering::Relaxed) as usize, + buf_len, + ) + .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Internal error")))?; + + if send_request.raw[0] != 0 { + if send_request.raw[4] == 8 { + // timed out + return Err(io::const_io_error!( + io::ErrorKind::BrokenPipe, + &"Timeout or connection closed", + )); + } else if send_request.raw[4] == 9 { + // would block + return Err(io::const_io_error!(io::ErrorKind::WouldBlock, &"Would block",)); + } else { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Error when sending", + )); + } + } + Ok(u32::from_le_bytes([ + send_request.raw[4], + send_request.raw[5], + send_request.raw[6], + send_request.raw[7], + ]) as usize) + } + + pub fn write_vectored(&self, bufs: &[IoSlice<'_>]) -> io::Result { + crate::io::default_write_vectored(|b| self.write(b), bufs) + } + + pub fn is_write_vectored(&self) -> bool { + false + } + + pub fn peer_addr(&self) -> io::Result { + Ok(self.peer_addr) + } + + pub fn socket_addr(&self) -> io::Result { + let mut get_addr = GetAddress { raw: [0u8; 4096] }; + + let Ok((_offset, _valid)) = crate::os::xous::ffi::lend_mut( + services::net_server(), + services::NetLendMut::StdGetAddress(self.fd).into(), + &mut get_addr.raw, + 0, + 0, + ) else { + return Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Internal error")); + }; + let mut i = get_addr.raw.iter(); + match *i.next().unwrap() { + 4 => Ok(SocketAddr::V4(SocketAddrV4::new( + Ipv4Addr::new( + *i.next().unwrap(), + *i.next().unwrap(), + *i.next().unwrap(), + *i.next().unwrap(), + ), + self.local_port, + ))), + 6 => { + let mut new_addr = [0u8; 16]; + for (src, octet) in i.zip(new_addr.iter_mut()) { + *octet = *src; + } + Ok(SocketAddr::V6(SocketAddrV6::new(new_addr.into(), self.local_port, 0, 0))) + } + _ => Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Internal error")), + } + } + + pub fn shutdown(&self, how: Shutdown) -> io::Result<()> { + crate::os::xous::ffi::blocking_scalar( + services::net_server(), + services::NetBlockingScalar::StdTcpStreamShutdown(self.fd, how).into(), + ) + .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value"))) + .map(|_| ()) + } + + pub fn duplicate(&self) -> io::Result { + self.handle_count.fetch_add(1, Ordering::Relaxed); + Ok(self.clone()) + } + + pub fn set_linger(&self, _: Option) -> io::Result<()> { + unimpl!(); + } + + pub fn linger(&self) -> io::Result> { + unimpl!(); + } + + pub fn set_nodelay(&self, enabled: bool) -> io::Result<()> { + crate::os::xous::ffi::blocking_scalar( + services::net_server(), + services::NetBlockingScalar::StdSetNodelay(self.fd, enabled).into(), + ) + .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value"))) + .map(|_| ()) + } + + pub fn nodelay(&self) -> io::Result { + Ok(crate::os::xous::ffi::blocking_scalar( + services::net_server(), + services::NetBlockingScalar::StdGetNodelay(self.fd).into(), + ) + .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value"))) + .map(|res| res[0] != 0)?) + } + + 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, 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).into(), + ) + .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value"))) + .map(|res| res[0] as _)?) + } + + pub fn take_error(&self) -> io::Result> { + // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. + Ok(None) + } + + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.nonblocking.store(nonblocking, Ordering::SeqCst); + Ok(()) + } +} + +impl fmt::Debug for TcpStream { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "TCP connection to {:?} port {} to local port {}", + self.peer_addr, self.remote_port, self.local_port + ) + } +} + +impl Drop for TcpStream { + fn drop(&mut self) { + if self.handle_count.fetch_sub(1, Ordering::Relaxed) == 1 { + // only drop if we're the last clone + crate::os::xous::ffi::blocking_scalar( + services::net_server(), + services::NetBlockingScalar::StdTcpClose(self.fd).into(), + ) + .unwrap(); + } + } +} diff --git a/library/std/src/sys/pal/xous/net/udp.rs b/library/std/src/sys/pal/xous/net/udp.rs new file mode 100644 index 000000000000..cafa5b3bde82 --- /dev/null +++ b/library/std/src/sys/pal/xous/net/udp.rs @@ -0,0 +1,471 @@ +use super::*; +use crate::cell::Cell; +use crate::fmt; +use crate::io; +use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, SocketAddr}; +use crate::os::xous::services; +use crate::sync::Arc; +use crate::time::Duration; +use core::convert::TryInto; +use core::sync::atomic::{AtomicUsize, Ordering}; + +macro_rules! unimpl { + () => { + return Err(io::const_io_error!( + io::ErrorKind::Unsupported, + &"This function is not yet implemented", + )); + }; +} + +#[derive(Clone)] +pub struct UdpSocket { + fd: u16, + local: SocketAddr, + remote: Cell>, + // in milliseconds. The setting applies only to `recv` calls after the timeout is set. + read_timeout: Cell, + // in milliseconds. The setting applies only to `send` calls after the timeout is set. + write_timeout: Cell, + handle_count: Arc, + nonblocking: Cell, +} + +impl UdpSocket { + pub fn bind(socketaddr: io::Result<&SocketAddr>) -> io::Result { + let addr = socketaddr?; + // 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 response = crate::os::xous::ffi::lend_mut( + services::net_server(), + services::NetLendMut::StdUdpBind.into(), + &mut connect_request.raw, + 0, + 4096, + ); + + if let Ok((_, valid)) = 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::InvalidInput, + &"Port can't be 0 or 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 u16; + return Ok(UdpSocket { + fd, + local: *addr, + remote: Cell::new(None), + read_timeout: Cell::new(0), + write_timeout: Cell::new(0), + handle_count: Arc::new(AtomicUsize::new(1)), + nonblocking: Cell::new(false), + }); + } + Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Invalid response")) + } + + pub fn peer_addr(&self) -> io::Result { + match self.remote.get() { + Some(dest) => Ok(dest), + None => Err(io::const_io_error!(io::ErrorKind::NotConnected, &"No peer specified")), + } + } + + pub fn socket_addr(&self) -> io::Result { + Ok(self.local) + } + + fn recv_inner(&self, buf: &mut [u8], do_peek: bool) -> io::Result<(usize, SocketAddr)> { + let mut receive_request = ReceiveData { raw: [0u8; 4096] }; + + if self.nonblocking.get() { + // nonblocking + receive_request.raw[0] = 0; + } else { + // blocking + receive_request.raw[0] = 1; + for (&s, d) in self + .read_timeout + .get() + .to_le_bytes() + .iter() + .zip(receive_request.raw[1..9].iter_mut()) + { + *d = s; + } + } + if let Ok((_offset, _valid)) = crate::os::xous::ffi::lend_mut( + services::net_server(), + services::NetLendMut::StdUdpRx(self.fd).into(), + &mut receive_request.raw, + if do_peek { 1 } else { 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, &"recv timed out",)); + } else if receive_request.raw[1] == NetError::WouldBlock as u8 { + return Err(io::const_io_error!( + io::ErrorKind::WouldBlock, + &"recv 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 { + let rr = &receive_request.raw; + let rxlen = 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",)); + }; + for (&s, d) in rr[22..22 + rxlen as usize].iter().zip(buf.iter_mut()) { + *d = s; + } + Ok((rxlen as usize, addr)) + } + } else { + Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unable to recv")) + } + } + + pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_inner(buf, false) + } + + pub fn recv(&self, buf: &mut [u8]) -> io::Result { + self.recv_from(buf).map(|(len, _addr)| len) + } + + pub fn peek_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> { + self.recv_inner(buf, true) + } + + pub fn peek(&self, buf: &mut [u8]) -> io::Result { + self.peek_from(buf).map(|(len, _addr)| len) + } + + pub fn connect(&self, maybe_addr: io::Result<&SocketAddr>) -> io::Result<()> { + let addr = maybe_addr?; + self.remote.set(Some(*addr)); + Ok(()) + } + + pub fn send(&self, buf: &[u8]) -> io::Result { + if let Some(addr) = self.remote.get() { + self.send_to(buf, &addr) + } else { + Err(io::const_io_error!(io::ErrorKind::NotConnected, &"No remote specified")) + } + } + + pub fn send_to(&self, buf: &[u8], addr: &SocketAddr) -> io::Result { + let mut tx_req = SendData { raw: [0u8; 4096] }; + + // Construct the request. + let port_bytes = addr.port().to_le_bytes(); + tx_req.raw[0] = port_bytes[0]; + tx_req.raw[1] = port_bytes[1]; + match addr.ip() { + IpAddr::V4(addr) => { + tx_req.raw[2] = 4; + for (dest, src) in tx_req.raw[3..].iter_mut().zip(addr.octets()) { + *dest = src; + } + } + IpAddr::V6(addr) => { + tx_req.raw[2] = 6; + for (dest, src) in tx_req.raw[3..].iter_mut().zip(addr.octets()) { + *dest = src; + } + } + } + let len = buf.len() as u16; + let len_bytes = len.to_le_bytes(); + tx_req.raw[19] = len_bytes[0]; + tx_req.raw[20] = len_bytes[1]; + for (&s, d) in buf.iter().zip(tx_req.raw[21..].iter_mut()) { + *d = s; + } + + // let buf = unsafe { + // xous::MemoryRange::new( + // &mut tx_req as *mut SendData as usize, + // core::mem::size_of::(), + // ) + // .unwrap() + // }; + + // write time-outs are implemented on the caller side. Basically, if the Net crate server + // is too busy to take the call immediately: retry, until the timeout is reached. + let now = crate::time::Instant::now(); + let write_timeout = if self.nonblocking.get() { + // nonblocking + core::time::Duration::ZERO + } else { + // blocking + if self.write_timeout.get() == 0 { + // forever + core::time::Duration::from_millis(u64::MAX) + } else { + // or this amount of time + core::time::Duration::from_millis(self.write_timeout.get()) + } + }; + loop { + let response = crate::os::xous::ffi::try_lend_mut( + services::net_server(), + services::NetLendMut::StdUdpTx(self.fd).into(), + &mut tx_req.raw, + 0, + 4096, + ); + match response { + Ok((_, valid)) => { + let response = &tx_req.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::InvalidInput, + &"Socket not valid" + )); + } 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" + )); + } + } else { + // no error + return Ok(len as usize); + } + } + Err(crate::os::xous::ffi::Error::ServerQueueFull) => { + if now.elapsed() >= write_timeout { + return Err(io::const_io_error!( + io::ErrorKind::WouldBlock, + &"Write timed out" + )); + } else { + // question: do we want to do something a bit more gentle than immediately retrying? + crate::thread::yield_now(); + } + } + _ => return Err(io::const_io_error!(io::ErrorKind::Other, &"Library error")), + } + } + } + + pub fn duplicate(&self) -> io::Result { + self.handle_count.fetch_add(1, Ordering::Relaxed); + Ok(self.clone()) + } + + pub fn set_read_timeout(&self, timeout: Option) -> io::Result<()> { + if let Some(d) = timeout { + if d.is_zero() { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Zero duration is invalid" + )); + } + } + self.read_timeout + .set(timeout.map(|t| t.as_millis().min(u64::MAX as u128) as u64).unwrap_or_default()); + Ok(()) + } + + pub fn set_write_timeout(&self, timeout: Option) -> io::Result<()> { + if let Some(d) = timeout { + if d.is_zero() { + return Err(io::const_io_error!( + io::ErrorKind::InvalidInput, + &"Zero duration is invalid" + )); + } + } + self.write_timeout + .set(timeout.map(|t| t.as_millis().min(u64::MAX as u128) as u64).unwrap_or_default()); + Ok(()) + } + + pub fn read_timeout(&self) -> io::Result> { + match self.read_timeout.get() { + 0 => Ok(None), + t => Ok(Some(Duration::from_millis(t as u64))), + } + } + + pub fn write_timeout(&self) -> io::Result> { + match self.write_timeout.get() { + 0 => Ok(None), + t => Ok(Some(Duration::from_millis(t as u64))), + } + } + + 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::StdSetTtlUdp(self.fd, 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::StdGetTtlUdp(self.fd).into(), + ) + .or(Err(io::const_io_error!(io::ErrorKind::InvalidInput, &"Unexpected return value"))) + .map(|res| res[0] as _)?) + } + + pub fn take_error(&self) -> io::Result> { + // this call doesn't have a meaning on our platform, but we can at least not panic if it's used. + Ok(None) + } + + pub fn set_nonblocking(&self, nonblocking: bool) -> io::Result<()> { + self.nonblocking.set(nonblocking); + Ok(()) + } + + // ------------- smoltcp base stack does not have multicast or broadcast support --------------- + pub fn set_broadcast(&self, _: bool) -> io::Result<()> { + unimpl!(); + } + + pub fn broadcast(&self) -> io::Result { + unimpl!(); + } + + pub fn set_multicast_loop_v4(&self, _: bool) -> io::Result<()> { + unimpl!(); + } + + pub fn multicast_loop_v4(&self) -> io::Result { + unimpl!(); + } + + pub fn set_multicast_ttl_v4(&self, _: u32) -> io::Result<()> { + unimpl!(); + } + + pub fn multicast_ttl_v4(&self) -> io::Result { + unimpl!(); + } + + pub fn set_multicast_loop_v6(&self, _: bool) -> io::Result<()> { + unimpl!(); + } + + pub fn multicast_loop_v6(&self) -> io::Result { + unimpl!(); + } + + pub fn join_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { + unimpl!(); + } + + pub fn join_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { + unimpl!(); + } + + pub fn leave_multicast_v4(&self, _: &Ipv4Addr, _: &Ipv4Addr) -> io::Result<()> { + unimpl!(); + } + + pub fn leave_multicast_v6(&self, _: &Ipv6Addr, _: u32) -> io::Result<()> { + unimpl!(); + } +} + +impl fmt::Debug for UdpSocket { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "UDP listening on {:?} to {:?}", self.local, self.remote.get(),) + } +} + +impl Drop for UdpSocket { + fn drop(&mut self) { + if self.handle_count.fetch_sub(1, Ordering::Relaxed) == 1 { + // only drop if we're the last clone + crate::os::xous::ffi::blocking_scalar( + services::net_server(), + services::NetBlockingScalar::StdUdpClose(self.fd).into(), + ) + .unwrap(); + } + } +} diff --git a/library/std/src/sys/pal/xous/stdio.rs b/library/std/src/sys/pal/xous/stdio.rs index 2ac694641ba9..11608964b52e 100644 --- a/library/std/src/sys/pal/xous/stdio.rs +++ b/library/std/src/sys/pal/xous/stdio.rs @@ -5,7 +5,7 @@ pub struct Stdout {} pub struct Stderr; use crate::os::xous::ffi::{lend, try_lend, try_scalar, Connection}; -use crate::os::xous::services::{log_server, try_connect, LogScalar}; +use crate::os::xous::services::{log_server, try_connect, LogLend, LogScalar}; impl Stdin { pub const fn new() -> Stdin { @@ -27,7 +27,7 @@ impl Stdout { impl io::Write for Stdout { fn write(&mut self, buf: &[u8]) -> io::Result { - #[repr(align(4096))] + #[repr(C, align(4096))] struct LendBuffer([u8; 4096]); let mut lend_buffer = LendBuffer([0u8; 4096]); let connection = log_server(); @@ -35,7 +35,8 @@ impl io::Write for Stdout { for (dest, src) in lend_buffer.0.iter_mut().zip(chunk) { *dest = *src; } - lend(connection, 1, &lend_buffer.0, 0, chunk.len()).unwrap(); + lend(connection, LogLend::StandardOutput.into(), &lend_buffer.0, 0, chunk.len()) + .unwrap(); } Ok(buf.len()) } @@ -53,7 +54,7 @@ impl Stderr { impl io::Write for Stderr { fn write(&mut self, buf: &[u8]) -> io::Result { - #[repr(align(4096))] + #[repr(C, align(4096))] struct LendBuffer([u8; 4096]); let mut lend_buffer = LendBuffer([0u8; 4096]); let connection = log_server(); @@ -61,7 +62,8 @@ impl io::Write for Stderr { for (dest, src) in lend_buffer.0.iter_mut().zip(chunk) { *dest = *src; } - lend(connection, 1, &lend_buffer.0, 0, chunk.len()).unwrap(); + lend(connection, LogLend::StandardError.into(), &lend_buffer.0, 0, chunk.len()) + .unwrap(); } Ok(buf.len()) } diff --git a/library/std/src/sys/pal/xous/thread.rs b/library/std/src/sys/pal/xous/thread.rs index 78c68de7bf38..0f452e07a5c5 100644 --- a/library/std/src/sys/pal/xous/thread.rs +++ b/library/std/src/sys/pal/xous/thread.rs @@ -68,14 +68,18 @@ impl Thread { ) .map_err(|code| io::Error::from_raw_os_error(code as i32))?; - extern "C" fn thread_start(main: *mut usize, guard_page_pre: usize, stack_size: usize) { + extern "C" fn thread_start( + main: *mut usize, + guard_page_pre: usize, + stack_size: usize, + ) -> ! { unsafe { - // Finally, let's run some code. + // Run the contents of the new thread. Box::from_raw(main as *mut Box)(); } // Destroy TLS, which will free the TLS page and call the destructor for - // any thread local storage. + // any thread local storage (if any). unsafe { crate::sys::thread_local_key::destroy_tls(); } diff --git a/library/std/src/sys/pal/xous/thread_local_key.rs b/library/std/src/sys/pal/xous/thread_local_key.rs index 3771ea657008..59a668c3df6f 100644 --- a/library/std/src/sys/pal/xous/thread_local_key.rs +++ b/library/std/src/sys/pal/xous/thread_local_key.rs @@ -23,10 +23,25 @@ pub type Dtor = unsafe extern "C" fn(*mut u8); const TLS_MEMORY_SIZE: usize = 4096; -/// TLS keys start at `1` to mimic POSIX. +/// TLS keys start at `1`. Index `0` is unused +#[cfg(not(test))] +#[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"] static TLS_KEY_INDEX: AtomicUsize = AtomicUsize::new(1); -fn tls_ptr_addr() -> *mut usize { +#[cfg(not(test))] +#[export_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"] +static DTORS: AtomicPtr = AtomicPtr::new(ptr::null_mut()); + +#[cfg(test)] +extern "Rust" { + #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key13TLS_KEY_INDEXE"] + static TLS_KEY_INDEX: AtomicUsize; + + #[link_name = "_ZN16__rust_internals3std3sys4xous16thread_local_key9DTORSE"] + static DTORS: AtomicPtr; +} + +fn tls_ptr_addr() -> *mut *mut u8 { let mut tp: usize; unsafe { asm!( @@ -34,50 +49,50 @@ fn tls_ptr_addr() -> *mut usize { out(reg) tp, ); } - core::ptr::from_exposed_addr_mut::(tp) + core::ptr::from_exposed_addr_mut::<*mut u8>(tp) } /// Create an area of memory that's unique per thread. This area will /// contain all thread local pointers. -fn tls_ptr() -> *mut usize { - let mut tp = tls_ptr_addr(); +fn tls_table() -> &'static mut [*mut u8] { + let tp = tls_ptr_addr(); + if !tp.is_null() { + return unsafe { + core::slice::from_raw_parts_mut(tp, TLS_MEMORY_SIZE / core::mem::size_of::<*mut u8>()) + }; + } // If the TP register is `0`, then this thread hasn't initialized // its TLS yet. Allocate a new page to store this memory. - if tp.is_null() { - tp = unsafe { - map_memory( - None, - None, - TLS_MEMORY_SIZE / core::mem::size_of::(), - MemoryFlags::R | MemoryFlags::W, - ) - } + let tp = unsafe { + map_memory( + None, + None, + TLS_MEMORY_SIZE / core::mem::size_of::<*mut u8>(), + MemoryFlags::R | MemoryFlags::W, + ) .expect("Unable to allocate memory for thread local storage") - .as_mut_ptr(); + }; - unsafe { - // Key #0 is currently unused. - (tp).write_volatile(0); + for val in tp.iter() { + assert!(*val as usize == 0); + } - // Set the thread's `$tp` register - asm!( - "mv tp, {}", - in(reg) tp as usize, - ); - } + unsafe { + // Set the thread's `$tp` register + asm!( + "mv tp, {}", + in(reg) tp.as_mut_ptr() as usize, + ); } tp } -/// Allocate a new TLS key. These keys are shared among all threads. -fn tls_alloc() -> usize { - TLS_KEY_INDEX.fetch_add(1, SeqCst) -} - #[inline] pub unsafe fn create(dtor: Option) -> Key { - let key = tls_alloc(); + // Allocate a new TLS key. These keys are shared among all threads. + #[allow(unused_unsafe)] + let key = unsafe { TLS_KEY_INDEX.fetch_add(1, SeqCst) }; if let Some(f) = dtor { unsafe { register_dtor(key, f) }; } @@ -87,18 +102,20 @@ pub unsafe fn create(dtor: Option) -> Key { #[inline] pub unsafe fn set(key: Key, value: *mut u8) { assert!((key < 1022) && (key >= 1)); - unsafe { tls_ptr().add(key).write_volatile(value as usize) }; + let table = tls_table(); + table[key] = value; } #[inline] pub unsafe fn get(key: Key) -> *mut u8 { assert!((key < 1022) && (key >= 1)); - core::ptr::from_exposed_addr_mut::(unsafe { tls_ptr().add(key).read_volatile() }) + tls_table()[key] } #[inline] pub unsafe fn destroy(_key: Key) { - panic!("can't destroy keys on Xous"); + // Just leak the key. Probably not great on long-running systems that create + // lots of TLS variables, but in practice that's not an issue. } // ------------------------------------------------------------------------- @@ -127,8 +144,6 @@ pub unsafe fn destroy(_key: Key) { // key but also a slot for the destructor queue on windows. An optimization for // another day! -static DTORS: AtomicPtr = AtomicPtr::new(ptr::null_mut()); - struct Node { dtor: Dtor, key: Key, @@ -138,10 +153,12 @@ struct Node { unsafe fn register_dtor(key: Key, dtor: Dtor) { let mut node = ManuallyDrop::new(Box::new(Node { key, dtor, next: ptr::null_mut() })); - let mut head = DTORS.load(SeqCst); + #[allow(unused_unsafe)] + let mut head = unsafe { DTORS.load(SeqCst) }; loop { node.next = head; - match DTORS.compare_exchange(head, &mut **node, SeqCst, SeqCst) { + #[allow(unused_unsafe)] + match unsafe { DTORS.compare_exchange(head, &mut **node, SeqCst, SeqCst) } { Ok(_) => return, // nothing to drop, we successfully added the node to the list Err(cur) => head = cur, } @@ -155,6 +172,7 @@ pub unsafe fn destroy_tls() { if tp.is_null() { return; } + unsafe { run_dtors() }; // Finally, free the TLS array @@ -169,12 +187,19 @@ pub unsafe fn destroy_tls() { unsafe fn run_dtors() { let mut any_run = true; + + // Run the destructor "some" number of times. This is 5x on Windows, + // so we copy it here. This allows TLS variables to create new + // TLS variables upon destruction that will also get destroyed. + // Keep going until we run out of tries or until we have nothing + // left to destroy. for _ in 0..5 { if !any_run { break; } any_run = false; - let mut cur = DTORS.load(SeqCst); + #[allow(unused_unsafe)] + let mut cur = unsafe { DTORS.load(SeqCst) }; while !cur.is_null() { let ptr = unsafe { get((*cur).key) }; diff --git a/library/std/src/sys/pal/xous/thread_parking.rs b/library/std/src/sys/pal/xous/thread_parking.rs index aa39c6d27185..0bd0462d77d3 100644 --- a/library/std/src/sys/pal/xous/thread_parking.rs +++ b/library/std/src/sys/pal/xous/thread_parking.rs @@ -29,31 +29,40 @@ impl Parker { // Change NOTIFIED to EMPTY and EMPTY to PARKED. let state = self.state.fetch_sub(1, Acquire); if state == NOTIFIED { + // The state has gone from NOTIFIED (1) to EMPTY (0) return; } + // The state has gone from EMPTY (0) to PARKED (-1) + assert!(state == EMPTY); - // The state was set to PARKED. Wait until the `unpark` wakes us up. + // The state is now PARKED (-1). Wait until the `unpark` wakes us up. blocking_scalar( ticktimer_server(), TicktimerScalar::WaitForCondition(self.index(), 0).into(), ) .expect("failed to send WaitForCondition command"); - self.state.swap(EMPTY, Acquire); + let state = self.state.swap(EMPTY, Acquire); + assert!(state == NOTIFIED || state == PARKED); } pub unsafe fn park_timeout(self: Pin<&Self>, timeout: Duration) { // Change NOTIFIED to EMPTY and EMPTY to PARKED. let state = self.state.fetch_sub(1, Acquire); if state == NOTIFIED { + // The state has gone from NOTIFIED (1) to EMPTY (0) return; } + // The state has gone from EMPTY (0) to PARKED (-1) + assert!(state == EMPTY); // A value of zero indicates an indefinite wait. Clamp the number of // milliseconds to the allowed range. let millis = usize::max(timeout.as_millis().try_into().unwrap_or(usize::MAX), 1); - let was_timeout = blocking_scalar( + // The state is now PARKED (-1). Wait until the `unpark` wakes us up, + // or things time out. + let _was_timeout = blocking_scalar( ticktimer_server(), TicktimerScalar::WaitForCondition(self.index(), millis).into(), ) @@ -61,28 +70,37 @@ impl Parker { != 0; let state = self.state.swap(EMPTY, Acquire); - if was_timeout && state == NOTIFIED { - // The state was set to NOTIFIED after we returned from the wait - // but before we reset the state. Therefore, a wakeup is on its - // way, which we need to consume here. - // NOTICE: this is a priority hole. - blocking_scalar( - ticktimer_server(), - TicktimerScalar::WaitForCondition(self.index(), 0).into(), - ) - .expect("failed to send WaitForCondition command"); - } + assert!(state == PARKED || state == NOTIFIED); } pub fn unpark(self: Pin<&Self>) { - let state = self.state.swap(NOTIFIED, Release); - if state == PARKED { - // The thread is parked, wake it up. - blocking_scalar( - ticktimer_server(), - TicktimerScalar::NotifyCondition(self.index(), 1).into(), - ) - .expect("failed to send NotifyCondition command"); + // If the state is already `NOTIFIED`, then another thread has + // indicated it wants to wake up the target thread. + // + // If the state is `EMPTY` then there is nothing to wake up, and + // the target thread will immediately exit from `park()` the + // next time that function is called. + if self.state.swap(NOTIFIED, Release) != PARKED { + return; + } + + // The thread is parked, wake it up. Keep trying until we wake something up. + // This will happen when the `NotifyCondition` call returns the fact that + // 1 condition was notified. + // Alternately, keep going until the state is seen as `EMPTY`, indicating + // the thread woke up and kept going. This can happen when the Park + // times out before we can send the NotifyCondition message. + while blocking_scalar( + ticktimer_server(), + TicktimerScalar::NotifyCondition(self.index(), 1).into(), + ) + .expect("failed to send NotifyCondition command")[0] + == 0 + && self.state.load(Acquire) != EMPTY + { + // The target thread hasn't yet hit the `WaitForCondition` call. + // Yield to let the target thread run some more. + crate::thread::yield_now(); } } } diff --git a/library/std/src/sys_common/once/mod.rs b/library/std/src/sys_common/once/mod.rs index 359697d83131..ec57568c54c4 100644 --- a/library/std/src/sys_common/once/mod.rs +++ b/library/std/src/sys_common/once/mod.rs @@ -25,6 +25,7 @@ cfg_if::cfg_if! { target_family = "unix", all(target_vendor = "fortanix", target_env = "sgx"), target_os = "solid_asp3", + target_os = "xous", ))] { mod queue; pub use queue::{Once, OnceState}; diff --git a/library/std/src/thread/local.rs b/library/std/src/thread/local.rs index 338567777f75..2e13f433dcff 100644 --- a/library/std/src/thread/local.rs +++ b/library/std/src/thread/local.rs @@ -186,12 +186,12 @@ macro_rules! thread_local { // empty (base case for the recursion) () => {}; - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }; $($rest:tt)*) => ( + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block; $($rest:tt)*) => ( $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); $crate::thread_local!($($rest)*); ); - ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const { $init:expr }) => ( + ($(#[$attr:meta])* $vis:vis static $name:ident: $t:ty = const $init:block) => ( $crate::thread::local_impl::thread_local_inner!($(#[$attr])* $vis $name, $t, const $init); ); diff --git a/library/std/tests/thread.rs b/library/std/tests/thread.rs index 754b264c6ad9..4ce81f2846ea 100644 --- a/library/std/tests/thread.rs +++ b/library/std/tests/thread.rs @@ -1,3 +1,4 @@ +use std::cell::{Cell, RefCell}; use std::sync::{Arc, Mutex}; use std::thread; use std::time::Duration; @@ -14,3 +15,24 @@ fn sleep() { thread::sleep(Duration::from_millis(100)); assert_eq!(*finished.lock().unwrap(), false); } + +#[test] +fn thread_local_containing_const_statements() { + // This exercises the `const $init:block` cases of the thread_local macro. + // Despite overlapping with expression syntax, the `const { ... }` is not + // parsed as `$init:expr`. + thread_local! { + static CELL: Cell = const { + let value = 1; + Cell::new(value) + }; + + static REFCELL: RefCell = const { + let value = 1; + RefCell::new(value) + }; + } + + assert_eq!(CELL.get(), 1); + assert_eq!(REFCELL.take(), 1); +} diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index 28d96cb1cfe5..83fdcddecf27 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -924,17 +924,29 @@ class RustBuild(object): # default toolchain is not nightly. # # But that setting has the collateral effect of rust-analyzer also - # passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various overrideCommand). - # For compiling bootstrap that can cause spurious rebuilding of bootstrap when - # rust-analyzer x.py invocations are interleaved with handwritten ones on the - # command line. + # passing RUSTC_BOOTSTRAP=1 to all x.py invocations too (the various + # overrideCommand). # - # Set RUSTC_BOOTSTRAP=1 consistently. + # Set a consistent RUSTC_BOOTSTRAP=1 here to prevent spurious rebuilds + # of bootstrap when rust-analyzer x.py invocations are interleaved with + # handwritten ones on the command line. env["RUSTC_BOOTSTRAP"] = "1" - default_rustflags = "" if env.get("RUSTFLAGS_BOOTSTRAP", "") else "-Zallow-features=" - - env.setdefault("RUSTFLAGS", default_rustflags) + # If any of RUSTFLAGS or RUSTFLAGS_BOOTSTRAP are present and nonempty, + # we allow arbitrary compiler flags in there, including unstable ones + # such as `-Zthreads=8`. + # + # But if there aren't custom flags being passed to bootstrap, then we + # cancel the RUSTC_BOOTSTRAP=1 from above by passing `-Zallow-features=` + # to ensure unstable language or library features do not accidentally + # get introduced into bootstrap over time. Distros rely on being able to + # compile bootstrap with a variety of their toolchains, not necessarily + # the same as Rust's CI uses. + if env.get("RUSTFLAGS", "") or env.get("RUSTFLAGS_BOOTSTRAP", ""): + # Preserve existing RUSTFLAGS. + env.setdefault("RUSTFLAGS", "") + else: + env["RUSTFLAGS"] = "-Zallow-features=" target_features = [] if self.get_toml("crt-static", build_section) == "true": diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 190f0fe3cddc..f954f01fe4ed 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -803,7 +803,14 @@ impl Rustc { } impl Step for Rustc { - type Output = (); + // We return the stage of the "actual" compiler (not the uplifted one). + // + // By "actual" we refer to the uplifting logic where we may not compile the requested stage; + // instead, we uplift it from the previous stages. Which can lead to bootstrap failures in + // specific situations where we request stage X from other steps. However we may end up + // uplifting it from stage Y, causing the other stage to fail when attempting to link with + // stage X which was never actually built. + type Output = u32; const ONLY_HOSTS: bool = true; const DEFAULT: bool = false; @@ -834,7 +841,7 @@ impl Step for Rustc { /// This will build the compiler for a particular stage of the build using /// the `compiler` targeting the `target` architecture. The artifacts /// created will also be linked into the sysroot directory. - fn run(self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) -> u32 { let compiler = self.compiler; let target = self.target; @@ -848,7 +855,7 @@ impl Step for Rustc { compiler, builder.config.ci_rustc_dev_contents(), ); - return; + return compiler.stage; } builder.ensure(Std::new(compiler, target)); @@ -857,7 +864,8 @@ impl Step for Rustc { builder.info("WARNING: Using a potentially old librustc. This may not behave well."); builder.info("WARNING: Use `--keep-stage-std` if you want to rebuild the compiler when it changes"); builder.ensure(RustcLink::from_rustc(self, compiler)); - return; + + return compiler.stage; } let compiler_to_use = builder.compiler_for(compiler.stage, compiler.host, target); @@ -880,7 +888,7 @@ impl Step for Rustc { }; builder.info(&msg); builder.ensure(RustcLink::from_rustc(self, compiler_to_use)); - return; + return compiler_to_use.stage; } // Ensure that build scripts and proc macros have a std / libproc_macro to link against. @@ -984,6 +992,8 @@ impl Step for Rustc { self, builder.compiler(compiler.stage, builder.config.build), )); + + compiler.stage } } @@ -1642,21 +1652,6 @@ impl Step for Assemble { return target_compiler; } - // Get the compiler that we'll use to bootstrap ourselves. - // - // Note that this is where the recursive nature of the bootstrap - // happens, as this will request the previous stage's compiler on - // downwards to stage 0. - // - // Also note that we're building a compiler for the host platform. We - // only assume that we can run `build` artifacts, which means that to - // produce some other architecture compiler we need to start from - // `build` to get there. - // - // FIXME: It may be faster if we build just a stage 1 compiler and then - // use that to bootstrap this compiler forward. - let build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); - // If we're downloading a compiler from CI, we can use the same compiler for all stages other than 0. if builder.download_rustc() { let sysroot = @@ -1671,19 +1666,30 @@ impl Step for Assemble { return target_compiler; } + // Get the compiler that we'll use to bootstrap ourselves. + // + // Note that this is where the recursive nature of the bootstrap + // happens, as this will request the previous stage's compiler on + // downwards to stage 0. + // + // Also note that we're building a compiler for the host platform. We + // only assume that we can run `build` artifacts, which means that to + // produce some other architecture compiler we need to start from + // `build` to get there. + // + // FIXME: It may be faster if we build just a stage 1 compiler and then + // use that to bootstrap this compiler forward. + let mut build_compiler = builder.compiler(target_compiler.stage - 1, builder.config.build); + // Build the libraries for this compiler to link to (i.e., the libraries // it uses at runtime). NOTE: Crates the target compiler compiles don't // link to these. (FIXME: Is that correct? It seems to be correct most // of the time but I think we do link to these for stage2/bin compilers // when not performing a full bootstrap). - builder.ensure(Rustc::new(build_compiler, target_compiler.host)); - - // FIXME: For now patch over problems noted in #90244 by early returning here, even though - // we've not properly assembled the target sysroot. A full fix is pending further investigation, - // for now full bootstrap usage is rare enough that this is OK. - if target_compiler.stage >= 3 && !builder.config.full_bootstrap { - return target_compiler; - } + let actual_stage = builder.ensure(Rustc::new(build_compiler, target_compiler.host)); + // Current build_compiler.stage might be uplifted instead of being built; so update it + // to not fail while linking the artifacts. + build_compiler.stage = actual_stage; for &backend in builder.config.rust_codegen_backends.iter() { if backend == "llvm" { diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 2ddf5737fbd9..9e5c1ed87489 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -72,6 +72,12 @@ ensure that each tier 2 target can be used as build target after each change. Au not always run so it's not guaranteed to produce a working build, but tier 2 targets often work to quite a good degree and patches are always welcome! +Tier 2 target-specific code is not closely scrutinized by Rust team(s) when +modifications are made. Bugs are possible in all code, but the level of quality +control for these targets is likely to be lower. See [library team +policy](https://std-dev-guide.rust-lang.org/policy/target-code.html) for +details on the review practices for standard library code. + Tier 2 targets with host tools additionally support running tools like `rustc` and `cargo` natively on the target, and automated builds ensure that the host tools build as well. This allows the target to be used as a development @@ -121,6 +127,12 @@ The `std` column in the table below has the following meanings: [`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html +Tier 2 target-specific code is not closely scrutinized by Rust team(s) when +modifications are made. Bugs are possible in all code, but the level of quality +control for these targets is likely to be lower. See [library team +policy](https://std-dev-guide.rust-lang.org/policy/target-code.html) for +details on the review practices for standard library code. + **NOTE:** The `rust-docs` component is not usually built for tier 2 targets, so Rustup may install the documentation for a similar tier 1 target instead. @@ -211,6 +223,12 @@ The `std` column in the table below has the following meanings: [`no_std`]: https://rust-embedded.github.io/book/intro/no-std.html +Tier 3 target-specific code is not closely scrutinized by Rust team(s) when +modifications are made. Bugs are possible in all code, but the level of quality +control for these targets is likely to be lower. See [library team +policy](https://std-dev-guide.rust-lang.org/policy/target-code.html) for +details on the review practices for standard library code. + The `host` column indicates whether the codebase includes support for building host tools. diff --git a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md index 13349ff6b8f4..424f1128e3b5 100644 --- a/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md +++ b/src/doc/unstable-book/src/compiler-flags/remap-path-scope.md @@ -20,5 +20,5 @@ This flag accepts a comma-separated list of values and may be specified multiple ```sh # This would produce an absolute path to main.rs in build outputs of # "./main.rs". -rustc --remap-path-prefix=$(PWD)=/remapped -Zremap-path-prefix=object main.rs +rustc --remap-path-prefix=$(PWD)=/remapped -Zremap-path-scope=object main.rs ``` diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md new file mode 100644 index 000000000000..3697ae38f9d8 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/trait-upcasting.md @@ -0,0 +1,27 @@ +# `trait_upcasting` + +The tracking issue for this feature is: [#65991] + +[#65991]: https://github.com/rust-lang/rust/issues/65991 + +------------------------ + +The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a +trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo` +so long as `Bar: Foo`. + +```rust,edition2018 +#![feature(trait_upcasting)] +#![allow(incomplete_features)] + +trait Foo {} + +trait Bar: Foo {} + +impl Foo for i32 {} + +impl Bar for T {} + +let bar: &dyn Bar = &123; +let foo: &dyn Foo = bar; +``` diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 124a2d9cba95..8706abda9796 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1049,7 +1049,7 @@ fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[ast::Attrib func.decl .inputs .values - .insert(a as _, Argument { name, type_: *ty, is_const: true }); + .insert(a.get() as _, Argument { name, type_: *ty, is_const: true }); } else { panic!("unexpected non const in position {pos}"); } diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index fa72758c2165..7cf385de6b77 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -377,7 +377,7 @@ pub(crate) fn run_global_ctxt( {}/rustdoc/how-to-write-documentation.html", crate::DOC_RUST_LANG_ORG_CHANNEL ); - tcx.struct_lint_node( + tcx.node_lint( crate::lint::MISSING_CRATE_LEVEL_DOCS, DocContext::as_local_hir_id(tcx, krate.module.item_id).unwrap(), "no documentation found for this crate's top-level module", @@ -449,6 +449,7 @@ pub(crate) fn run_global_ctxt( tcx.sess.time("check_lint_expectations", || tcx.check_expectations(Some(sym::rustdoc))); + // We must include lint errors here. if tcx.dcx().has_errors_or_lint_errors().is_some() { rustc_errors::FatalError.raise(); } diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 82746a7ab034..f2e083de0ec7 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -150,6 +150,7 @@ pub(crate) fn run(options: RustdocOptions) -> Result<(), ErrorGuaranteed> { collector }); + // We must include lint errors here. if compiler.sess.dcx().has_errors_or_lint_errors().is_some() { FatalError.raise(); } diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index bad1511dfd29..ee5891c12fc5 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -827,7 +827,7 @@ impl<'tcx> ExtraInfo<'tcx> { fn error_invalid_codeblock_attr(&self, msg: impl Into) { if let Some(def_id) = self.def_id.as_local() { - self.tcx.struct_span_lint_hir( + self.tcx.node_span_lint( crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, self.tcx.local_def_id_to_hir_id(def_id), self.sp, @@ -843,7 +843,7 @@ impl<'tcx> ExtraInfo<'tcx> { f: impl for<'a, 'b> FnOnce(&'b mut DiagnosticBuilder<'a, ()>), ) { if let Some(def_id) = self.def_id.as_local() { - self.tcx.struct_span_lint_hir( + self.tcx.node_span_lint( crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, self.tcx.local_def_id_to_hir_id(def_id), self.sp, diff --git a/src/librustdoc/html/static/js/main.js b/src/librustdoc/html/static/js/main.js index 88901191cda2..b46701b55ea7 100644 --- a/src/librustdoc/html/static/js/main.js +++ b/src/librustdoc/html/static/js/main.js @@ -1721,6 +1721,7 @@ href="https://doc.rust-lang.org/${channel}/rustdoc/read-documentation/search.htm } currentPointerId = e.pointerId; } + window.hideAllModals(false); e.preventDefault(); window.addEventListener("pointermove", resize, false); window.addEventListener("pointercancel", stopResize, false); diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index d962beda4bee..658ed862ae76 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -796,7 +796,7 @@ fn main_args( compiler.enter(|queries| { let mut gcx = abort_on_err(queries.global_ctxt(), sess); - if sess.dcx().has_errors_or_lint_errors().is_some() { + if sess.dcx().has_errors().is_some() { sess.dcx().fatal("Compilation failed, aborting rustdoc"); } diff --git a/src/librustdoc/passes/check_doc_test_visibility.rs b/src/librustdoc/passes/check_doc_test_visibility.rs index a931e8804d9c..0603aae55360 100644 --- a/src/librustdoc/passes/check_doc_test_visibility.rs +++ b/src/librustdoc/passes/check_doc_test_visibility.rs @@ -126,7 +126,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item if should_have_doc_example(cx, item) { debug!("reporting error for {item:?} (hir_id={hir_id:?})"); let sp = item.attr_span(cx.tcx); - cx.tcx.struct_span_lint_hir( + cx.tcx.node_span_lint( crate::lint::MISSING_DOC_CODE_EXAMPLES, hir_id, sp, @@ -137,7 +137,7 @@ pub(crate) fn look_for_tests<'tcx>(cx: &DocContext<'tcx>, dox: &str, item: &Item } else if tests.found_tests > 0 && !cx.cache.effective_visibilities.is_exported(cx.tcx, item.item_id.expect_def_id()) { - cx.tcx.struct_span_lint_hir( + cx.tcx.node_span_lint( crate::lint::PRIVATE_DOC_TESTS, hir_id, item.attr_span(cx.tcx), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 30b3e5c784dc..ca1870a3a645 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1704,7 +1704,7 @@ fn report_diagnostic( let sp = item.attr_span(tcx); - tcx.struct_span_lint_hir(lint, hir_id, sp, msg, |lint| { + tcx.node_span_lint(lint, hir_id, sp, msg, |lint| { let (span, link_range) = match link_range { MarkdownLinkRange::Destination(md_range) => { let mut md_range = md_range.clone(); diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index fc7ef4bcdfa9..e2a7ef8556ea 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -22,7 +22,7 @@ pub(crate) fn collect_trait_impls(mut krate: Crate, cx: &mut DocContext<'_>) -> let tcx = cx.tcx; // We need to check if there are errors before running this pass because it would crash when // we try to get auto and blanket implementations. - if tcx.dcx().has_errors_or_lint_errors().is_some() { + if tcx.dcx().has_errors().is_some() { return krate; } diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index bffa17da3b4c..c6989fbbf255 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -24,7 +24,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item) { let sp = source_span_for_markdown_range(cx.tcx, &dox, &range, &item.attrs.doc_strings) .unwrap_or_else(|| item.attr_span(cx.tcx)); - cx.tcx.struct_span_lint_hir(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| { + cx.tcx.node_span_lint(crate::lint::BARE_URLS, hir_id, sp, msg, |lint| { lint.note("bare URLs are not automatically turned into clickable links") .span_suggestion( sp, diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index 782938f10943..e73649c72249 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -99,7 +99,7 @@ fn check_rust_syntax( // All points of divergence have been handled earlier so this can be // done the same way whether the span is precise or not. let hir_id = cx.tcx.local_def_id_to_hir_id(local_id); - cx.tcx.struct_span_lint_hir(crate::lint::INVALID_RUST_CODEBLOCKS, hir_id, sp, msg, |lint| { + cx.tcx.node_span_lint(crate::lint::INVALID_RUST_CODEBLOCKS, hir_id, sp, msg, |lint| { let explanation = if is_ignore { "`ignore` code blocks require valid Rust code for syntax highlighting; \ mark blocks that do not contain Rust code as text" diff --git a/src/librustdoc/passes/lint/html_tags.rs b/src/librustdoc/passes/lint/html_tags.rs index 90874c01102e..da3770aa927a 100644 --- a/src/librustdoc/passes/lint/html_tags.rs +++ b/src/librustdoc/passes/lint/html_tags.rs @@ -25,7 +25,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { Some(sp) => sp, None => item.attr_span(tcx), }; - tcx.struct_span_lint_hir(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| { + tcx.node_span_lint(crate::lint::INVALID_HTML_TAGS, hir_id, sp, msg, |lint| { use rustc_lint_defs::Applicability; // If a tag looks like ``, it might actually be a generic. // We don't try to detect stuff `` because that's not valid HTML, diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 73f6a4263606..9069098bf1a3 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -176,7 +176,7 @@ fn check_inline_or_reference_unknown_redundancy( &item.attrs.doc_strings, )?; - cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { + cx.tcx.node_span_lint(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { lint.span_label(explicit_span, "explicit target is redundant") .span_label(display_span, "because label contains path that resolves to same destination") .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links") @@ -226,7 +226,7 @@ fn check_reference_redundancy( &item.attrs.doc_strings, )?; - cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { + cx.tcx.node_span_lint(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| { lint.span_label(explicit_span, "explicit target is redundant") .span_label(display_span, "because label contains path that resolves to same destination") .span_note(def_span, "referenced explicit link target defined here") diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index 0893cd0b40b5..dbbf39362e31 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -56,7 +56,7 @@ pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) { ) .unwrap_or_else(|| item.attr_span(tcx)); - tcx.struct_span_lint_hir(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| { + tcx.node_span_lint(crate::lint::UNESCAPED_BACKTICKS, hir_id, span, "unescaped backtick", |lint| { let mut help_emitted = false; match element.prev_code_guess { diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs index 74bec5a2e11f..b7d9c16f3483 100644 --- a/src/librustdoc/scrape_examples.rs +++ b/src/librustdoc/scrape_examples.rs @@ -311,7 +311,7 @@ pub(crate) fn run( // The visitor might have found a type error, which we need to // promote to a fatal error - if tcx.dcx().has_errors_or_lint_errors().is_some() { + if tcx.dcx().has_errors().is_some() { return Err(String::from("Compilation failed, aborting rustdoc")); } diff --git a/src/tools/clippy/clippy.toml b/src/tools/clippy/clippy.toml index 4a1805f75235..8c405ac6a4e8 100644 --- a/src/tools/clippy/clippy.toml +++ b/src/tools/clippy/clippy.toml @@ -2,6 +2,6 @@ avoid-breaking-exported-api = false # use the various `span_lint_*` methods instead, which also add a link to the docs disallowed-methods = [ - "rustc_lint::context::LintContext::struct_span_lint", - "rustc_middle::ty::context::TyCtxt::struct_span_lint_hir" + "rustc_lint::context::LintContext::span_lint", + "rustc_middle::ty::context::TyCtxt::node_span_lint" ] diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index 3761ba81f521..bb86b6f30759 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -107,7 +107,7 @@ pub(super) fn check<'tcx>( && let Some(src) = snippet_opt(cx, cast_expr.span) && cast_to.is_floating_point() && let Some(num_lit) = NumericLiteral::from_lit_kind(&src, &lit.node) - && let from_nbits = 128 - n.leading_zeros() + && let from_nbits = 128 - n.get().leading_zeros() && let to_nbits = fp_ty_mantissa_nbits(cast_to) && from_nbits != 0 && to_nbits != 0 diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs index cc74844f2942..b8d7e8f3b07c 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_add.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::{LitIntType, LitKind}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Block, Expr, ExprKind, Stmt, StmtKind}; use rustc_lint::{LateContext, LateLintPass}; @@ -69,7 +70,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingAdd { && clippy_utils::SpanlessEq::new(cx).eq_expr(l, target) && BinOpKind::Add == op1.node && let ExprKind::Lit(lit) = value.kind - && let LitKind::Int(1, LitIntType::Unsuffixed) = lit.node + && let LitKind::Int(Pu128(1), LitIntType::Unsuffixed) = lit.node && block.expr.is_none() { let mut app = Applicability::MachineApplicable; diff --git a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs index 81df1a889c78..127c73ed637b 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_saturating_sub.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::{higher, is_integer_literal, peel_blocks_with_stmt, SpanlessEq}; use rustc_ast::ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass}; @@ -86,7 +87,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitSaturatingSub { match cond_num_val.kind { ExprKind::Lit(cond_lit) => { // Check if the constant is zero - if let LitKind::Int(0, _) = cond_lit.node { + if let LitKind::Int(Pu128(0), _) = cond_lit.node { if cx.typeck_results().expr_ty(cond_left).is_signed() { } else { print_lint_and_sugg(cx, var_name, expr); diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index fda6c9749d43..58f713d81871 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -461,7 +461,7 @@ fn is_array_length_equal_to_range(cx: &LateContext<'_>, start: &Expr<'_>, end: & if let ExprKind::Lit(lit) = expr.kind && let ast::LitKind::Int(value, _) = lit.node { - Some(value) + Some(value.get()) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index 4acf46f73c90..08b8a9e2ff07 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -209,8 +209,8 @@ fn is_end_eq_array_len<'tcx>( && let Some(arr_len) = arr_len_const.try_eval_target_usize(cx.tcx, cx.param_env) { return match limits { - ast::RangeLimits::Closed => end_int + 1 >= arr_len.into(), - ast::RangeLimits::HalfOpen => end_int >= arr_len.into(), + ast::RangeLimits::Closed => end_int.get() + 1 >= arr_len.into(), + ast::RangeLimits::HalfOpen => end_int.get() >= arr_len.into(), }; } diff --git a/src/tools/clippy/clippy_lints/src/manual_bits.rs b/src/tools/clippy/clippy_lints/src/manual_bits.rs index 96c652283daa..aa02e4e7a434 100644 --- a/src/tools/clippy/clippy_lints/src/manual_bits.rs +++ b/src/tools/clippy/clippy_lints/src/manual_bits.rs @@ -3,6 +3,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::get_parent_expr; use clippy_utils::source::snippet_with_context; use rustc_ast::ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, GenericArg, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext}; @@ -62,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for ManualBits { && let Some((real_ty, resolved_ty, other_expr)) = get_one_size_of_ty(cx, left_expr, right_expr) && matches!(resolved_ty.kind(), ty::Int(_) | ty::Uint(_)) && let ExprKind::Lit(lit) = &other_expr.kind - && let LitKind::Int(8, _) = lit.node + && let LitKind::Int(Pu128(8), _) = lit.node { let mut app = Applicability::MachineApplicable; let ty_snip = snippet_with_context(cx, real_ty.span, ctxt, "..", &mut app).0; diff --git a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs index d585290f7773..ec60de92c4ba 100644 --- a/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs +++ b/src/tools/clippy/clippy_lints/src/manual_range_patterns.rs @@ -45,7 +45,7 @@ fn expr_as_i128(expr: &Expr<'_>) -> Option { && let LitKind::Int(num, _) = lit.node { // Intentionally not handling numbers greater than i128::MAX (for u128 literals) for now. - num.try_into().ok() + num.get().try_into().ok() } else { None } diff --git a/src/tools/clippy/clippy_lints/src/manual_strip.rs b/src/tools/clippy/clippy_lints/src/manual_strip.rs index 7b04fd28b896..bcd024360024 100644 --- a/src/tools/clippy/clippy_lints/src/manual_strip.rs +++ b/src/tools/clippy/clippy_lints/src/manual_strip.rs @@ -161,7 +161,7 @@ fn eq_pattern_length<'tcx>(cx: &LateContext<'tcx>, pattern: &Expr<'_>, expr: &'t .. }) = expr.kind { - constant_length(cx, pattern).map_or(false, |length| length == *n) + constant_length(cx, pattern).map_or(false, |length| *n == length) } else { len_arg(cx, expr).map_or(false, |arg| eq_expr_value(cx, pattern, arg)) } diff --git a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs index 5ca161e93096..d645e6c6c05c 100644 --- a/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs +++ b/src/tools/clippy/clippy_lints/src/matches/match_same_arms.rs @@ -293,7 +293,7 @@ impl<'a> NormalizedPat<'a> { LitKind::ByteStr(ref bytes, _) | LitKind::CStr(ref bytes, _) => Self::LitBytes(bytes), LitKind::Byte(val) => Self::LitInt(val.into()), LitKind::Char(val) => Self::LitInt(val.into()), - LitKind::Int(val, _) => Self::LitInt(val), + LitKind::Int(val, _) => Self::LitInt(val.get()), LitKind::Bool(val) => Self::LitBool(val), LitKind::Float(..) | LitKind::Err => Self::Wild, }, @@ -305,7 +305,7 @@ impl<'a> NormalizedPat<'a> { None => 0, Some(e) => match &e.kind { ExprKind::Lit(lit) => match lit.node { - LitKind::Int(val, _) => val, + LitKind::Int(val, _) => val.get(), LitKind::Char(val) => val.into(), LitKind::Byte(val) => val.into(), _ => return Self::Wild, @@ -317,7 +317,7 @@ impl<'a> NormalizedPat<'a> { None => (u128::MAX, RangeEnd::Included), Some(e) => match &e.kind { ExprKind::Lit(lit) => match lit.node { - LitKind::Int(val, _) => (val, bounds), + LitKind::Int(val, _) => (val.get(), bounds), LitKind::Char(val) => (val.into(), bounds), LitKind::Byte(val) => (val.into(), bounds), _ => return Self::Wild, diff --git a/src/tools/clippy/clippy_lints/src/methods/get_first.rs b/src/tools/clippy/clippy_lints/src/methods/get_first.rs index e1f1e4893558..55fcf3728940 100644 --- a/src/tools/clippy/clippy_lints/src/methods/get_first.rs +++ b/src/tools/clippy/clippy_lints/src/methods/get_first.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_lint::LateContext; @@ -20,7 +21,7 @@ pub(super) fn check<'tcx>( && let Some(impl_id) = cx.tcx.impl_of_method(method_id) && let identity = cx.tcx.type_of(impl_id).instantiate_identity() && let hir::ExprKind::Lit(Spanned { - node: LitKind::Int(0, _), + node: LitKind::Int(Pu128(0), _), .. }) = arg.kind { diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs index 29e69b111de6..f198849c5c0c 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -13,7 +13,7 @@ fn expr_as_u128(cx: &LateContext<'_>, e: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = expr_or_init(cx, e).kind && let LitKind::Int(n, _) = lit.node { - Some(n) + Some(n.get()) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs index 63d41677feed..e45c7962f13f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs +++ b/src/tools/clippy/clippy_lints/src/methods/seek_from_current.rs @@ -1,4 +1,5 @@ use rustc_ast::ast::{LitIntType, LitKind}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -41,7 +42,7 @@ fn arg_is_seek_from_current<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) // check if argument of `SeekFrom::Current` is `0` if args.len() == 1 && let ExprKind::Lit(lit) = args[0].kind - && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node + && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node { return true; } diff --git a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs index 9f38460357ba..cc4cb47e35c6 100644 --- a/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs +++ b/src/tools/clippy/clippy_lints/src/methods/seek_to_start_instead_of_rewind.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::implements_trait; use clippy_utils::{is_expr_used_or_unified, match_def_path, paths}; use rustc_ast::ast::{LitIntType, LitKind}; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -31,7 +32,7 @@ pub(super) fn check<'tcx>( && match_def_path(cx, def_id, &paths::STD_IO_SEEKFROM_START) && args1.len() == 1 && let ExprKind::Lit(lit) = args1[0].kind - && let LitKind::Int(0, LitIntType::Unsuffixed) = lit.node + && let LitKind::Int(Pu128(0), LitIntType::Unsuffixed) = lit.node { let method_call_span = expr.span.with_lo(name_span.lo()); span_lint_and_then( diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index ebbdde48b450..f3577ef6082b 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -2,6 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{is_trait_method, path_to_local_id, peel_blocks, strip_pat_refs}; use rustc_ast::ast; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; @@ -150,7 +151,7 @@ pub(super) fn check( }, ); }, - ast::LitKind::Int(0, _) => check_fold_with_op( + ast::LitKind::Int(Pu128(0), _) => check_fold_with_op( cx, expr, acc, @@ -162,7 +163,7 @@ pub(super) fn check( method_name: "sum", }, ), - ast::LitKind::Int(1, _) => { + ast::LitKind::Int(Pu128(1), _) => { check_fold_with_op( cx, expr, diff --git a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs index 9e87fb45aa65..3e271a606115 100644 --- a/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs +++ b/src/tools/clippy/clippy_lints/src/methods/vec_resize_to_zero.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::ty::is_type_diagnostic_item; use rustc_ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; @@ -20,7 +21,7 @@ pub(super) fn check<'tcx>( && let Some(impl_id) = cx.tcx.impl_of_method(method_id) && is_type_diagnostic_item(cx, cx.tcx.type_of(impl_id).instantiate_identity(), sym::Vec) && let ExprKind::Lit(Spanned { - node: LitKind::Int(0, _), + node: LitKind::Int(Pu128(0), _), .. }) = count_arg.kind && let ExprKind::Lit(Spanned { diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index bbc4d0a0f9a5..0e4d39c99902 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -7,6 +7,7 @@ use clippy_utils::source::snippet; use clippy_utils::visitors::for_each_expr; use clippy_utils::{eq_expr_value, hash_expr, higher}; use rustc_ast::{LitKind, RangeLimits}; +use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::{Applicability, Diagnostic}; use rustc_hir::{BinOp, Block, Body, Expr, ExprKind, UnOp}; @@ -102,8 +103,8 @@ fn len_comparison<'hir>( ) -> Option<(LengthComparison, usize, &'hir Expr<'hir>)> { macro_rules! int_lit_pat { ($id:ident) => { - ExprKind::Lit(Spanned { - node: LitKind::Int($id, _), + ExprKind::Lit(&Spanned { + node: LitKind::Int(Pu128($id), _), .. }) }; @@ -112,13 +113,13 @@ fn len_comparison<'hir>( // normalize comparison, `v.len() > 4` becomes `4 < v.len()` // this simplifies the logic a bit let (op, left, right) = normalize_comparison(bin_op.node, left, right)?; - match (op, &left.kind, &right.kind) { - (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, *left as usize, right)), - (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, *right as usize, left)), - (Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, *left as usize, right)), - (Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, *right as usize, left)), - (Rel::Eq, int_lit_pat!(left), _) => Some((LengthComparison::LengthEqualInt, *left as usize, right)), - (Rel::Eq, _, int_lit_pat!(right)) => Some((LengthComparison::LengthEqualInt, *right as usize, left)), + match (op, left.kind, right.kind) { + (Rel::Lt, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanLength, left as usize, right)), + (Rel::Lt, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanInt, right as usize, left)), + (Rel::Le, int_lit_pat!(left), _) => Some((LengthComparison::IntLessThanOrEqualLength, left as usize, right)), + (Rel::Le, _, int_lit_pat!(right)) => Some((LengthComparison::LengthLessThanOrEqualInt, right as usize, left)), + (Rel::Eq, int_lit_pat!(left), _) => Some((LengthComparison::LengthEqualInt, left as usize, right)), + (Rel::Eq, _, int_lit_pat!(right)) => Some((LengthComparison::LengthEqualInt, right as usize, left)), _ => None, } } @@ -206,14 +207,14 @@ impl<'hir> IndexEntry<'hir> { /// for `..=5` this returns `Some(5)` fn upper_index_expr(expr: &Expr<'_>) -> Option { if let ExprKind::Lit(lit) = &expr.kind - && let LitKind::Int(index, _) = lit.node + && let LitKind::Int(Pu128(index), _) = lit.node { Some(index as usize) } else if let Some(higher::Range { end: Some(end), limits, .. }) = higher::Range::hir(expr) && let ExprKind::Lit(lit) = &end.kind - && let LitKind::Int(index @ 1.., _) = lit.node + && let LitKind::Int(Pu128(index @ 1..), _) = lit.node { match limits { RangeLimits::HalfOpen => Some(index as usize - 1), diff --git a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs index c081dec9b6b7..929efb6c574d 100644 --- a/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs +++ b/src/tools/clippy/clippy_lints/src/operators/arithmetic_side_effects.rs @@ -151,7 +151,7 @@ impl ArithmeticSideEffects { if let hir::ExprKind::Lit(lit) = actual.kind && let ast::LitKind::Int(n, _) = lit.node { - return Some(n); + return Some(n.get()); } if let Some(Constant::Int(n)) = constant(cx, cx.typeck_results(), expr) { return Some(n); diff --git a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs index fbf65e92b322..a6aba33e431a 100644 --- a/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs +++ b/src/tools/clippy/clippy_lints/src/operators/verbose_bit_mask.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::Sugg; use rustc_ast::ast::LitKind; +use rustc_data_structures::packed::Pu128; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -19,9 +20,9 @@ pub(super) fn check<'tcx>( && let ExprKind::Binary(op1, left1, right1) = &left.kind && BinOpKind::BitAnd == op1.node && let ExprKind::Lit(lit) = &right1.kind - && let LitKind::Int(n, _) = lit.node + && let LitKind::Int(Pu128(n), _) = lit.node && let ExprKind::Lit(lit1) = &right.kind - && let LitKind::Int(0, _) = lit1.node + && let LitKind::Int(Pu128(0), _) = lit1.node && n.leading_zeros() == n.count_zeros() && n > u128::from(threshold) { diff --git a/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs b/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs index 5059712d69c1..df37619227c8 100644 --- a/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs +++ b/src/tools/clippy/clippy_lints/src/utils/internal_lints/compiler_lint_functions.rs @@ -41,7 +41,6 @@ impl CompilerLintFunctions { pub fn new() -> Self { let mut map = FxHashMap::default(); map.insert("span_lint", "utils::span_lint"); - map.insert("struct_span_lint", "utils::span_lint"); map.insert("lint", "utils::span_lint"); map.insert("span_lint_note", "utils::span_lint_and_note"); map.insert("span_lint_help", "utils::span_lint_and_help"); diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 727f93c83274..61b38391d9e0 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -275,7 +275,7 @@ pub fn lit_to_mir_constant<'tcx>(lit: &LitKind, ty: Option>) -> Constan LitKind::Byte(b) => Constant::Int(u128::from(b)), LitKind::ByteStr(ref s, _) | LitKind::CStr(ref s, _) => Constant::Binary(Lrc::clone(s)), LitKind::Char(c) => Constant::Char(c), - LitKind::Int(n, _) => Constant::Int(n), + LitKind::Int(n, _) => Constant::Int(n.get()), LitKind::Float(ref is, LitFloatType::Suffixed(fty)) => match fty { ast::FloatTy::F32 => Constant::F32(is.as_str().parse().unwrap()), ast::FloatTy::F64 => Constant::F64(is.as_str().parse().unwrap()), diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 7562961538e3..56978eb2ee80 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -47,7 +47,7 @@ fn docs_link(diag: &mut Diagnostic, lint: &'static Lint) { /// ``` pub fn span_lint(cx: &T, lint: &'static Lint, sp: impl Into, msg: &str) { #[expect(clippy::disallowed_methods)] - cx.struct_span_lint(lint, sp, msg.to_string(), |diag| { + cx.span_lint(lint, sp, msg.to_string(), |diag| { docs_link(diag, lint); }); } @@ -81,7 +81,7 @@ pub fn span_lint_and_help( help: &str, ) { #[expect(clippy::disallowed_methods)] - cx.struct_span_lint(lint, span, msg.to_string(), |diag| { + cx.span_lint(lint, span, msg.to_string(), |diag| { let help = help.to_string(); if let Some(help_span) = help_span { diag.span_help(help_span, help.to_string()); @@ -124,7 +124,7 @@ pub fn span_lint_and_note( note: &str, ) { #[expect(clippy::disallowed_methods)] - cx.struct_span_lint(lint, span, msg.to_string(), |diag| { + cx.span_lint(lint, span, msg.to_string(), |diag| { let note = note.to_string(); if let Some(note_span) = note_span { diag.span_note(note_span, note); @@ -146,7 +146,7 @@ where F: FnOnce(&mut Diagnostic), { #[expect(clippy::disallowed_methods)] - cx.struct_span_lint(lint, sp, msg.to_string(), |diag| { + cx.span_lint(lint, sp, msg.to_string(), |diag| { f(diag); docs_link(diag, lint); }); @@ -154,7 +154,7 @@ where pub fn span_lint_hir(cx: &LateContext<'_>, lint: &'static Lint, hir_id: HirId, sp: Span, msg: &str) { #[expect(clippy::disallowed_methods)] - cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| { + cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| { docs_link(diag, lint); }); } @@ -168,7 +168,7 @@ pub fn span_lint_hir_and_then( f: impl FnOnce(&mut Diagnostic), ) { #[expect(clippy::disallowed_methods)] - cx.tcx.struct_span_lint_hir(lint, hir_id, sp, msg.to_string(), |diag| { + cx.tcx.node_span_lint(lint, hir_id, sp, msg.to_string(), |diag| { f(diag); docs_link(diag, lint); }); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index d264e46f1332..ebe520b27eb5 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -80,6 +80,7 @@ use std::sync::{Mutex, MutexGuard, OnceLock}; use itertools::Itertools; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnhashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId, LocalModDefId, LOCAL_CRATE}; @@ -838,7 +839,7 @@ pub fn is_default_equivalent_call(cx: &LateContext<'_>, repl_func: &Expr<'_>) -> pub fn is_default_equivalent(cx: &LateContext<'_>, e: &Expr<'_>) -> bool { match &e.kind { ExprKind::Lit(lit) => match lit.node { - LitKind::Bool(false) | LitKind::Int(0, _) => true, + LitKind::Bool(false) | LitKind::Int(Pu128(0), _) => true, LitKind::Str(s, _) => s.is_empty(), _ => false, }, diff --git a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs similarity index 83% rename from src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs rename to src/tools/clippy/tests/ui-internal/disallow_span_lint.rs index c81d54918cbb..b9b4a07d29d0 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.rs +++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.rs @@ -11,7 +11,7 @@ use rustc_lint::{Lint, LintContext}; use rustc_middle::ty::TyCtxt; pub fn a(cx: impl LintContext, lint: &'static Lint, span: impl Into, msg: impl Into) { - cx.struct_span_lint(lint, span, msg, |_| {}); + cx.span_lint(lint, span, msg, |_| {}); } pub fn b( @@ -21,7 +21,7 @@ pub fn b( span: impl Into, msg: impl Into, ) { - tcx.struct_span_lint_hir(lint, hir_id, span, msg, |_| {}); + tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); } fn main() {} diff --git a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr similarity index 68% rename from src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr rename to src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr index 7d424124f2b1..03556823a8f5 100644 --- a/src/tools/clippy/tests/ui-internal/disallow_struct_span_lint.stderr +++ b/src/tools/clippy/tests/ui-internal/disallow_span_lint.stderr @@ -1,16 +1,16 @@ -error: use of a disallowed method `rustc_lint::context::LintContext::struct_span_lint` +error: use of a disallowed method `rustc_lint::context::LintContext::span_lint` --> $DIR/disallow_struct_span_lint.rs:14:5 | -LL | cx.struct_span_lint(lint, span, msg, |_| {}); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | cx.span_lint(lint, span, msg, |_| {}); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: `-D clippy::disallowed-methods` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::disallowed_methods)]` -error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::struct_span_lint_hir` +error: use of a disallowed method `rustc_middle::ty::context::TyCtxt::node_span_lint` --> $DIR/disallow_struct_span_lint.rs:24:5 | -LL | tcx.struct_span_lint_hir(lint, hir_id, span, msg, |_| {}); +LL | tcx.node_span_lint(lint, hir_id, span, msg, |_| {}); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/let_underscore_lock.rs b/src/tools/clippy/tests/ui/let_underscore_lock.rs index ccac73be79e4..28d8dd498319 100644 --- a/src/tools/clippy/tests/ui/let_underscore_lock.rs +++ b/src/tools/clippy/tests/ui/let_underscore_lock.rs @@ -26,6 +26,7 @@ fn main() { let _ = p_rw; } +#[allow(let_underscore_lock)] fn uplifted() { // shouldn't lint std locks as they were uplifted as rustc's `let_underscore_lock` diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index 80a47c852692..b0b6d9943663 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -10,7 +10,7 @@ #![feature(nonzero_ops)] #![feature(let_chains)] #![feature(lint_reasons)] -#![feature(int_roundings)] +#![cfg_attr(not(bootstrap), feature(trait_upcasting))] // Configure clippy and other lints #![allow( clippy::collapsible_else_if, diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs index 7d46ecd8f6ea..648ac07c43ec 100644 --- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs +++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs @@ -1,3 +1,6 @@ +#![feature(trait_upcasting)] +#![allow(incomplete_features)] + trait Foo: PartialEq + std::fmt::Debug + Send + Sync { fn a(&self) -> i32 { 10 diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs index 75b512f6f729..8d6da0733fe1 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc.rs @@ -1,6 +1,7 @@ //@revisions: stack tree //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(allocator_api)] +#![allow(incomplete_features)] // for trait upcasting +#![feature(allocator_api, trait_upcasting)] use std::alloc::Layout; use std::alloc::{AllocError, Allocator}; diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs index ddaefeca3a3b..8432012a9ba5 100644 --- a/src/tools/miri/tests/pass/dyn-upcast.rs +++ b/src/tools/miri/tests/pass/dyn-upcast.rs @@ -1,3 +1,6 @@ +#![feature(trait_upcasting)] +#![allow(incomplete_features)] + fn main() { basic(); diamond(); diff --git a/src/tools/remote-test-client/src/main.rs b/src/tools/remote-test-client/src/main.rs index bcda930d093c..590c735596ed 100644 --- a/src/tools/remote-test-client/src/main.rs +++ b/src/tools/remote-test-client/src/main.rs @@ -300,7 +300,7 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec) { // Ok now it's time to read all the output. We're receiving "frames" // representing stdout/stderr, so we decode all that here. - let mut header = [0; 5]; + let mut header = [0; 9]; let mut stderr_done = false; let mut stdout_done = false; let mut client = t!(client.into_inner()); @@ -308,10 +308,8 @@ fn run(support_lib_count: usize, exe: String, all_args: Vec) { let mut stderr = io::stderr(); while !stdout_done || !stderr_done { t!(client.read_exact(&mut header)); - let amt = ((header[1] as u64) << 24) - | ((header[2] as u64) << 16) - | ((header[3] as u64) << 8) - | ((header[4] as u64) << 0); + let amt = u64::from_be_bytes(header[1..9].try_into().unwrap()); + if header[0] == 0 { if amt == 0 { stdout_done = true; @@ -349,7 +347,8 @@ fn send(path: &Path, dst: &mut dyn Write) { t!(dst.write_all(&[0])); let mut file = t!(File::open(&path)); let amt = t!(file.metadata()).len(); - t!(dst.write_all(&[(amt >> 24) as u8, (amt >> 16) as u8, (amt >> 8) as u8, (amt >> 0) as u8,])); + + t!(dst.write_all(&amt.to_be_bytes())); t!(io::copy(&mut file, dst)); } diff --git a/src/tools/remote-test-server/src/main.rs b/src/tools/remote-test-server/src/main.rs index 3d61a0675590..68d7aa56c438 100644 --- a/src/tools/remote-test-server/src/main.rs +++ b/src/tools/remote-test-server/src/main.rs @@ -347,7 +347,7 @@ fn recv(dir: &Path, io: &mut B) -> PathBuf { // the filesystem limits. let len = cmp::min(filename.len() - 1, 50); let dst = dir.join(t!(str::from_utf8(&filename[..len]))); - let amt = read_u32(io) as u64; + let amt = read_u64(io); t!(io::copy(&mut io.take(amt), &mut t!(File::create(&dst)))); set_permissions(&dst); dst @@ -365,7 +365,7 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex) { loop { let n = t!(src.read(&mut b)); let mut dst = dst.lock().unwrap(); - t!(dst.write_all(&create_header(which, n as u32))); + t!(dst.write_all(&create_header(which, n as u64))); if n > 0 { t!(dst.write_all(&b[..n])); } else { @@ -377,7 +377,7 @@ fn my_copy(src: &mut dyn Read, which: u8, dst: &Mutex) { fn batch_copy(buf: &[u8], which: u8, dst: &Mutex) { let n = buf.len(); let mut dst = dst.lock().unwrap(); - t!(dst.write_all(&create_header(which, n as u32))); + t!(dst.write_all(&create_header(which, n as u64))); if n > 0 { t!(dst.write_all(buf)); // Marking buf finished @@ -385,13 +385,13 @@ fn batch_copy(buf: &[u8], which: u8, dst: &Mutex) { } } -const fn create_header(which: u8, n: u32) -> [u8; 5] { +const fn create_header(which: u8, n: u64) -> [u8; 9] { let bytes = n.to_be_bytes(); - [which, bytes[0], bytes[1], bytes[2], bytes[3]] + [which, bytes[0], bytes[1], bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7]] } -fn read_u32(r: &mut dyn Read) -> u32 { - let mut len = [0; 4]; +fn read_u64(r: &mut dyn Read) -> u64 { + let mut len = [0; 8]; t!(r.read_exact(&mut len)); - u32::from_be_bytes(len) + u64::from_be_bytes(len) } diff --git a/src/tools/rust-analyzer/.editorconfig b/src/tools/rust-analyzer/.editorconfig index f00ade5fd826..e337066f7eac 100644 --- a/src/tools/rust-analyzer/.editorconfig +++ b/src/tools/rust-analyzer/.editorconfig @@ -8,6 +8,7 @@ end_of_line = lf insert_final_newline = true indent_style = space indent_size = 4 +max_line_length = 100 [*.md] indent_size = 2 diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock index 15d06222eb42..a743d1c870a5 100644 --- a/src/tools/rust-analyzer/Cargo.lock +++ b/src/tools/rust-analyzer/Cargo.lock @@ -160,9 +160,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "chalk-derive" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "329427f28cd2bddaacd47c4dcd3d7082d315c61fb164394c690fe98c1b6ee9d3" +checksum = "5676cea088c32290fe65c82895be9d06dd21e0fa49bb97ca840529e9417ab71a" dependencies = [ "proc-macro2", "quote", @@ -172,9 +172,9 @@ dependencies = [ [[package]] name = "chalk-ir" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9e1e1659238bd598d0f7dbc5034cf1ff46010a3d6827704c9ed443c8359cb484" +checksum = "ff550c2cdd63ff74394214dce03d06386928a641c0f08837535f04af573a966d" dependencies = [ "bitflags 2.4.1", "chalk-derive", @@ -183,9 +183,9 @@ dependencies = [ [[package]] name = "chalk-recursive" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3e0bff0ba1bed11407384fcec0353aeb6888901e63cb47d04505ec47adad847" +checksum = "4c4559e5c9b200240453b07d893f9c3c74413b53b0d33cbe272c68b0b77aa1c3" dependencies = [ "chalk-derive", "chalk-ir", @@ -196,9 +196,9 @@ dependencies = [ [[package]] name = "chalk-solve" -version = "0.95.0" +version = "0.96.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb9c46d501cf83732a91056c0c846ae7a16d6b3c67a6a6bb5e9cc0a2e91563b6" +checksum = "0882e68ce9eb5a0a2413806538494d19df6ee520ab17d1faf489e952f32e98b8" dependencies = [ "chalk-derive", "chalk-ir", @@ -1001,9 +1001,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.6.4" +version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" +checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" [[package]] name = "memmap2" @@ -1532,6 +1532,7 @@ dependencies = [ "lsp-server 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)", "lsp-types", "mbe", + "memchr", "mimalloc", "nohash-hasher", "num_cpus", @@ -1712,9 +1713,9 @@ checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" [[package]] name = "smol_str" -version = "0.2.0" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74212e6bbe9a4352329b2f68ba3130c15a3f26fe88ff22dbdc6cdd58fa85e99c" +checksum = "e6845563ada680337a52d43bb0b29f396f2d911616f6573012645b9e3d048a49" dependencies = [ "serde", ] diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index 35bef151196f..2547f1ccb991 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -105,7 +105,7 @@ dissimilar = "1.0.7" either = "1.9.0" expect-test = "1.4.0" hashbrown = { version = "0.14", features = [ - "inline-more", + "inline-more", ], default-features = false } indexmap = "2.1.0" itertools = "0.12.0" @@ -118,11 +118,11 @@ semver = "1.0.14" serde = { version = "1.0.192", features = ["derive"] } serde_json = "1.0.108" smallvec = { version = "1.10.0", features = [ - "const_new", - "union", - "const_generics", + "const_new", + "union", + "const_generics", ] } -smol_str = "0.2.0" +smol_str = "0.2.1" text-size = "1.1.1" tracing = "0.1.40" tracing-tree = "0.3.0" @@ -138,8 +138,63 @@ xshell = "0.2.5" # We need to freeze the version of the crate, as the raw-api feature is considered unstable dashmap = { version = "=5.5.3", features = ["raw-api"] } +[workspace.lints.rust] +rust_2018_idioms = "warn" +unused_lifetimes = "warn" +semicolon_in_expressions_from_macros = "warn" + [workspace.lints.clippy] -collapsible_if = "allow" -needless_pass_by_value = "allow" -nonminimal_bool = "allow" -redundant_pattern_matching = "allow" +# FIXME Remove the tidy test once the lint table is stable + +## lint groups +complexity = { level = "warn", priority = -1 } +correctness = { level = "deny", priority = -1 } +perf = { level = "deny", priority = -1 } +restriction = { level = "allow", priority = -1 } +style = { level = "warn", priority = -1 } +suspicious = { level = "warn", priority = -1 } + +## allow following lints +# () makes a fine error in most cases +result_unit_err = "allow" +# We don't expose public APIs that matter like this +len_without_is_empty = "allow" +# We have macros that rely on this currently +enum_variant_names = "allow" +# Builder pattern disagrees +new_ret_no_self = "allow" + +## Following lints should be tackled at some point +borrowed_box = "allow" +borrow_deref_ref = "allow" +derivable_impls = "allow" +derived_hash_with_manual_eq = "allow" +field_reassign_with_default = "allow" +forget_non_drop = "allow" +format_collect = "allow" +large_enum_variant = "allow" +needless_doctest_main = "allow" +new_without_default = "allow" +non_canonical_clone_impl = "allow" +non_canonical_partial_ord_impl = "allow" +self_named_constructors = "allow" +skip_while_next = "allow" +too_many_arguments = "allow" +toplevel_ref_arg = "allow" +type_complexity = "allow" +unnecessary_cast = "allow" +unnecessary_filter_map = "allow" +unnecessary_lazy_evaluations = "allow" +unnecessary_mut_passed = "allow" +useless_conversion = "allow" +useless_format = "allow" +wildcard_in_or_patterns = "allow" +wrong_self_convention = "allow" + +## warn at following lints +dbg_macro = "warn" +todo = "warn" +unimplemented = "allow" +rc_buffer = "warn" +# FIXME enable this, we use this pattern a lot so its annoying work ... +# str_to_string = "warn" diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs index e45a81238ac9..852f36ea712a 100644 --- a/src/tools/rust-analyzer/crates/base-db/src/input.rs +++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs @@ -9,7 +9,7 @@ use std::{fmt, mem, ops, str::FromStr}; use cfg::CfgOptions; -use la_arena::{Arena, Idx}; +use la_arena::{Arena, Idx, RawIdx}; use rustc_hash::{FxHashMap, FxHashSet}; use semver::Version; use syntax::SmolStr; @@ -157,6 +157,10 @@ impl CrateOrigin { pub fn is_lib(&self) -> bool { matches!(self, CrateOrigin::Library { .. }) } + + pub fn is_lang(&self) -> bool { + matches!(self, CrateOrigin::Lang { .. }) + } } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -174,7 +178,7 @@ impl From<&str> for LangCrateOrigin { match s { "alloc" => LangCrateOrigin::Alloc, "core" => LangCrateOrigin::Core, - "proc-macro" => LangCrateOrigin::ProcMacro, + "proc-macro" | "proc_macro" => LangCrateOrigin::ProcMacro, "std" => LangCrateOrigin::Std, "test" => LangCrateOrigin::Test, _ => LangCrateOrigin::Other, @@ -257,6 +261,7 @@ impl ReleaseChannel { } } + #[allow(clippy::should_implement_trait)] pub fn from_str(str: &str) -> Option { Some(match str { "" | "stable" => ReleaseChannel::Stable, @@ -326,7 +331,7 @@ impl CrateData { return false; } - if let Some(_) = opts.next() { + if opts.next().is_some() { return false; } } @@ -522,7 +527,7 @@ impl CrateGraph { self.arena.iter().map(|(idx, _)| idx) } - // FIXME: used for `handle_hack_cargo_workspace`, should be removed later + // FIXME: used for fixing up the toolchain sysroot, should be removed and done differently #[doc(hidden)] pub fn iter_mut(&mut self) -> impl Iterator + '_ { self.arena.iter_mut() @@ -619,7 +624,12 @@ impl CrateGraph { /// This will deduplicate the crates of the graph where possible. /// Note that for deduplication to fully work, `self`'s crate dependencies must be sorted by crate id. /// If the crate dependencies were sorted, the resulting graph from this `extend` call will also have the crate dependencies sorted. - pub fn extend(&mut self, mut other: CrateGraph, proc_macros: &mut ProcMacroPaths) { + pub fn extend( + &mut self, + mut other: CrateGraph, + proc_macros: &mut ProcMacroPaths, + on_finished: impl FnOnce(&FxHashMap), + ) { let topo = other.crates_in_topological_order(); let mut id_map: FxHashMap = FxHashMap::default(); for topo in topo { @@ -630,7 +640,7 @@ impl CrateGraph { let res = self.arena.iter().find_map(|(id, data)| { match (&data.origin, &crate_data.origin) { (a, b) if a == b => { - if data.eq_ignoring_origin_and_deps(&crate_data, false) { + if data.eq_ignoring_origin_and_deps(crate_data, false) { return Some((id, false)); } } @@ -642,8 +652,8 @@ impl CrateGraph { // version and discard the library one as the local version may have // dev-dependencies that we want to keep resolving. See #15656 for more // information. - if data.eq_ignoring_origin_and_deps(&crate_data, true) { - return Some((id, if a.is_local() { false } else { true })); + if data.eq_ignoring_origin_and_deps(crate_data, true) { + return Some((id, !a.is_local())); } } (_, _) => return None, @@ -670,6 +680,8 @@ impl CrateGraph { *proc_macros = mem::take(proc_macros).into_iter().map(|(id, macros)| (id_map[&id], macros)).collect(); + + on_finished(&id_map); } fn find_path( @@ -721,6 +733,29 @@ impl CrateGraph { fn hacky_find_crate<'a>(&'a self, display_name: &'a str) -> impl Iterator + 'a { self.iter().filter(move |it| self[*it].display_name.as_deref() == Some(display_name)) } + + /// Removes all crates from this crate graph except for the ones in `to_keep` and fixes up the dependencies. + /// Returns a mapping from old crate ids to new crate ids. + pub fn remove_crates_except(&mut self, to_keep: &[CrateId]) -> Vec> { + let mut id_map = vec![None; self.arena.len()]; + self.arena = std::mem::take(&mut self.arena) + .into_iter() + .filter_map(|(id, data)| if to_keep.contains(&id) { Some((id, data)) } else { None }) + .enumerate() + .map(|(new_id, (id, data))| { + id_map[id.into_raw().into_u32() as usize] = + Some(CrateId::from_raw(RawIdx::from_u32(new_id as u32))); + data + }) + .collect(); + for (_, data) in self.arena.iter_mut() { + data.dependencies.iter_mut().for_each(|dep| { + dep.crate_id = + id_map[dep.crate_id.into_raw().into_u32() as usize].expect("crate was filtered") + }); + } + id_map + } } impl ops::Index for CrateGraph { diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs index 30452e34aac3..8fbfcc81d280 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs @@ -24,12 +24,12 @@ use triomphe::Arc; use crate::{ db::DefDatabase, - item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeNode}, + item_tree::{AttrOwner, Fields, ItemTreeId, ItemTreeModItemNode}, lang_item::LangItem, nameres::{ModuleOrigin, ModuleSource}, src::{HasChildSource, HasSource}, - AdtId, AssocItemLoc, AttrDefId, EnumId, GenericParamId, ItemLoc, LocalEnumVariantId, - LocalFieldId, Lookup, MacroId, VariantId, + AdtId, AssocItemLoc, AttrDefId, GenericParamId, ItemLoc, LocalFieldId, Lookup, MacroId, + VariantId, }; #[derive(Default, Debug, Clone, PartialEq, Eq)] @@ -70,33 +70,6 @@ impl ops::Deref for AttrsWithOwner { impl Attrs { pub const EMPTY: Self = Self(RawAttrs::EMPTY); - pub(crate) fn variants_attrs_query( - db: &dyn DefDatabase, - e: EnumId, - ) -> Arc> { - let _p = profile::span("variants_attrs_query"); - // FIXME: There should be some proper form of mapping between item tree enum variant ids and hir enum variant ids - let mut res = ArenaMap::default(); - - let loc = e.lookup(db); - let krate = loc.container.krate; - let item_tree = loc.id.item_tree(db); - let enum_ = &item_tree[loc.id.value]; - let crate_graph = db.crate_graph(); - let cfg_options = &crate_graph[krate].cfg_options; - - let mut idx = 0; - for variant in enum_.variants.clone() { - let attrs = item_tree.attrs(db, krate, variant.into()); - if attrs.is_cfg_enabled(cfg_options) { - res.insert(Idx::from_raw(RawIdx::from(idx)), attrs); - idx += 1; - } - } - - Arc::new(res) - } - pub(crate) fn fields_attrs_query( db: &dyn DefDatabase, v: VariantId, @@ -108,29 +81,11 @@ impl Attrs { let crate_graph = db.crate_graph(); let (fields, item_tree, krate) = match v { VariantId::EnumVariantId(it) => { - let e = it.parent; - let loc = e.lookup(db); - let krate = loc.container.krate; + let loc = it.lookup(db); + let krate = loc.parent.lookup(db).container.krate; let item_tree = loc.id.item_tree(db); - let enum_ = &item_tree[loc.id.value]; - - let cfg_options = &crate_graph[krate].cfg_options; - - let Some(variant) = enum_ - .variants - .clone() - .filter(|variant| { - let attrs = item_tree.attrs(db, krate, (*variant).into()); - attrs.is_cfg_enabled(cfg_options) - }) - .zip(0u32..) - .find(|(_variant, idx)| it.local_id == Idx::from_raw(RawIdx::from(*idx))) - .map(|(variant, _idx)| variant) - else { - return Arc::new(res); - }; - - (item_tree[variant].fields.clone(), item_tree, krate) + let variant = &item_tree[loc.id.value]; + (variant.fields.clone(), item_tree, krate) } VariantId::StructId(it) => { let loc = it.lookup(db); @@ -401,10 +356,12 @@ impl AttrsWithOwner { AttrDefId::FieldId(it) => { return db.fields_attrs(it.parent)[it.local_id].clone(); } - AttrDefId::EnumVariantId(it) => { - return db.variants_attrs(it.parent)[it.local_id].clone(); - } // FIXME: DRY this up + AttrDefId::EnumVariantId(it) => { + let id = it.lookup(db).id; + let tree = id.item_tree(db); + tree.raw_attrs(id.value.into()).clone() + } AttrDefId::AdtId(it) => match it { AdtId::StructId(it) => attrs_from_item_tree_loc(db, it), AdtId::EnumId(it) => attrs_from_item_tree_loc(db, it), @@ -503,12 +460,7 @@ impl AttrsWithOwner { AdtId::EnumId(id) => any_has_attrs(db, id), }, AttrDefId::FunctionId(id) => any_has_attrs(db, id), - AttrDefId::EnumVariantId(id) => { - let map = db.variants_attrs_source_map(id.parent); - let file_id = id.parent.lookup(db).id.file_id(); - let root = db.parse_or_expand(file_id); - InFile::new(file_id, ast::AnyHasAttrs::new(map[id.local_id].to_node(&root))) - } + AttrDefId::EnumVariantId(id) => any_has_attrs(db, id), AttrDefId::StaticId(id) => any_has_attrs(db, id), AttrDefId::ConstId(id) => any_has_attrs(db, id), AttrDefId::TraitId(id) => any_has_attrs(db, id), @@ -654,13 +606,16 @@ fn any_has_attrs<'db>( id.lookup(db).source(db).map(ast::AnyHasAttrs::new) } -fn attrs_from_item_tree(db: &dyn DefDatabase, id: ItemTreeId) -> RawAttrs { +fn attrs_from_item_tree( + db: &dyn DefDatabase, + id: ItemTreeId, +) -> RawAttrs { let tree = id.item_tree(db); let mod_item = N::id_to_mod_item(id.value); tree.raw_attrs(mod_item.into()).clone() } -fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( +fn attrs_from_item_tree_loc<'db, N: ItemTreeModItemNode>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup = dyn DefDatabase + 'db, Data = ItemLoc>, ) -> RawAttrs { @@ -668,7 +623,7 @@ fn attrs_from_item_tree_loc<'db, N: ItemTreeNode>( attrs_from_item_tree(db, id) } -fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( +fn attrs_from_item_tree_assoc<'db, N: ItemTreeModItemNode>( db: &(dyn DefDatabase + 'db), lookup: impl Lookup = dyn DefDatabase + 'db, Data = AssocItemLoc>, ) -> RawAttrs { @@ -676,20 +631,6 @@ fn attrs_from_item_tree_assoc<'db, N: ItemTreeNode>( attrs_from_item_tree(db, id) } -pub(crate) fn variants_attrs_source_map( - db: &dyn DefDatabase, - def: EnumId, -) -> Arc>> { - let mut res = ArenaMap::default(); - let child_source = def.child_source(db); - - for (idx, variant) in child_source.value.iter() { - res.insert(idx, AstPtr::new(variant)); - } - - Arc::new(res) -} - pub(crate) fn fields_attrs_source_map( db: &dyn DefDatabase, def: VariantId, diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body.rs b/src/tools/rust-analyzer/crates/hir-def/src/body.rs index db28c6731ece..81132d738539 100644 --- a/src/tools/rust-analyzer/crates/hir-def/src/body.rs +++ b/src/tools/rust-analyzer/crates/hir-def/src/body.rs @@ -26,7 +26,7 @@ use crate::{ }, nameres::DefMap, path::{ModPath, Path}, - src::{HasChildSource, HasSource}, + src::HasSource, BlockId, DefWithBodyId, HasModule, Lookup, }; @@ -37,7 +37,7 @@ pub struct Body { pub pats: Arena, pub bindings: Arena, pub labels: Arena