diff options
| author | bors <bors@rust-lang.org> | 2024-10-12 21:03:01 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2024-10-12 21:03:01 +0000 |
| commit | ef4e8259b5016d85e261587b605028b2ff06c13d (patch) | |
| tree | 9625da8e08773e78c30a43523d12631b452673e0 /compiler | |
| parent | 6b9676b45431a1e531b9c5f7bd289fc36a312749 (diff) | |
| parent | de729170508bda3ef71c7c8778c37b5343ef6dfe (diff) | |
| download | rust-ef4e8259b5016d85e261587b605028b2ff06c13d.tar.gz rust-ef4e8259b5016d85e261587b605028b2ff06c13d.zip | |
Auto merge of #131628 - matthiaskrgr:rollup-imbojxz, r=matthiaskrgr
Rollup of 8 pull requests Successful merges: - #128784 (Check ABI target compatibility for function pointers) - #130965 (make `Step` doc-comments more clear) - #131239 (Don't assume traits used as type are trait objs in 2021 edition) - #131277 (Handle `clippy` cases of `rustc::potential_query_instability` lint) - #131503 (More clearly document Stdin::read_line) - #131567 (Emit an error for unstable attributes that reference already stable features) - #131599 (Shallowly match opaque key in storage) - #131617 (remove const_cow_is_borrowed feature gate) Failed merges: - #131616 (merge const_ipv4 / const_ipv6 feature gate into 'ip' feature gate) r? `@ghost` `@rustbot` modify labels: rollup
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/rustc_data_structures/src/unhash.rs | 1 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/check.rs | 24 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/check/mod.rs | 2 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs | 19 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs | 53 | ||||
| -rw-r--r-- | compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 26 | ||||
| -rw-r--r-- | compiler/rustc_lint_defs/src/builtin.rs | 45 | ||||
| -rw-r--r-- | compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs | 51 | ||||
| -rw-r--r-- | compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs | 34 | ||||
| -rw-r--r-- | compiler/rustc_passes/messages.ftl | 6 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/errors.rs | 11 | ||||
| -rw-r--r-- | compiler/rustc_passes/src/stability.rs | 16 | ||||
| -rw-r--r-- | compiler/rustc_session/src/parse.rs | 2 |
13 files changed, 196 insertions, 94 deletions
diff --git a/compiler/rustc_data_structures/src/unhash.rs b/compiler/rustc_data_structures/src/unhash.rs index 48e21a9dab1..0617ef83aad 100644 --- a/compiler/rustc_data_structures/src/unhash.rs +++ b/compiler/rustc_data_structures/src/unhash.rs @@ -3,6 +3,7 @@ use std::hash::{BuildHasherDefault, Hasher}; pub type UnhashMap<K, V> = HashMap<K, V, BuildHasherDefault<Unhasher>>; pub type UnhashSet<V> = HashSet<V, BuildHasherDefault<Unhasher>>; +pub type UnindexMap<K, V> = indexmap::IndexMap<K, V, BuildHasherDefault<Unhasher>>; /// This no-op hasher expects only a single `write_u64` call. It's intended for /// map keys that already have hash-like quality, like `Fingerprint`. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index dd13c3d8fc1..4429f6346e8 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -8,7 +8,9 @@ use rustc_hir::Node; use rustc_hir::def::{CtorKind, DefKind}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::Obligation; -use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS; +use rustc_lint_defs::builtin::{ + REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS, UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, +}; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; use rustc_middle::span_bug; @@ -52,16 +54,18 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { }); } } +} - // This ABI is only allowed on function pointers - if abi == Abi::CCmseNonSecureCall { - struct_span_code_err!( - tcx.dcx(), - span, - E0781, - "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" - ) - .emit(); +pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Abi) { + match tcx.sess.target.is_abi_supported(abi) { + Some(true) => (), + Some(false) | None => { + tcx.node_span_lint(UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, hir_id, span, |lint| { + lint.primary_message( + "use of calling convention not supported on this target on function pointer", + ); + }); + } } } diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index d3d88919d87..004540b2643 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -73,7 +73,7 @@ pub mod wfcheck; use std::num::NonZero; -pub use check::check_abi; +pub use check::{check_abi, check_abi_fn_ptr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{Diag, ErrorGuaranteed, pluralize, struct_span_code_err}; use rustc_hir::def_id::{DefId, LocalDefId}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs index 5150db7f51b..a562759da11 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/cmse.rs @@ -1,6 +1,5 @@ -use rustc_errors::DiagCtxtHandle; -use rustc_hir as hir; -use rustc_hir::HirId; +use rustc_errors::{DiagCtxtHandle, E0781, struct_span_code_err}; +use rustc_hir::{self as hir, HirId}; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::{self, ParamEnv, TyCtxt}; use rustc_span::Span; @@ -26,7 +25,19 @@ pub(crate) fn validate_cmse_abi<'tcx>( .. }) = hir_node else { - // might happen when this ABI is used incorrectly. That will be handled elsewhere + let span = match tcx.parent_hir_node(hir_id) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::ForeignMod { .. }, span, .. + }) => *span, + _ => tcx.hir().span(hir_id), + }; + struct_span_code_err!( + tcx.dcx(), + span, + E0781, + "the `\"C-cmse-nonsecure-call\"` ABI is only allowed on function pointers" + ) + .emit(); return; }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs index 5607fe873f6..11c0450bfe2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs @@ -1,6 +1,6 @@ use rustc_ast::TraitObjectSyntax; use rustc_errors::codes::*; -use rustc_errors::{Diag, EmissionGuarantee, StashKey}; +use rustc_errors::{Diag, EmissionGuarantee, ErrorGuaranteed, StashKey, Suggestions}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_lint_defs::Applicability; @@ -15,13 +15,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// /// *Bare* trait object types are ones that aren't preceded by the keyword `dyn`. /// In edition 2021 and onward we emit a hard error for them. - pub(super) fn prohibit_or_lint_bare_trait_object_ty(&self, self_ty: &hir::Ty<'_>) { + pub(super) fn prohibit_or_lint_bare_trait_object_ty( + &self, + self_ty: &hir::Ty<'_>, + ) -> Option<ErrorGuaranteed> { let tcx = self.tcx(); let hir::TyKind::TraitObject([poly_trait_ref, ..], _, TraitObjectSyntax::None) = self_ty.kind else { - return; + return None; }; let in_path = match tcx.parent_hir_node(self_ty.hir_id) { @@ -70,8 +73,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } if self_ty.span.edition().at_least_rust_2021() { - let msg = "trait objects must include the `dyn` keyword"; - let label = "add `dyn` keyword before this trait"; + let msg = "expected a type, found a trait"; + let label = "you can add the `dyn` keyword if you want a trait object"; let mut diag = rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg); if self_ty.span.can_be_used_for_suggestions() @@ -83,7 +86,17 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Check if the impl trait that we are considering is an impl of a local trait. self.maybe_suggest_blanket_trait_impl(self_ty, &mut diag); self.maybe_suggest_assoc_ty_bound(self_ty, &mut diag); - diag.stash(self_ty.span, StashKey::TraitMissingMethod); + // In case there is an associate type with the same name + // Add the suggestion to this error + if let Some(mut sugg) = + tcx.dcx().steal_non_err(self_ty.span, StashKey::AssociatedTypeSuggestion) + && let Suggestions::Enabled(ref mut s1) = diag.suggestions + && let Suggestions::Enabled(ref mut s2) = sugg.suggestions + { + s1.append(s2); + sugg.cancel(); + } + diag.stash(self_ty.span, StashKey::TraitMissingMethod) } else { tcx.node_span_lint(BARE_TRAIT_OBJECTS, self_ty.hir_id, self_ty.span, |lint| { lint.primary_message("trait objects without an explicit `dyn` are deprecated"); @@ -96,6 +109,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } self.maybe_suggest_blanket_trait_impl(self_ty, lint); }); + None } } @@ -174,41 +188,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // 1. Independent functions // 2. Functions inside trait blocks // 3. Functions inside impl blocks - let (sig, generics, owner) = match tcx.hir_node_by_def_id(parent_id) { + let (sig, generics) = match tcx.hir_node_by_def_id(parent_id) { hir::Node::Item(hir::Item { kind: hir::ItemKind::Fn(sig, generics, _), .. }) => { - (sig, generics, None) + (sig, generics) } hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Fn(sig, _), generics, - owner_id, .. - }) => (sig, generics, Some(tcx.parent(owner_id.to_def_id()))), + }) => (sig, generics), _ => return false, }; let Ok(trait_name) = tcx.sess.source_map().span_to_snippet(self_ty.span) else { return false; }; let impl_sugg = vec![(self_ty.span.shrink_to_lo(), "impl ".to_string())]; - let mut is_downgradable = true; - // Check if trait object is safe for suggesting dynamic dispatch. let is_dyn_compatible = 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 { - // For recursive traits, don't downgrade the error. (#119652) - is_downgradable = false; - } - tcx.is_dyn_compatible(id) - } + Res::Def(DefKind::Trait, id) => tcx.is_dyn_compatible(id), _ => false, }) } @@ -255,9 +259,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { suggestion, Applicability::MachineApplicable, ); - } else if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); } return true; } @@ -281,10 +282,6 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); if !is_dyn_compatible { diag.note(format!("`{trait_name}` it is dyn-incompatible, so it can't be `dyn`")); - if is_downgradable { - // We'll emit the dyn-compatibility error already, with a structured suggestion. - diag.downgrade_to_delayed_bug(); - } } else { // No ampersand in suggestion if it's borrowed already let (dyn_str, paren_dyn_str) = diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 28a1fc88741..d760acf53bd 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -53,6 +53,7 @@ use rustc_trait_selection::traits::{self, ObligationCtxt}; use tracing::{debug, debug_span, instrument}; use crate::bounds::Bounds; +use crate::check::check_abi_fn_ptr; use crate::errors::{AmbiguousLifetimeBound, BadReturnTypeNotation, WildPatTy}; use crate::hir_ty_lowering::errors::{GenericsArgsErrExtend, prohibit_assoc_item_constraint}; use crate::hir_ty_lowering::generics::{check_generic_arg_count, lower_generic_args}; @@ -2063,13 +2064,18 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) } hir::TyKind::TraitObject(bounds, lifetime, repr) => { - self.prohibit_or_lint_bare_trait_object_ty(hir_ty); - - let repr = match repr { - TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, - TraitObjectSyntax::DynStar => ty::DynStar, - }; - self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + if let Some(guar) = self.prohibit_or_lint_bare_trait_object_ty(hir_ty) { + // Don't continue with type analysis if the `dyn` keyword is missing + // It generates confusing errors, especially if the user meant to use another + // keyword like `impl` + Ty::new_error(tcx, guar) + } else { + let repr = match repr { + TraitObjectSyntax::Dyn | TraitObjectSyntax::None => ty::Dyn, + TraitObjectSyntax::DynStar => ty::DynStar, + }; + self.lower_trait_object_ty(hir_ty.span, hir_ty.hir_id, bounds, lifetime, repr) + } } // If we encounter a fully qualified path with RTN generics, then it must have // *not* gone through `lower_ty_maybe_return_type_notation`, and therefore @@ -2337,6 +2343,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let fn_ty = tcx.mk_fn_sig(input_tys, output_ty, decl.c_variadic, safety, abi); let bare_fn_ty = ty::Binder::bind_with_vars(fn_ty, bound_vars); + if let hir::Node::Ty(hir::Ty { kind: hir::TyKind::BareFn(bare_fn_ty), span, .. }) = + tcx.hir_node(hir_id) + { + check_abi_fn_ptr(tcx, hir_id, *span, bare_fn_ty.abi); + } + // reject function types that violate cmse ABI requirements cmse::validate_cmse_abi(self.tcx(), self.dcx(), hir_id, abi, bare_fn_ty); diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 827791c54be..23dc5214fe2 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -124,6 +124,7 @@ declare_lint_pass! { UNSTABLE_NAME_COLLISIONS, UNSTABLE_SYNTAX_PRE_EXPANSION, UNSUPPORTED_CALLING_CONVENTIONS, + UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, UNUSED_ASSIGNMENTS, UNUSED_ASSOCIATED_TYPE_BOUNDS, UNUSED_ATTRIBUTES, @@ -3840,6 +3841,50 @@ declare_lint! { } declare_lint! { + /// The `unsupported_fn_ptr_calling_conventions` lint is output whenever there is a use of + /// a target dependent calling convention on a target that does not support this calling + /// convention on a function pointer. + /// + /// For example `stdcall` does not make much sense for a x86_64 or, more apparently, powerpc + /// code, because this calling convention was never specified for those targets. + /// + /// ### Example + /// + /// ```rust,ignore (needs specific targets) + /// fn stdcall_ptr(f: extern "stdcall" fn ()) { + /// f() + /// } + /// ``` + /// + /// This will produce: + /// + /// ```text + /// warning: use of calling convention not supported on this target on function pointer + /// --> $DIR/unsupported.rs:34:15 + /// | + /// LL | fn stdcall_ptr(f: extern "stdcall" fn()) { + /// | ^^^^^^^^^^^^^^^^^^^^^^^^ + /// | + /// = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + /// = note: for more information, see issue #130260 <https://github.com/rust-lang/rust/issues/130260> + /// = note: `#[warn(unsupported_fn_ptr_calling_conventions)]` on by default + /// ``` + /// + /// ### Explanation + /// + /// On most of the targets the behaviour of `stdcall` and similar calling conventions is not + /// defined at all, but was previously accepted due to a bug in the implementation of the + /// compiler. + pub UNSUPPORTED_FN_PTR_CALLING_CONVENTIONS, + Warn, + "use of unsupported calling convention for function pointer", + @future_incompatible = FutureIncompatibleInfo { + reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps, + reference: "issue #130260 <https://github.com/rust-lang/rust/issues/130260>", + }; +} + +declare_lint! { /// The `break_with_label_and_loop` lint detects labeled `break` expressions with /// an unlabeled loop as their value expression. /// diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 458edf920ab..daacc669118 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -4,6 +4,7 @@ use derive_where::derive_where; #[cfg(feature = "nightly")] use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable}; use rustc_type_ir::data_structures::{HashMap, HashSet, ensure_sufficient_stack}; +use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_type_ir::inherent::*; use rustc_type_ir::relate::Relate; @@ -18,9 +19,9 @@ use crate::delegate::SolverDelegate; use crate::solve::inspect::{self, ProofTreeBuilder}; use crate::solve::search_graph::SearchGraph; use crate::solve::{ - CanonicalInput, CanonicalResponse, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, - GoalSource, HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, - QueryResult, SolverMode, + CanonicalInput, Certainty, FIXPOINT_STEP_LIMIT, Goal, GoalEvaluationKind, GoalSource, + HasChanged, NestedNormalizationGoals, NoSolution, PredefinedOpaquesData, QueryResult, + SolverMode, }; pub(super) mod canonical; @@ -987,40 +988,22 @@ where // Do something for each opaque/hidden pair defined with `def_id` in the // current inference context. - pub(super) fn unify_existing_opaque_tys( + pub(super) fn probe_existing_opaque_ty( &mut self, - param_env: I::ParamEnv, key: ty::OpaqueTypeKey<I>, - ty: I::Ty, - ) -> Vec<CanonicalResponse<I>> { - // FIXME: Super inefficient to be cloning this... - let opaques = self.delegate.clone_opaque_types_for_query_response(); - - let mut values = vec![]; - for (candidate_key, candidate_ty) in opaques { - if candidate_key.def_id != key.def_id { - continue; - } - values.extend( - self.probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { - result: *result, - }) - .enter(|ecx| { - for (a, b) in std::iter::zip(candidate_key.args.iter(), key.args.iter()) { - ecx.eq(param_env, a, b)?; - } - ecx.eq(param_env, candidate_ty, ty)?; - ecx.add_item_bounds_for_hidden_type( - candidate_key.def_id.into(), - candidate_key.args, - param_env, - candidate_ty, - ); - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }), + ) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> { + let mut matching = + self.delegate.clone_opaque_types_for_query_response().into_iter().filter( + |(candidate_key, _)| { + candidate_key.def_id == key.def_id + && DeepRejectCtxt::relate_rigid_rigid(self.cx()) + .args_may_unify(candidate_key.args, key.args) + }, ); - } - values + let first = matching.next(); + let second = matching.next(); + assert_eq!(second, None); + first } // Try to evaluate a const, or return `None` if the const is too generic. diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs index 6a0703c5313..f8d51f304f3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/opaque_types.rs @@ -7,7 +7,9 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::{self as ty, Interner}; use crate::delegate::SolverDelegate; -use crate::solve::{Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode}; +use crate::solve::{ + Certainty, EvalCtxt, Goal, NoSolution, QueryResult, Reveal, SolverMode, inspect, +}; impl<D, I> EvalCtxt<'_, D> where @@ -52,14 +54,28 @@ where // // If that fails, we insert `expected` as a new hidden type instead of // eagerly emitting an error. - let matches = - self.unify_existing_opaque_tys(goal.param_env, opaque_type_key, expected); - if !matches.is_empty() { - if let Some(response) = self.try_merge_responses(&matches) { - return Ok(response); - } else { - return self.flounder(&matches); - } + let existing = self.probe_existing_opaque_ty(opaque_type_key); + if let Some((candidate_key, candidate_ty)) = existing { + return self + .probe(|result| inspect::ProbeKind::OpaqueTypeStorageLookup { + result: *result, + }) + .enter(|ecx| { + for (a, b) in std::iter::zip( + candidate_key.args.iter(), + opaque_type_key.args.iter(), + ) { + ecx.eq(goal.param_env, a, b)?; + } + ecx.eq(goal.param_env, candidate_ty, expected)?; + ecx.add_item_bounds_for_hidden_type( + candidate_key.def_id.into(), + candidate_key.args, + goal.param_env, + candidate_ty, + ); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }); } // Otherwise, define a new opaque type diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index be76d6cef2b..c11c3850034 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -739,6 +739,12 @@ passes_unrecognized_repr_hint = unrecognized representation hint .help = valid reprs are `Rust` (default), `C`, `align`, `packed`, `transparent`, `simd`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize`, `usize` +passes_unstable_attr_for_already_stable_feature = + can't mark as unstable using an already stable feature + .label = this feature is already stable + .item = the stability attribute annotates this item + .help = consider removing the attribute + passes_unused = unused attribute .suggestion = remove this attribute diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 4f00c90fa3b..f9186d3089a 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1481,6 +1481,17 @@ pub(crate) struct CannotStabilizeDeprecated { } #[derive(Diagnostic)] +#[diag(passes_unstable_attr_for_already_stable_feature)] +pub(crate) struct UnstableAttrForAlreadyStableFeature { + #[primary_span] + #[label] + #[help] + pub span: Span, + #[label(passes_item)] + pub item_sp: Span, +} + +#[derive(Diagnostic)] #[diag(passes_missing_stability_attr)] pub(crate) struct MissingStabilityAttr<'a> { #[primary_span] diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 46b67e930d5..751c87a9fe5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -10,6 +10,7 @@ use rustc_attr::{ }; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; +use rustc_feature::ACCEPTED_FEATURES; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId}; @@ -246,12 +247,27 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> { } } + if let Stability { level: Unstable { .. }, feature } = stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx + .dcx() + .emit_err(errors::UnstableAttrForAlreadyStableFeature { span, item_sp }); + } + } if let Stability { level: Unstable { implied_by: Some(implied_by), .. }, feature } = stab { self.index.implications.insert(implied_by, feature); } + if let Some(ConstStability { level: Unstable { .. }, feature, .. }) = const_stab { + if ACCEPTED_FEATURES.iter().find(|f| f.name == feature).is_some() { + self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature { + span: const_span.unwrap(), // If const_stab contains Some(..), same is true for const_span + item_sp, + }); + } + } if let Some(ConstStability { level: Unstable { implied_by: Some(implied_by), .. }, feature, diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 9781c746520..3d44810e7dd 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -66,7 +66,7 @@ impl GatedSpans { #[derive(Default)] pub struct SymbolGallery { /// All symbols occurred and their first occurrence span. - pub symbols: Lock<FxHashMap<Symbol, Span>>, + pub symbols: Lock<FxIndexMap<Symbol, Span>>, } impl SymbolGallery { |
