diff options
| author | bors <bors@rust-lang.org> | 2025-06-27 16:10:20 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2025-06-27 16:10:20 +0000 |
| commit | fe5f3dedf7b4d6bea2cadb17343f747d70b4c66b (patch) | |
| tree | a2d21c87c62143398a4550ba96982a29c7d29e9c /compiler | |
| parent | 13c46fd0b089360922a557d8e18a63a2c41dfbeb (diff) | |
| parent | 0bbeeffe57378b9460ec6df4532b8a569003f7f9 (diff) | |
| download | rust-fe5f3dedf7b4d6bea2cadb17343f747d70b4c66b.tar.gz rust-fe5f3dedf7b4d6bea2cadb17343f747d70b4c66b.zip | |
Auto merge of #143091 - GuillaumeGomez:rollup-f300qwe, r=GuillaumeGomez
Rollup of 10 pull requests Successful merges: - rust-lang/rust#142270 (Rustdoc js: even more typechecking improvements) - rust-lang/rust#142420 (Report infer ty errors during hir ty lowering) - rust-lang/rust#142671 (add #![rustc_no_implicit_bounds]) - rust-lang/rust#142721 (Add tracing to `InterpCx::layout_of()` ) - rust-lang/rust#142818 (Port `#[used]` to new attribute parsing infrastructure) - rust-lang/rust#143020 (codegen_fn_attrs: make comment more precise) - rust-lang/rust#143051 (Add tracing to `validate_operand`) - rust-lang/rust#143060 (Only args in main diag are saved and restored without removing the newly added ones) - rust-lang/rust#143065 (Improve recovery when users write `where:`) - rust-lang/rust#143084 (const-eval: error when initializing a static writes to that static) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
51 files changed, 348 insertions, 367 deletions
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 9b4535dcfbc..fc816f2cb79 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -893,7 +893,7 @@ impl Token { || self.is_qpath_start() || matches!(self.is_metavar_seq(), Some(MetaVarKind::Path)) || self.is_path_segment_keyword() - || self.is_ident() && !self.is_reserved_ident() + || self.is_non_reserved_ident() } /// Returns `true` if the token is a given keyword, `kw`. @@ -937,6 +937,10 @@ impl Token { self.is_non_raw_ident_where(Ident::is_reserved) } + pub fn is_non_reserved_ident(&self) -> bool { + self.ident().is_some_and(|(id, raw)| raw == IdentIsRaw::Yes || !Ident::is_reserved(id)) + } + /// Returns `true` if the token is the identifier `true` or `false`. pub fn is_bool_lit(&self) -> bool { self.is_non_raw_ident_where(|id| id.name.is_bool_lit()) diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index 3c231be20dc..c60185cdde0 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -634,10 +634,8 @@ impl TokenStream { ( TokenTree::Token(token_left, Spacing::Alone), TokenTree::Token(token_right, _), - ) if ((token_left.is_ident() && !token_left.is_reserved_ident()) - || token_left.is_lit()) - && ((token_right.is_ident() && !token_right.is_reserved_ident()) - || token_right.is_lit()) => + ) if (token_left.is_non_reserved_ident() || token_left.is_lit()) + && (token_right.is_non_reserved_ident() || token_right.is_lit()) => { token_left.span } diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index d755afad59f..60a4f289306 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -131,6 +131,17 @@ impl Deprecation { } } +/// There are three valid forms of the attribute: +/// `#[used]`, which is semantically equivalent to `#[used(linker)]` except that the latter is currently unstable. +/// `#[used(compiler)]` +/// `#[used(linker)]` +#[derive(Encodable, Decodable, Copy, Clone, Debug, PartialEq, Eq, Hash)] +#[derive(HashStable_Generic, PrintAttribute)] +pub enum UsedBy { + Compiler, + Linker, +} + /// Represents parsed *built-in* inert attributes. /// /// ## Overview @@ -285,5 +296,8 @@ pub enum AttributeKind { /// Represents `#[track_caller]` TrackCaller(Span), + + /// Represents `#[used]` + Used { used_by: UsedBy, span: Span }, // tidy-alphabetical-end } diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs index d4402f4e2e6..64bcf1fe6cc 100644 --- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs @@ -38,6 +38,7 @@ impl AttributeKind { PubTransparent(..) => Yes, SkipDuringMethodDispatch { .. } => No, TrackCaller(..) => Yes, + Used { .. } => No, } } } diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 5a849e79cc3..7c412d4fa89 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,4 +1,4 @@ -use rustc_attr_data_structures::{AttributeKind, OptimizeAttr}; +use rustc_attr_data_structures::{AttributeKind, OptimizeAttr, UsedBy}; use rustc_feature::{AttributeTemplate, template}; use rustc_session::parse::feature_err; use rustc_span::{Span, Symbol, sym}; @@ -228,3 +228,84 @@ impl<S: Stage> SingleAttributeParser<S> for NoMangleParser { Some(AttributeKind::NoMangle(cx.attr_span)) } } + +#[derive(Default)] +pub(crate) struct UsedParser { + first_compiler: Option<Span>, + first_linker: Option<Span>, +} + +// A custom `AttributeParser` is used rather than a Simple attribute parser because +// - Specifying two `#[used]` attributes is a warning (but will be an error in the future) +// - But specifying two conflicting attributes: `#[used(compiler)]` and `#[used(linker)]` is already an error today +// We can change this to a Simple parser once the warning becomes an error +impl<S: Stage> AttributeParser<S> for UsedParser { + const ATTRIBUTES: AcceptMapping<Self, S> = &[( + &[sym::used], + template!(Word, List: "compiler|linker"), + |group: &mut Self, cx, args| { + let used_by = match args { + ArgParser::NoArgs => UsedBy::Linker, + ArgParser::List(list) => { + let Some(l) = list.single() else { + cx.expected_single_argument(list.span); + return; + }; + + match l.meta_item().and_then(|i| i.path().word_sym()) { + Some(sym::compiler) => { + if !cx.features().used_with_arg() { + feature_err( + &cx.sess(), + sym::used_with_arg, + cx.attr_span, + "`#[used(compiler)]` is currently unstable", + ) + .emit(); + } + UsedBy::Compiler + } + Some(sym::linker) => { + if !cx.features().used_with_arg() { + feature_err( + &cx.sess(), + sym::used_with_arg, + cx.attr_span, + "`#[used(linker)]` is currently unstable", + ) + .emit(); + } + UsedBy::Linker + } + _ => { + cx.expected_specific_argument(l.span(), vec!["compiler", "linker"]); + return; + } + } + } + ArgParser::NameValue(_) => return, + }; + + let target = match used_by { + UsedBy::Compiler => &mut group.first_compiler, + UsedBy::Linker => &mut group.first_linker, + }; + + let attr_span = cx.attr_span; + if let Some(prev) = *target { + cx.warn_unused_duplicate(prev, attr_span); + } else { + *target = Some(attr_span); + } + }, + )]; + + fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> { + // Ratcheting behaviour, if both `linker` and `compiler` are specified, use `linker` + Some(match (self.first_compiler, self.first_linker) { + (_, Some(span)) => AttributeKind::Used { used_by: UsedBy::Linker, span }, + (Some(span), _) => AttributeKind::Used { used_by: UsedBy::Compiler, span }, + (None, None) => return None, + }) + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 83e3c75dedb..71bb86ca3d3 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -17,6 +17,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; use crate::attributes::codegen_attrs::{ ColdParser, ExportNameParser, NakedParser, NoMangleParser, OptimizeParser, TrackCallerParser, + UsedParser, }; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; @@ -103,6 +104,7 @@ attribute_parsers!( ConstStabilityParser, NakedParser, StabilityParser, + UsedParser, // tidy-alphabetical-end // tidy-alphabetical-start diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl index 6362d2edf85..84d63819343 100644 --- a/compiler/rustc_codegen_ssa/messages.ftl +++ b/compiler/rustc_codegen_ssa/messages.ftl @@ -48,8 +48,6 @@ codegen_ssa_error_writing_def_file = codegen_ssa_expected_name_value_pair = expected name value pair -codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)` - codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified codegen_ssa_extract_bundled_libs_archive_member = failed to get data from archive member '{$rlib}': {$error} diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 94df5e8b361..acdda32d58a 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -4,7 +4,7 @@ use rustc_abi::ExternAbi; use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode}; use rustc_ast::{LitKind, MetaItem, MetaItemInner, attr}; use rustc_attr_data_structures::{ - AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, find_attr, + AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr, ReprAttr, UsedBy, find_attr, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; @@ -160,6 +160,10 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } codegen_fn_attrs.flags |= CodegenFnAttrFlags::TRACK_CALLER } + AttributeKind::Used { used_by, .. } => match used_by { + UsedBy::Compiler => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER, + UsedBy::Linker => codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER, + }, _ => {} } } @@ -181,44 +185,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::rustc_std_internal_symbol => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } - sym::used => { - let inner = attr.meta_item_list(); - match inner.as_deref() { - Some([item]) if item.has_name(sym::linker) => { - if !tcx.features().used_with_arg() { - feature_err( - &tcx.sess, - sym::used_with_arg, - attr.span(), - "`#[used(linker)]` is currently unstable", - ) - .emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER; - } - Some([item]) if item.has_name(sym::compiler) => { - if !tcx.features().used_with_arg() { - feature_err( - &tcx.sess, - sym::used_with_arg, - attr.span(), - "`#[used(compiler)]` is currently unstable", - ) - .emit(); - } - codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_COMPILER; - } - Some(_) => { - tcx.dcx().emit_err(errors::ExpectedUsedSymbol { span: attr.span() }); - } - None => { - // Unconditionally using `llvm.used` causes issues in handling - // `.init_array` with the gold linker. Luckily gold has been - // deprecated with GCC 15 and rustc now warns about using gold. - codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED_LINKER - } - } - } sym::thread_local => codegen_fn_attrs.flags |= CodegenFnAttrFlags::THREAD_LOCAL, sym::target_feature => { let Some(sig) = tcx.hir_node_by_def_id(did).fn_sig() else { @@ -430,7 +396,9 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { } } - // Apply the minimum function alignment here, so that individual backends don't have to. + // Apply the minimum function alignment here. This ensures that a function's alignment is + // determined by the `-C` flags of the crate it is defined in, not the `-C` flags of the crate + // it happens to be codegen'd (or const-eval'd) in. codegen_fn_attrs.alignment = Ord::max(codegen_fn_attrs.alignment, tcx.sess.opts.unstable_opts.min_function_alignment); diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index db536af0162..1950a35b364 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -727,13 +727,6 @@ pub struct UnknownArchiveKind<'a> { } #[derive(Diagnostic)] -#[diag(codegen_ssa_expected_used_symbol)] -pub(crate) struct ExpectedUsedSymbol { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] #[diag(codegen_ssa_multiple_main_functions)] #[help] pub(crate) struct MultipleMainFunctions { diff --git a/compiler/rustc_const_eval/messages.ftl b/compiler/rustc_const_eval/messages.ftl index 97b154ad142..671ae5975a7 100644 --- a/compiler/rustc_const_eval/messages.ftl +++ b/compiler/rustc_const_eval/messages.ftl @@ -352,7 +352,7 @@ const_eval_realloc_or_alloc_with_offset = *[other] {""} } {$ptr} which does not point to the beginning of an object -const_eval_recursive_static = encountered static that tried to initialize itself with itself +const_eval_recursive_static = encountered static that tried to access itself during initialization const_eval_remainder_by_zero = calculating the remainder with a divisor of zero diff --git a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs index be840191547..569a07c3a01 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -7,7 +7,7 @@ use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ErrorHandled, InterpErrorInfo, ReportedErrorInfo}; use rustc_middle::mir::{self, ConstAlloc, ConstValue}; use rustc_middle::query::TyCtxtAt; -use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, throw_inval}; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index a68dcf29988..2ec3f8432c7 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -62,7 +62,7 @@ pub struct CompileTimeMachine<'tcx> { /// If `Some`, we are evaluating the initializer of the static with the given `LocalDefId`, /// storing the result in the given `AllocId`. - /// Used to prevent reads from a static's base allocation, as that may allow for self-initialization loops. + /// Used to prevent accesses to a static's base allocation, as that may allow for self-initialization loops. pub(crate) static_root_ids: Option<(AllocId, LocalDefId)>, /// A cache of "data range" computations for unions (i.e., the offsets of non-padding bytes). @@ -705,19 +705,27 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { interp_ok(()) } - fn before_alloc_read(ecx: &InterpCx<'tcx, Self>, alloc_id: AllocId) -> InterpResult<'tcx> { + fn before_alloc_access( + tcx: TyCtxtAt<'tcx>, + machine: &Self, + alloc_id: AllocId, + ) -> InterpResult<'tcx> { + if machine.stack.is_empty() { + // Get out of the way for the final copy. + return interp_ok(()); + } // Check if this is the currently evaluated static. - if Some(alloc_id) == ecx.machine.static_root_ids.map(|(id, _)| id) { + if Some(alloc_id) == machine.static_root_ids.map(|(id, _)| id) { return Err(ConstEvalErrKind::RecursiveStatic).into(); } // If this is another static, make sure we fire off the query to detect cycles. // But only do that when checks for static recursion are enabled. - if ecx.machine.static_root_ids.is_some() { - if let Some(GlobalAlloc::Static(def_id)) = ecx.tcx.try_get_global_alloc(alloc_id) { - if ecx.tcx.is_foreign_item(def_id) { + if machine.static_root_ids.is_some() { + if let Some(GlobalAlloc::Static(def_id)) = tcx.try_get_global_alloc(alloc_id) { + if tcx.is_foreign_item(def_id) { throw_unsup!(ExternStatic(def_id)); } - ecx.ctfe_query(|tcx| tcx.eval_static_initializer(def_id))?; + tcx.eval_static_initializer(def_id)?; } } interp_ok(()) diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 73cb1e77436..2aaf718c733 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -2,7 +2,6 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_middle::query::Key; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use tracing::instrument; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index b3d2e1a0598..5ab72c853c4 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -1,7 +1,7 @@ use rustc_abi::{BackendRepr, FieldIdx, VariantIdx}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; -use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::DUMMY_SP; diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 37677f9e048..79c14b204e3 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -6,7 +6,7 @@ use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; use rustc_hir::def_id::DefId; -use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{FnAbiOf, IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, Instance, Ty, VariantDef}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::sym; diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 9e15f4572d7..1036935bb10 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -6,7 +6,7 @@ use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::CastKind; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::adjustment::PointerCoercion; -use rustc_middle::ty::layout::{IntegerExt, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty}; use rustc_middle::{bug, span_bug}; use tracing::trace; diff --git a/compiler/rustc_const_eval/src/interpret/discriminant.rs b/compiler/rustc_const_eval/src/interpret/discriminant.rs index 6c4b000e16b..b7e7f65c95c 100644 --- a/compiler/rustc_const_eval/src/interpret/discriminant.rs +++ b/compiler/rustc_const_eval/src/interpret/discriminant.rs @@ -1,7 +1,7 @@ //! Functions for reading and writing discriminants of multi-variant layouts (enums and coroutines). use rustc_abi::{self as abi, FieldIdx, TagEncoding, VariantIdx, Variants}; -use rustc_middle::ty::layout::{LayoutOf, PrimitiveExt, TyAndLayout}; +use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout}; use rustc_middle::ty::{self, CoroutineArgsExt, ScalarInt, Ty}; use rustc_middle::{mir, span_bug}; use tracing::{instrument, trace}; diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index b69bc0918be..99ca733df58 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -7,7 +7,8 @@ use rustc_hir::def_id::DefId; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::layout::{ - self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOfHelpers, TyAndLayout, + self, FnAbiError, FnAbiOfHelpers, FnAbiRequest, LayoutError, LayoutOf, LayoutOfHelpers, + TyAndLayout, }; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeFoldable, TypingEnv, Variance}; use rustc_middle::{mir, span_bug}; @@ -21,7 +22,7 @@ use super::{ MemPlaceMeta, Memory, OpTy, Place, PlaceTy, PointerArithmetic, Projectable, Provenance, err_inval, interp_ok, throw_inval, throw_ub, throw_ub_custom, }; -use crate::{ReportErrorExt, fluent_generated as fluent, util}; +use crate::{ReportErrorExt, enter_trace_span, fluent_generated as fluent, util}; pub struct InterpCx<'tcx, M: Machine<'tcx>> { /// Stores the `Machine` instance. @@ -91,6 +92,20 @@ impl<'tcx, M: Machine<'tcx>> LayoutOfHelpers<'tcx> for InterpCx<'tcx, M> { } } +impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { + /// This inherent method takes priority over the trait method with the same name in LayoutOf, + /// and allows wrapping the actual [LayoutOf::layout_of] with a tracing span. + /// See [LayoutOf::layout_of] for the original documentation. + #[inline] + pub fn layout_of( + &self, + ty: Ty<'tcx>, + ) -> <InterpCx<'tcx, M> as LayoutOfHelpers<'tcx>>::LayoutOfResult { + let _span = enter_trace_span!(M, "InterpCx::layout_of", "ty = {:?}", ty.kind()); + LayoutOf::layout_of(self, ty) + } +} + impl<'tcx, M: Machine<'tcx>> FnAbiOfHelpers<'tcx> for InterpCx<'tcx, M> { type FnAbiOfResult = Result<&'tcx FnAbi<'tcx, Ty<'tcx>>, InterpErrorKind<'tcx>>; @@ -284,6 +299,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { frame: &Frame<'tcx, M::Provenance, M::FrameExtra>, value: T, ) -> Result<T, ErrorHandled> { + let _span = enter_trace_span!( + M, + "instantiate_from_frame_and_normalize_erasing_regions", + "{}", + frame.instance + ); frame .instance .try_instantiate_mir_and_normalize_erasing_regions( diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 96c39c7bb32..6acc89c8b02 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -8,7 +8,7 @@ use rustc_abi::Size; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_hir::def_id::DefId; use rustc_middle::mir::{self, BinOp, ConstValue, NonDivergingIntrinsic}; -use rustc_middle::ty::layout::{LayoutOf as _, TyAndLayout, ValidityRequirement}; +use rustc_middle::ty::layout::{TyAndLayout, ValidityRequirement}; use rustc_middle::ty::{GenericArgsRef, Ty, TyCtxt}; use rustc_middle::{bug, ty}; use rustc_span::{Symbol, sym}; diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs index b9e022c9604..d6d230fbd17 100644 --- a/compiler/rustc_const_eval/src/interpret/machine.rs +++ b/compiler/rustc_const_eval/src/interpret/machine.rs @@ -443,7 +443,11 @@ pub trait Machine<'tcx>: Sized { /// /// Used to prevent statics from self-initializing by reading from their own memory /// as it is being initialized. - fn before_alloc_read(_ecx: &InterpCx<'tcx, Self>, _alloc_id: AllocId) -> InterpResult<'tcx> { + fn before_alloc_access( + _tcx: TyCtxtAt<'tcx>, + _machine: &Self, + _alloc_id: AllocId, + ) -> InterpResult<'tcx> { interp_ok(()) } diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs index 57bf867e389..69fceb02ff9 100644 --- a/compiler/rustc_const_eval/src/interpret/memory.rs +++ b/compiler/rustc_const_eval/src/interpret/memory.rs @@ -720,7 +720,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { // do this after `check_and_deref_ptr` to ensure some basic sanity has already been checked. if !self.memory.validation_in_progress.get() { if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(ptr, size_i64) { - M::before_alloc_read(self, alloc_id)?; + M::before_alloc_access(self.tcx, &self.machine, alloc_id)?; } } @@ -821,6 +821,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { if let Some((alloc_id, offset, prov, alloc, machine)) = ptr_and_alloc { let range = alloc_range(offset, size); if !validation_in_progress { + // For writes, it's okay to only call those when there actually is a non-zero + // amount of bytes to be written: a zero-sized write doesn't manifest anything. + M::before_alloc_access(tcx, machine, alloc_id)?; M::before_memory_write( tcx, machine, @@ -1396,6 +1399,14 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let src_parts = self.get_ptr_access(src, size)?; let dest_parts = self.get_ptr_access(dest, size * num_copies)?; // `Size` multiplication + // Similar to `get_ptr_alloc`, we need to call `before_alloc_access` even for zero-sized + // reads. However, just like in `get_ptr_alloc_mut`, the write part is okay to skip for + // zero-sized writes. + if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(src, size.bytes().try_into().unwrap()) + { + M::before_alloc_access(tcx, &self.machine, alloc_id)?; + } + // FIXME: we look up both allocations twice here, once before for the `check_ptr_access` // and once below to get the underlying `&[mut] Allocation`. @@ -1408,12 +1419,9 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let src_range = alloc_range(src_offset, size); assert!(!self.memory.validation_in_progress.get(), "we can't be copying during validation"); - // Trigger read hooks. - // For the overlapping case, it is crucial that we trigger the read hooks + // Trigger read hook. + // For the overlapping case, it is crucial that we trigger the read hook // before the write hook -- the aliasing model cares about the order. - if let Ok((alloc_id, ..)) = self.ptr_try_get_alloc_id(src, size.bytes() as i64) { - M::before_alloc_read(self, alloc_id)?; - } M::before_memory_read( tcx, &self.machine, @@ -1438,16 +1446,18 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { let provenance = src_alloc .provenance() .prepare_copy(src_range, dest_offset, num_copies, self) - .map_err(|e| e.to_interp_error(dest_alloc_id))?; + .map_err(|e| e.to_interp_error(src_alloc_id))?; // Prepare a copy of the initialization mask. let init = src_alloc.init_mask().prepare_copy(src_range); - // Destination alloc preparations and access hooks. - let (dest_alloc, extra) = self.get_alloc_raw_mut(dest_alloc_id)?; + // Destination alloc preparations... + let (dest_alloc, machine) = self.get_alloc_raw_mut(dest_alloc_id)?; let dest_range = alloc_range(dest_offset, size * num_copies); + // ...and access hooks. + M::before_alloc_access(tcx, machine, dest_alloc_id)?; M::before_memory_write( tcx, - extra, + machine, &mut dest_alloc.extra, dest, (dest_alloc_id, dest_prov), diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs index 337b1617676..62cbbae24a8 100644 --- a/compiler/rustc_const_eval/src/interpret/operand.rs +++ b/compiler/rustc_const_eval/src/interpret/operand.rs @@ -8,7 +8,7 @@ use rustc_abi as abi; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_hir::def::Namespace; use rustc_middle::mir::interpret::ScalarSizeMismatch; -use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter}; use rustc_middle::ty::{ConstInt, ScalarInt, Ty, TyCtxt}; use rustc_middle::{bug, mir, span_bug, ty}; diff --git a/compiler/rustc_const_eval/src/interpret/operator.rs b/compiler/rustc_const_eval/src/interpret/operator.rs index 899670aeb62..74f8a0a7b09 100644 --- a/compiler/rustc_const_eval/src/interpret/operator.rs +++ b/compiler/rustc_const_eval/src/interpret/operator.rs @@ -3,7 +3,7 @@ use rustc_abi::Size; use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::NullOp; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FloatTy, ScalarInt, Ty}; use rustc_middle::{bug, mir, span_bug}; use rustc_span::sym; diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs index e4885af7faf..88f323e0c56 100644 --- a/compiler/rustc_const_eval/src/interpret/place.rs +++ b/compiler/rustc_const_eval/src/interpret/place.rs @@ -7,7 +7,7 @@ use std::assert_matches::assert_matches; use either::{Either, Left, Right}; use rustc_abi::{BackendRepr, HasDataLayout, Size}; use rustc_middle::ty::Ty; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, mir, span_bug}; use tracing::{instrument, trace}; diff --git a/compiler/rustc_const_eval/src/interpret/projection.rs b/compiler/rustc_const_eval/src/interpret/projection.rs index ad47a19a14d..a71affb1be1 100644 --- a/compiler/rustc_const_eval/src/interpret/projection.rs +++ b/compiler/rustc_const_eval/src/interpret/projection.rs @@ -12,7 +12,7 @@ use std::ops::Range; use rustc_abi::{self as abi, FieldIdx, Size, VariantIdx}; use rustc_middle::ty::Ty; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::{bug, mir, span_bug, ty}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_const_eval/src/interpret/stack.rs b/compiler/rustc_const_eval/src/interpret/stack.rs index 2a2d1bb2754..3361a586b8e 100644 --- a/compiler/rustc_const_eval/src/interpret/stack.rs +++ b/compiler/rustc_const_eval/src/interpret/stack.rs @@ -7,7 +7,7 @@ use either::{Either, Left, Right}; use rustc_hir as hir; use rustc_hir::definitions::DefPathData; use rustc_index::IndexVec; -use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_mir_dataflow::impls::always_storage_live_locals; diff --git a/compiler/rustc_const_eval/src/interpret/traits.rs b/compiler/rustc_const_eval/src/interpret/traits.rs index 7249ef23bf6..8b634955bb7 100644 --- a/compiler/rustc_const_eval/src/interpret/traits.rs +++ b/compiler/rustc_const_eval/src/interpret/traits.rs @@ -1,6 +1,5 @@ use rustc_abi::{Align, FieldIdx, Size}; use rustc_middle::mir::interpret::{InterpResult, Pointer}; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ExistentialPredicateStableCmpExt, Ty, TyCtxt, VtblEntry}; use tracing::trace; diff --git a/compiler/rustc_const_eval/src/interpret/validity.rs b/compiler/rustc_const_eval/src/interpret/validity.rs index 7e26b7f3d96..099ee4e16ff 100644 --- a/compiler/rustc_const_eval/src/interpret/validity.rs +++ b/compiler/rustc_const_eval/src/interpret/validity.rs @@ -24,7 +24,7 @@ use rustc_middle::mir::interpret::{ ExpectedKind, InterpErrorKind, InvalidMetaKind, Misalignment, PointerKind, Provenance, UnsupportedOpInfo, ValidationErrorInfo, alloc_range, interp_ok, }; -use rustc_middle::ty::layout::{LayoutCx, LayoutOf, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_span::{Symbol, sym}; use tracing::trace; @@ -35,6 +35,7 @@ use super::{ Machine, MemPlaceMeta, PlaceTy, Pointer, Projectable, Scalar, ValueVisitor, err_ub, format_interp_error, }; +use crate::enter_trace_span; // for the validation errors #[rustfmt::skip] @@ -1363,8 +1364,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }) } - /// This function checks the data at `op` to be const-valid. - /// `op` is assumed to cover valid memory if it is an indirect operand. + /// This function checks the data at `val` to be const-valid. + /// `val` is assumed to cover valid memory if it is an indirect operand. /// It will error if the bits at the destination do not match the ones described by the layout. /// /// `ref_tracking` is used to record references that we encounter so that they @@ -1390,8 +1391,8 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { ) } - /// This function checks the data at `op` to be runtime-valid. - /// `op` is assumed to cover valid memory if it is an indirect operand. + /// This function checks the data at `val` to be runtime-valid. + /// `val` is assumed to cover valid memory if it is an indirect operand. /// It will error if the bits at the destination do not match the ones described by the layout. #[inline(always)] pub fn validate_operand( @@ -1400,6 +1401,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { recursive: bool, reset_provenance_and_padding: bool, ) -> InterpResult<'tcx> { + let _span = enter_trace_span!( + M, + "validate_operand", + "recursive={recursive}, reset_provenance_and_padding={reset_provenance_and_padding}, val={val:?}" + ); + // Note that we *could* actually be in CTFE here with `-Zextra-const-ub-checks`, but it's // still correct to not use `ctfe_mode`: that mode is for validation of the final constant // value, it rules out things like `UnsafeCell` in awkward places. diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs index 5aea91233bd..d5970b69baf 100644 --- a/compiler/rustc_const_eval/src/interpret/visitor.rs +++ b/compiler/rustc_const_eval/src/interpret/visitor.rs @@ -6,7 +6,6 @@ use std::num::NonZero; use rustc_abi::{FieldIdx, FieldsShape, VariantIdx, Variants}; use rustc_index::IndexVec; use rustc_middle::mir::interpret::InterpResult; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty}; use tracing::trace; diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 671214002a0..ab2de279ed8 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -1,6 +1,5 @@ use rustc_abi::FieldIdx; use rustc_hir::LangItem; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::{bug, mir}; use rustc_span::Symbol; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 8e1392998d4..7d9915d7f68 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -1140,6 +1140,10 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[ WarnFollowing, EncodeCrossCrate::Yes ), rustc_attr!( + TEST, rustc_no_implicit_bounds, CrateLevel, template!(Word), + WarnFollowing, EncodeCrossCrate::No + ), + rustc_attr!( TEST, rustc_strict_coherence, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes ), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 88e0ee1cc0b..75dff588669 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3141,6 +3141,15 @@ pub enum TraitItemKind<'hir> { /// type. Type(GenericBounds<'hir>, Option<&'hir Ty<'hir>>), } +impl TraitItemKind<'_> { + pub fn descr(&self) -> &'static str { + match self { + TraitItemKind::Const(..) => "associated constant", + TraitItemKind::Fn(..) => "function", + TraitItemKind::Type(..) => "associated type", + } + } +} // The bodies for items are stored "out of line", in a separate // hashmap in the `Crate`. Here we just record the hir-id of the item @@ -3202,6 +3211,15 @@ pub enum ImplItemKind<'hir> { /// An associated type. Type(&'hir Ty<'hir>), } +impl ImplItemKind<'_> { + pub fn descr(&self) -> &'static str { + match self { + ImplItemKind::Const(..) => "associated constant", + ImplItemKind::Fn(..) => "function", + ImplItemKind::Type(..) => "associated type", + } + } +} /// A constraint on an associated item. /// @@ -4527,6 +4545,16 @@ pub enum ForeignItemKind<'hir> { Type, } +impl ForeignItemKind<'_> { + pub fn descr(&self) -> &'static str { + match self { + ForeignItemKind::Fn(..) => "function", + ForeignItemKind::Static(..) => "static variable", + ForeignItemKind::Type => "type", + } + } +} + /// A variable captured by a closure. #[derive(Debug, Copy, Clone, HashStable_Generic)] pub struct Upvar { diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 00f9347b1cc..89ce74879d8 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -231,7 +231,6 @@ fn check_item<'tcx>(tcx: TyCtxt<'tcx>, item: &'tcx hir::Item<'tcx>) -> Result<() item.name = ? tcx.def_path_str(def_id) ); crate::collect::lower_item(tcx, item.item_id()); - crate::collect::reject_placeholder_type_signatures_in_item(tcx, item); let res = match item.kind { // Right now we check that every default trait implementation diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c967e87bfd8..d7568554669 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -29,7 +29,7 @@ use rustc_errors::{ }; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt, walk_generics}; +use rustc_hir::intravisit::{InferKind, Visitor, VisitorExt}; use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; @@ -154,26 +154,7 @@ impl<'v> Visitor<'v> for HirPlaceholderCollector { } } -/// If there are any placeholder types (`_`), emit an error explaining that this is not allowed -/// and suggest adding type parameters in the appropriate place, taking into consideration any and -/// all already existing generic type parameters to avoid suggesting a name that is already in use. -pub(crate) fn placeholder_type_error<'tcx>( - cx: &dyn HirTyLowerer<'tcx>, - generics: Option<&hir::Generics<'_>>, - placeholder_types: Vec<Span>, - suggest: bool, - hir_ty: Option<&hir::Ty<'_>>, - kind: &'static str, -) { - if placeholder_types.is_empty() { - return; - } - - placeholder_type_error_diag(cx, generics, placeholder_types, vec![], suggest, hir_ty, kind) - .emit(); -} - -pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>( +fn placeholder_type_error_diag<'cx, 'tcx>( cx: &'cx dyn HirTyLowerer<'tcx>, generics: Option<&hir::Generics<'_>>, placeholder_types: Vec<Span>, @@ -245,37 +226,6 @@ pub(crate) fn placeholder_type_error_diag<'cx, 'tcx>( err } -pub(super) fn reject_placeholder_type_signatures_in_item<'tcx>( - tcx: TyCtxt<'tcx>, - item: &'tcx hir::Item<'tcx>, -) { - let (generics, suggest) = match &item.kind { - hir::ItemKind::Union(_, generics, _) - | hir::ItemKind::Enum(_, generics, _) - | hir::ItemKind::TraitAlias(_, generics, _) - | hir::ItemKind::Trait(_, _, _, generics, ..) - | hir::ItemKind::Impl(hir::Impl { generics, .. }) - | hir::ItemKind::Struct(_, generics, _) => (generics, true), - hir::ItemKind::TyAlias(_, generics, _) => (generics, false), - // `static`, `fn` and `const` are handled elsewhere to suggest appropriate type. - _ => return, - }; - - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_item(item); - - let icx = ItemCtxt::new(tcx, item.owner_id.def_id); - - placeholder_type_error( - icx.lowerer(), - Some(generics), - visitor.spans, - suggest && !visitor.may_contain_const_infer, - None, - item.kind.descr(), - ); -} - /////////////////////////////////////////////////////////////////////////// // Utility types and common code for the above passes. @@ -313,6 +263,54 @@ impl<'tcx> ItemCtxt<'tcx> { None => Ok(()), } } + + fn report_placeholder_type_error( + &self, + placeholder_types: Vec<Span>, + infer_replacements: Vec<(Span, String)>, + ) -> ErrorGuaranteed { + let node = self.tcx.hir_node_by_def_id(self.item_def_id); + let generics = node.generics(); + let kind_id = match node { + Node::GenericParam(_) | Node::WherePredicate(_) | Node::Field(_) => { + self.tcx.local_parent(self.item_def_id) + } + _ => self.item_def_id, + }; + // FIXME: just invoke `tcx.def_descr` instead of going through the HIR + // Can also remove most `descr` methods then. + let kind = match self.tcx.hir_node_by_def_id(kind_id) { + Node::Item(it) => it.kind.descr(), + Node::ImplItem(it) => it.kind.descr(), + Node::TraitItem(it) => it.kind.descr(), + Node::ForeignItem(it) => it.kind.descr(), + Node::OpaqueTy(_) => "opaque type", + Node::Synthetic => self.tcx.def_descr(kind_id.into()), + node => todo!("{node:#?}"), + }; + let mut diag = placeholder_type_error_diag( + self, + generics, + placeholder_types, + infer_replacements.iter().map(|&(span, _)| span).collect(), + false, + None, + kind, + ); + if !infer_replacements.is_empty() { + diag.multipart_suggestion( + format!( + "try replacing `_` with the type{} in the corresponding trait method \ + signature", + rustc_errors::pluralize!(infer_replacements.len()), + ), + infer_replacements, + Applicability::MachineApplicable, + ); + } + + diag.emit() + } } impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { @@ -346,10 +344,14 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { + if !self.tcx.dcx().has_stashed_diagnostic(span, StashKey::ItemNoType) { + self.report_placeholder_type_error(vec![span], vec![]); + } Ty::new_error_with_message(self.tcx(), span, "bad placeholder type") } fn ct_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Const<'tcx> { + self.report_placeholder_type_error(vec![span], vec![]); ty::Const::new_error_with_message(self.tcx(), span, "bad placeholder constant") } @@ -524,18 +526,13 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { fn lower_fn_sig( &self, decl: &hir::FnDecl<'tcx>, - generics: Option<&hir::Generics<'_>>, + _generics: Option<&hir::Generics<'_>>, hir_id: rustc_hir::HirId, - hir_ty: Option<&hir::Ty<'_>>, + _hir_ty: Option<&hir::Ty<'_>>, ) -> (Vec<Ty<'tcx>>, Ty<'tcx>) { let tcx = self.tcx(); - // We proactively collect all the inferred type params to emit a single error per fn def. - let mut visitor = HirPlaceholderCollector::default(); - let mut infer_replacements = vec![]; - if let Some(generics) = generics { - walk_generics(&mut visitor, generics); - } + let mut infer_replacements = vec![]; let input_tys = decl .inputs @@ -551,8 +548,6 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { } } - // Only visit the type looking for `_` if we didn't fix the type above - visitor.visit_ty_unambig(a); self.lowerer().lower_ty(a) }) .collect(); @@ -566,42 +561,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { infer_replacements.push((output.span, suggested_ty.to_string())); Ty::new_error_with_message(tcx, output.span, suggested_ty.to_string()) } else { - visitor.visit_ty_unambig(output); self.lower_ty(output) } } hir::FnRetTy::DefaultReturn(..) => tcx.types.unit, }; - if !(visitor.spans.is_empty() && infer_replacements.is_empty()) { - // We check for the presence of - // `ident_span` to not emit an error twice when we have `fn foo(_: fn() -> _)`. - - let mut diag = crate::collect::placeholder_type_error_diag( - self, - generics, - visitor.spans, - infer_replacements.iter().map(|(s, _)| *s).collect(), - !visitor.may_contain_const_infer, - hir_ty, - "function", - ); - - if !infer_replacements.is_empty() { - diag.multipart_suggestion( - format!( - "try replacing `_` with the type{} in the corresponding trait method \ - signature", - rustc_errors::pluralize!(infer_replacements.len()), - ), - infer_replacements, - Applicability::MachineApplicable, - ); - } - - diag.emit(); + if !infer_replacements.is_empty() { + self.report_placeholder_type_error(vec![], infer_replacements); } - (input_tys, output_ty) } @@ -652,7 +620,6 @@ pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { let it = tcx.hir_item(item_id); debug!(item = ?it.kind.ident(), id = %it.hir_id()); let def_id = item_id.owner_id.def_id; - let icx = ItemCtxt::new(tcx, def_id); match &it.kind { // These don't define types. @@ -678,16 +645,6 @@ pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { } hir::ForeignItemKind::Static(..) => { tcx.ensure_ok().codegen_fn_attrs(item.owner_id); - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_foreign_item(item); - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - "static variable", - ); } _ => (), } @@ -741,22 +698,10 @@ pub(super) fn lower_item(tcx: TyCtxt<'_>, item_id: hir::ItemId) { tcx.ensure_ok().predicates_of(def_id); } - hir::ItemKind::Static(_, _, ty, _) | hir::ItemKind::Const(_, _, ty, _) => { + hir::ItemKind::Static(..) | hir::ItemKind::Const(..) => { tcx.ensure_ok().generics_of(def_id); tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); - if !ty.is_suggestable_infer_ty() { - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_item(it); - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - it.kind.descr(), - ); - } } hir::ItemKind::Fn { .. } => { @@ -773,7 +718,6 @@ pub(crate) fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) let trait_item = tcx.hir_trait_item(trait_item_id); let def_id = trait_item_id.owner_id; tcx.ensure_ok().generics_of(def_id); - let icx = ItemCtxt::new(tcx, def_id.def_id); match trait_item.kind { hir::TraitItemKind::Fn(..) => { @@ -782,58 +726,19 @@ pub(crate) fn lower_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::TraitItemId) tcx.ensure_ok().fn_sig(def_id); } - hir::TraitItemKind::Const(ty, body_id) => { + hir::TraitItemKind::Const(..) => { tcx.ensure_ok().type_of(def_id); - if !tcx.dcx().has_stashed_diagnostic(ty.span, StashKey::ItemNoType) - && !(ty.is_suggestable_infer_ty() && body_id.is_some()) - { - // Account for `const C: _;`. - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_trait_item(trait_item); - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - "associated constant", - ); - } } hir::TraitItemKind::Type(_, Some(_)) => { tcx.ensure_ok().item_bounds(def_id); tcx.ensure_ok().item_self_bounds(def_id); tcx.ensure_ok().type_of(def_id); - // Account for `type T = _;`. - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_trait_item(trait_item); - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - "associated type", - ); } hir::TraitItemKind::Type(_, None) => { tcx.ensure_ok().item_bounds(def_id); tcx.ensure_ok().item_self_bounds(def_id); - // #74612: Visit and try to find bad placeholders - // even if there is no concrete type. - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_trait_item(trait_item); - - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - "associated type", - ); } }; @@ -846,41 +751,13 @@ pub(super) fn lower_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::ImplItemId) { tcx.ensure_ok().type_of(def_id); tcx.ensure_ok().predicates_of(def_id); let impl_item = tcx.hir_impl_item(impl_item_id); - let icx = ItemCtxt::new(tcx, def_id.def_id); match impl_item.kind { hir::ImplItemKind::Fn(..) => { tcx.ensure_ok().codegen_fn_attrs(def_id); tcx.ensure_ok().fn_sig(def_id); } - hir::ImplItemKind::Type(_) => { - // Account for `type T = _;` - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_impl_item(impl_item); - - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - "associated type", - ); - } - hir::ImplItemKind::Const(ty, _) => { - // Account for `const T: _ = ..;` - if !ty.is_suggestable_infer_ty() { - let mut visitor = HirPlaceholderCollector::default(); - visitor.visit_impl_item(impl_item); - placeholder_type_error( - icx.lowerer(), - None, - visitor.spans, - false, - None, - "associated constant", - ); - } - } + hir::ImplItemKind::Type(_) => {} + hir::ImplItemKind::Const(..) => {} } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index ea1dfdfd806..e06df5e4679 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -5,14 +5,14 @@ use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LocalDefId}; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::{AmbigArg, LangItem, PolyTraitRef}; use rustc_middle::bug; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, }; -use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw}; +use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym}; use rustc_trait_selection::traits; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -188,6 +188,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) { let tcx = self.tcx(); + // Skip adding any default bounds if `#![rustc_no_implicit_bounds]` + if tcx.has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) { + return; + } + let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, span); let pointee_sized_did = tcx.require_lang_item(LangItem::PointeeSized, span); @@ -408,24 +413,21 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let tcx = self.tcx(); let trait_id = tcx.lang_items().get(trait_); if let Some(trait_id) = trait_id - && self.do_not_provide_default_trait_bound( - trait_id, - hir_bounds, - self_ty_where_predicates, - ) + && self.should_add_default_traits(trait_id, hir_bounds, self_ty_where_predicates) { add_trait_bound(tcx, bounds, self_ty, trait_id, span); } } - fn do_not_provide_default_trait_bound<'a>( + /// Returns `true` if default trait bound should be added. + fn should_add_default_traits<'a>( &self, trait_def_id: DefId, hir_bounds: &'a [hir::GenericBound<'tcx>], self_ty_where_predicates: Option<(LocalDefId, &'tcx [hir::WherePredicate<'tcx>])>, ) -> bool { let collected = collect_bounds(hir_bounds, self_ty_where_predicates, trait_def_id); - !collected.any() + !self.tcx().has_attr(CRATE_DEF_ID, sym::rustc_no_implicit_bounds) && !collected.any() } /// Lower HIR bounds into `bounds` given the self type `param_ty` and the overarching late-bound vars if any. diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 04fdada8024..dcd0116d804 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -220,7 +220,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } /// Generates the code for a field with no attributes. - fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> (TokenStream, TokenStream) { + fn generate_field_arg(&mut self, binding_info: &BindingInfo<'_>) -> TokenStream { let diag = &self.parent.diag; let field = binding_info.ast(); @@ -230,16 +230,12 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let ident = field.ident.as_ref().unwrap(); let ident = format_ident!("{}", ident); // strip `r#` prefix, if present - let args = quote! { + quote! { #diag.arg( stringify!(#ident), #field_binding ); - }; - let remove_args = quote! { - #diag.remove_arg(stringify!(#ident)); - }; - (args, remove_args) + } } /// Generates the necessary code for all attributes on a field. @@ -610,7 +606,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let restore_args = quote! { #diag.restore_args(); }; - let (plain_args, remove_args): (TokenStream, TokenStream) = self + let plain_args: TokenStream = self .variant .bindings() .iter() @@ -623,9 +619,8 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { // For #[derive(Subdiagnostic)] // // - Store args of the main diagnostic for later restore. - // - add args of subdiagnostic. + // - Add args of subdiagnostic. // - Generate the calls, such as note, label, etc. - // - Remove the arguments for allowing Vec<Subdiagnostic> to be used. // - Restore the arguments for allowing main and subdiagnostic share the same fields. Ok(quote! { #init @@ -634,7 +629,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { #store_args #plain_args #calls - #remove_args #restore_args }) } diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index 51f57e71ce9..69b8be3d9cb 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -768,6 +768,7 @@ impl<'tcx> TyCtxt<'tcx> { pub fn def_kind_descr(self, def_kind: DefKind, def_id: DefId) -> &'static str { match def_kind { DefKind::AssocFn if self.associated_item(def_id).is_method() => "method", + DefKind::AssocTy if self.opt_rpitit_info(def_id).is_some() => "opaque type", DefKind::Closure if let Some(coroutine_kind) = self.coroutine_kind(def_id) => { match coroutine_kind { hir::CoroutineKind::Desugared( diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 0cf8142a560..fe53de31f75 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -16,7 +16,6 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::{InterpResult, Scalar}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor}; use rustc_middle::mir::*; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_mir_dataflow::fmt::DebugWithContext; use rustc_mir_dataflow::lattice::{FlatSet, HasBottom}; diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index bda71ceaa55..1ead241c3ba 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -102,7 +102,7 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::GlobalAlloc; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; -use rustc_middle::ty::layout::{HasTypingEnv, LayoutOf}; +use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs index b45bff2af44..f9e642e28eb 100644 --- a/compiler/rustc_mir_transform/src/jump_threading.rs +++ b/compiler/rustc_mir_transform/src/jump_threading.rs @@ -45,7 +45,6 @@ use rustc_middle::bug; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, ScalarInt, TyCtxt}; use rustc_mir_dataflow::lattice::HasBottom; use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem}; diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index a64bb424117..1df0ccbd8af 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2731,7 +2731,7 @@ impl<'a> Parser<'a> { return first_pat; } if !matches!(first_pat.kind, PatKind::Ident(_, _, None) | PatKind::Path(..)) - || !self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) + || !self.look_ahead(1, |token| token.is_non_reserved_ident()) { let mut snapshot_type = self.create_snapshot_for_diagnostic(); snapshot_type.bump(); // `:` diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 4e312aab497..3cedc86dc0d 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3875,8 +3875,7 @@ impl<'a> Parser<'a> { // Check if a colon exists one ahead. This means we're parsing a fieldname. let is_shorthand = !this.look_ahead(1, |t| t == &token::Colon || t == &token::Eq); // Proactively check whether parsing the field will be incorrect. - let is_wrong = this.token.is_ident() - && !this.token.is_reserved_ident() + let is_wrong = this.token.is_non_reserved_ident() && !this.look_ahead(1, |t| { t == &token::Colon || t == &token::Eq diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index c05479feb61..af1d1a1ec66 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -353,6 +353,20 @@ impl<'a> Parser<'a> { if !self.eat_keyword(exp!(Where)) { return Ok((where_clause, None)); } + + if self.eat_noexpect(&token::Colon) { + let colon_span = self.prev_token.span; + self.dcx() + .struct_span_err(colon_span, "unexpected colon after `where`") + .with_span_suggestion_short( + colon_span, + "remove the colon", + "", + Applicability::MachineApplicable, + ) + .emit(); + } + where_clause.has_where_token = true; let where_lo = self.prev_token.span; diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 5088caa80f8..9ed7124a11c 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1552,7 +1552,8 @@ impl<'a> Parser<'a> { }) .map_err(|mut err| { err.span_label(ident.span, "while parsing this enum"); - if self.token == token::Colon { + // Try to recover `enum Foo { ident : Ty }`. + if self.prev_token.is_non_reserved_ident() && self.token == token::Colon { let snapshot = self.create_snapshot_for_diagnostic(); self.bump(); match self.parse_ty() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b2e90251367..cfc0399b0ca 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -685,7 +685,7 @@ impl<'a> Parser<'a> { /// Is the given keyword `kw` followed by a non-reserved identifier? fn is_kw_followed_by_ident(&self, kw: Symbol) -> bool { - self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_ident() && !t.is_reserved_ident()) + self.token.is_keyword(kw) && self.look_ahead(1, |t| t.is_non_reserved_ident()) } #[inline] diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 9bce2fa74ca..1f4049f197f 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -126,7 +126,7 @@ impl<'a> Parser<'a> { /// ``` fn recover_colon_before_qpath_proj(&mut self) -> bool { if !self.check_noexpect(&TokenKind::Colon) - || self.look_ahead(1, |t| !t.is_ident() || t.is_reserved_ident()) + || self.look_ahead(1, |t| !t.is_non_reserved_ident()) { return false; } @@ -260,7 +260,7 @@ impl<'a> Parser<'a> { if self.may_recover() && style == PathStyle::Expr // (!) && self.token == token::Colon - && self.look_ahead(1, |token| token.is_ident() && !token.is_reserved_ident()) + && self.look_ahead(1, |token| token.is_non_reserved_ident()) { // Emit a special error message for `a::b:c` to help users // otherwise, `a: c` might have meant to introduce a new binding @@ -334,9 +334,7 @@ impl<'a> Parser<'a> { self.expect_gt().map_err(|mut err| { // Try to recover a `:` into a `::` if self.token == token::Colon - && self.look_ahead(1, |token| { - token.is_ident() && !token.is_reserved_ident() - }) + && self.look_ahead(1, |token| token.is_non_reserved_ident()) { err.cancel(); err = self.dcx().create_err(PathSingleColon { diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index c37cb0881c3..2fa6520f2a4 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -798,7 +798,7 @@ impl<'a> Parser<'a> { } if self.prev_token.is_reserved_ident() && self.prev_token.is_ident_named(kw::Await) { // Likely `foo.await bar` - } else if !self.prev_token.is_reserved_ident() && self.prev_token.is_ident() { + } else if self.prev_token.is_non_reserved_ident() { // Likely `foo bar` } else if self.prev_token.kind == token::Question { // `foo? bar` diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index e2995daadfe..b1c7b0fcd6c 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -816,9 +816,6 @@ passes_unused_variable_try_prefix = unused variable: `{$name}` .suggestion = if this is intentional, prefix it with an underscore -passes_used_compiler_linker = - `used(compiler)` and `used(linker)` can't be used together - passes_used_static = attribute must be applied to a `static` variable .label = but this is a {$target} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 491b3699f4c..877bb9be289 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -200,6 +200,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::NoMangle(attr_span)) => { self.check_no_mangle(hir_id, *attr_span, span, target) } + Attribute::Parsed(AttributeKind::Used { span: attr_span, .. }) => { + self.check_used(*attr_span, target, span); + } Attribute::Unparsed(attr_item) => { style = Some(attr_item.style); match attr.path().as_slice() { @@ -333,7 +336,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | sym::cfi_encoding // FIXME(cfi_encoding) | sym::pointee // FIXME(derive_coerce_pointee) | sym::omit_gdb_pretty_printer_section // FIXME(omit_gdb_pretty_printer_section) - | sym::used // handled elsewhere to restrict to static items | sym::instruction_set // broken on stable!!! | sym::windows_subsystem // broken on stable!!! | sym::patchable_function_entry // FIXME(patchable_function_entry) @@ -403,7 +405,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } self.check_repr(attrs, span, target, item, hir_id); - self.check_used(attrs, target, span); self.check_rustc_force_inline(hir_id, attrs, span, target); self.check_mix_no_mangle_export(hir_id, attrs); } @@ -2107,44 +2108,13 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_used(&self, attrs: &[Attribute], target: Target, target_span: Span) { - let mut used_linker_span = None; - let mut used_compiler_span = None; - for attr in attrs.iter().filter(|attr| attr.has_name(sym::used)) { - if target != Target::Static { - self.dcx().emit_err(errors::UsedStatic { - attr_span: attr.span(), - span: target_span, - target: target.name(), - }); - } - let inner = attr.meta_item_list(); - match inner.as_deref() { - Some([item]) if item.has_name(sym::linker) => { - if used_linker_span.is_none() { - used_linker_span = Some(attr.span()); - } - } - Some([item]) if item.has_name(sym::compiler) => { - if used_compiler_span.is_none() { - used_compiler_span = Some(attr.span()); - } - } - Some(_) => { - // This error case is handled in rustc_hir_analysis::collect. - } - None => { - // Default case (compiler) when arg isn't defined. - if used_compiler_span.is_none() { - used_compiler_span = Some(attr.span()); - } - } - } - } - if let (Some(linker_span), Some(compiler_span)) = (used_linker_span, used_compiler_span) { - self.tcx - .dcx() - .emit_err(errors::UsedCompilerLinker { spans: vec![linker_span, compiler_span] }); + fn check_used(&self, attr_span: Span, target: Target, target_span: Span) { + if target != Target::Static { + self.dcx().emit_err(errors::UsedStatic { + attr_span, + span: target_span, + target: target.name(), + }); } } diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 3286ccc94f2..f89d925202c 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -642,13 +642,6 @@ pub(crate) struct UsedStatic { } #[derive(Diagnostic)] -#[diag(passes_used_compiler_linker)] -pub(crate) struct UsedCompilerLinker { - #[primary_span] - pub spans: Vec<Span>, -} - -#[derive(Diagnostic)] #[diag(passes_allow_internal_unstable)] pub(crate) struct AllowInternalUnstable { #[primary_span] diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 368944ffd5c..4be7c7ba510 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1876,6 +1876,7 @@ symbols! { rustc_never_returns_null_ptr, rustc_never_type_options, rustc_no_implicit_autorefs, + rustc_no_implicit_bounds, rustc_no_mir_inline, rustc_nonnull_optimization_guaranteed, rustc_nounwind, |
