From 8eb7f88742d901accf61e47dc3bb11da00137430 Mon Sep 17 00:00:00 2001 From: Sasha Pourcelot Date: Fri, 26 Jun 2026 14:19:58 +0000 Subject: [PATCH] reflection: add the rustc_isolated_const attribute --- compiler/rustc_attr_ir/src/data_structures.rs | 3 + .../rustc_attr_ir/src/encode_cross_crate.rs | 1 + .../src/attributes/rustc_internal.rs | 9 ++ compiler/rustc_attr_parsing/src/context.rs | 1 + .../src/diagnostics/conflict_errors.rs | 1 + .../src/const_eval/eval_queries.rs | 15 +++- compiler/rustc_const_eval/src/lib.rs | 4 +- compiler/rustc_feature/src/builtin_attrs.rs | 1 + .../src/coherence/builtin.rs | 4 +- .../src/hir_ty_lowering/errors.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- compiler/rustc_hir_typeck/src/expr.rs | 11 ++- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 1 + .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_hir_typeck/src/opaque_types.rs | 3 +- compiler/rustc_infer/src/infer/mod.rs | 9 +- .../rustc_infer/src/infer/opaque_types/mod.rs | 3 +- compiler/rustc_middle/src/queries.rs | 8 +- compiler/rustc_middle/src/query/keys.rs | 7 ++ .../src/ty/context/impl_interner.rs | 14 ++- compiler/rustc_middle/src/ty/mod.rs | 13 ++- compiler/rustc_middle/src/ty/trait_def.rs | 44 ++++++---- .../rustc_mir_transform/src/elaborate_drop.rs | 4 +- .../src/solve/assembly/mod.rs | 88 +++++++++++-------- .../src/solve/eval_ctxt/mod.rs | 12 ++- .../src/solve/normalizes_to.rs | 3 +- .../src/solve/project_goals/opaque_types.rs | 7 +- .../src/solve/search_graph.rs | 5 +- .../src/solve/trait_goals.rs | 13 ++- compiler/rustc_passes/src/check_attr.rs | 1 + compiler/rustc_span/src/symbol.rs | 1 + .../error_reporting/infer/note_and_explain.rs | 58 +++++++----- .../src/error_reporting/traits/ambiguity.rs | 12 ++- .../traits/fulfillment_errors.rs | 8 +- .../src/error_reporting/traits/mod.rs | 4 +- .../src/error_reporting/traits/suggestions.rs | 2 +- .../src/solve/delegate.rs | 2 +- .../src/solve/fulfill.rs | 1 + .../src/traits/auto_trait.rs | 4 +- .../src/traits/fulfill.rs | 3 +- .../src/traits/normalize.rs | 10 ++- .../src/traits/project.rs | 4 +- .../src/traits/query/normalize.rs | 5 +- .../src/traits/select/candidate_assembly.rs | 8 +- .../src/traits/select/mod.rs | 9 +- .../src/traits/specialize/mod.rs | 4 +- compiler/rustc_ty_utils/src/instance.rs | 6 +- compiler/rustc_ty_utils/src/layout.rs | 6 +- compiler/rustc_type_ir/src/infer_ctxt.rs | 71 +++++++++++++-- compiler/rustc_type_ir/src/interner.rs | 13 +++ .../rustc_type_ir/src/region_constraint.rs | 1 + compiler/rustc_type_ir/src/relate/combine.rs | 1 + src/librustdoc/clean/blanket_impl.rs | 3 +- .../passes/collect_intra_doc_links.rs | 2 +- .../clippy/clippy_lints/src/dereference.rs | 3 +- .../src/derive/derive_ord_xor_partial_ord.rs | 49 ++++++----- .../src/derive/derived_hash_with_manual_eq.rs | 53 ++++++----- .../src/unconditional_recursion.rs | 3 +- tests/ui/reflection/rustc_isolated_const.rs | 34 +++++++ .../ui/reflection/rustc_isolated_const.stderr | 9 ++ .../reflection/rustc_isolated_const_local.rs | 19 ++++ 61 files changed, 505 insertions(+), 194 deletions(-) create mode 100644 tests/ui/reflection/rustc_isolated_const.rs create mode 100644 tests/ui/reflection/rustc_isolated_const.stderr create mode 100644 tests/ui/reflection/rustc_isolated_const_local.rs diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index d722d515582dc..177f3496fdb61 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1296,6 +1296,9 @@ pub enum AttributeKind { /// Represents `#[rustc_intrinsic_const_stable_indirect]` RustcIntrinsicConstStableIndirect, + /// Represents `#[rustc_isolated_const]` + RustcIsolatedConst, + /// Represents `#[rustc_legacy_const_generics]` RustcLegacyConstGenerics { fn_indexes: ThinVec<(usize, Span)>, diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index 6f05f763f2ada..8231db69c250a 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -155,6 +155,7 @@ impl AttributeKind { RustcInsignificantDtor => Yes, RustcIntrinsic => Yes, RustcIntrinsicConstStableIndirect => No, + RustcIsolatedConst => Yes, RustcLegacyConstGenerics { .. } => Yes, RustcLintOptDenyFieldAccess { .. } => Yes, RustcLintOptTy => Yes, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index bb982184772e7..b0012796418b6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1114,3 +1114,12 @@ impl NoArgsAttributeParser for RustcCanonicalSymbolParser { ); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCanonicalSymbol; } + +pub(crate) struct RustcIsolatedConstParser; + +impl NoArgsAttributeParser for RustcIsolatedConstParser { + const PATH: &[Symbol] = &[sym::rustc_isolated_const]; + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Const)]); + const STABILITY: AttributeStability = unstable!(rustc_attrs); + const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIsolatedConst; +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 22a4a069b75c7..f42fdf434ef29 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -328,6 +328,7 @@ attribute_parsers!( Single>, Single>, Single>, + Single>, Single>, Single>, Single>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f4b2ceb850666..fca73d13248a4 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -1380,6 +1380,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { self.infcx.tcx.for_each_relevant_impl( self.infcx.tcx.lang_items().clone_trait().unwrap(), ty, + ty::IncludeLocalImpls::Yes, |def_id| { if self.infcx.tcx.is_automatically_derived(def_id) { derive_clone = true; 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 5764400148ca7..fb0035c5d63ab 100644 --- a/compiler/rustc_const_eval/src/const_eval/eval_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/eval_queries.rs @@ -45,7 +45,8 @@ fn retry_codegen_mode_with_postanalysis<'tcx, K: TypeVisitable>, V> | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::Reflection - | ty::TypingMode::PostAnalysis => {} + | ty::TypingMode::PostAnalysis + | ty::TypingMode::IsolatedConst => {} } None @@ -357,11 +358,19 @@ pub(crate) fn turn_into_const_value<'tcx>( #[instrument(skip(tcx), level = "debug")] pub fn eval_to_const_value_raw_provider<'tcx>( tcx: TyCtxt<'tcx>, - key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, + mut key: ty::PseudoCanonicalInput<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::EvalToConstValueResult<'tcx> { crate::assert_typing_mode(key.typing_env.typing_mode()); - if let Some((value, _ty)) = tcx.trivial_const(key.value.instance.def_id()) { + let def_id = key.value.instance.def_id(); + + if matches!(tcx.def_kind(def_id), DefKind::Const { .. }) + && rustc_hir::find_attr!(tcx, def_id, RustcIsolatedConst) + { + key.typing_env = ty::TypingEnv::isolated_const(tcx, key.value.instance.def_id()); + } + + if let Some((value, _ty)) = tcx.trivial_const(def_id) { return Ok(value); } diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index a853dd63d3435..41cca98b79ae6 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -29,7 +29,9 @@ use rustc_span::bug; fn assert_typing_mode(typing_mode: ty::TypingMode<'_>) { if cfg!(debug_assertions) { match typing_mode.assert_not_erased() { - ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {} + ty::TypingMode::PostAnalysis + | ty::TypingMode::Codegen + | ty::TypingMode::IsolatedConst => {} // Const eval always happens in PostAnalysis or Codegen mode. See the comment in // `InterpCx::new` for more details. ty::TypingMode::Coherence diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 0f96eb7f158ed..7306d7ea4ae3c 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -334,6 +334,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ sym::rustc_const_stable_indirect, sym::rustc_intrinsic_const_stable_indirect, sym::rustc_allow_const_fn_unstable, + sym::rustc_isolated_const, // ========================================================================== // Internal attributes, Layout related: diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index e9adabc7ca4bb..db33099413f4e 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -14,7 +14,8 @@ use rustc_infer::traits::{Obligation, TraitErrors}; use rustc_middle::ty::adjustment::CoerceUnsizedInfo; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, suggest_constraining_type_params, + self, IncludeLocalImpls, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, + suggest_constraining_type_params, }; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -302,6 +303,7 @@ fn visit_implementation_of_dispatch_from_dyn(checker: &Checker<'_>) -> Result<() tcx.for_each_relevant_impl( tcx.require_lang_item(LangItem::CoerceUnsized, span), source, + IncludeLocalImpls::Yes, |impl_def_id| { res = res.and(tcx.ensure_result().coerce_unsized_info(impl_def_id)); }, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index f2cf4743d76b6..70dc6dc30d172 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -563,7 +563,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { vec!["Self".to_string()] } else { // Find all the types that have an `impl` for the trait. - tcx.all_impls(trait_def_id) + tcx.all_impls(trait_def_id, ty::IncludeLocalImpls::Yes) .map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) .filter(|header| { // Consider only accessible traits 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 6bb1c4d04e065..b6dee398fd603 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1883,7 +1883,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Consider only accessible traits && tcx.visibility(*trait_def_id) .is_accessible_from(self.mod_id(), tcx) - && tcx.all_impls(*trait_def_id) + && tcx.all_impls(*trait_def_id, ty::IncludeLocalImpls::Yes) .any(|impl_def_id| { let header = tcx.impl_trait_header(impl_def_id); let trait_ref = header.trait_ref.instantiate(tcx, infcx.fresh_args_for_item(DUMMY_SP, impl_def_id)).skip_norm_wip(); diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d191fdbdc1ec0..e93f1af134a37 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -3546,9 +3546,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let index_trait_output_def_id = self.tcx.get_diagnostic_item(sym::IndexOutput)?; let mut relevant_impls = vec![]; - self.tcx.for_each_relevant_impl(index_trait_def_id, base_ty, |impl_def_id| { - relevant_impls.push(impl_def_id); - }); + self.tcx.for_each_relevant_impl( + index_trait_def_id, + base_ty, + self.typing_mode().include_local_impls(), + |impl_def_id| { + relevant_impls.push(impl_def_id); + }, + ); let [impl_def_id] = relevant_impls[..] else { // Only report unsatisfied impl predicates if there's one impl return None; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 15383cd8a2a53..4027a38044c56 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -695,6 +695,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty::TypingMode::Typeck { defining_opaque_types_and_generators } => { defining_opaque_types_and_generators } + ty::TypingMode::IsolatedConst => ty::List::empty(), ty::TypingMode::Coherence | ty::TypingMode::Reflection | ty::TypingMode::PostTypeckUntilBorrowck { .. } diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e074ebf01bda4..9de8bc7900731 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -4696,7 +4696,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Check if there's a negative impl of `candidate` for `rcvr_ty` if self .tcx - .all_impls(candidate.def_id) + .all_impls(candidate.def_id, self.typing_mode().include_local_impls()) .map(|imp_did| self.tcx.impl_trait_header(imp_did)) .filter(|header| header.polarity != ty::ImplPolarity::Positive) .any(|header| { diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index c96144d849944..5cc131ad64dad 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -107,7 +107,8 @@ impl<'tcx> FnCtxt<'_, 'tcx> { | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis - | ty::TypingMode::Codegen => { + | ty::TypingMode::Codegen + | ty::TypingMode::IsolatedConst => { bug!() } }; diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 267c36652656d..50e8685aa7032 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -373,7 +373,8 @@ impl<'tcx> Drop for InferCtxt<'tcx> { | TypingMode::PostBorrowck { .. } | TypingMode::Reflection | TypingMode::PostAnalysis - | TypingMode::Codegen => {} + | TypingMode::Codegen + | TypingMode::IsolatedConst => {} // In erased mode, the opaque type storage is always empty TypingMode::ErasedNotCoherence(..) => {} TypingMode::PostTypeckUntilBorrowck { .. } => { @@ -1201,7 +1202,8 @@ impl<'tcx> InferCtxt<'tcx> { | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis - | TypingMode::Codegen => false, + | TypingMode::Codegen + | TypingMode::IsolatedConst => false, } } @@ -1689,7 +1691,8 @@ impl<'tcx> InferCtxt<'tcx> { | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis | ty::TypingMode::Reflection - | ty::TypingMode::Codegen) => mode, + | ty::TypingMode::Codegen + | ty::TypingMode::IsolatedConst) => mode, ty::TypingMode::ErasedNotCoherence(MayBeErased) => unreachable!(), }; ty::TypingEnv::new(param_env, typing_mode) diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 3cca843157b8f..a44ce5b72a852 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -285,7 +285,8 @@ impl<'tcx> InferCtxt<'tcx> { mode @ (ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen - | ty::TypingMode::Reflection) => { + | ty::TypingMode::Reflection + | ty::TypingMode::IsolatedConst) => { bug!("insert hidden type in {mode:?}") } } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 9e1bafa4fd2a2..5b3d68ec77040 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -116,8 +116,8 @@ use crate::ty::layout::ValidityRequirement; use crate::ty::print::PrintTraitRefExt; use crate::ty::util::AlwaysRequiresDrop; use crate::ty::{ - self, CrateInherentImpls, GenericArg, GenericArgsRef, LitToConstInput, PseudoCanonicalInput, - RequiredDepth, SizedTraitKind, Ty, TyCtxt, TyCtxtFeed, + self, CrateInherentImpls, GenericArg, GenericArgsRef, IncludeLocalImpls, LitToConstInput, + PseudoCanonicalInput, RequiredDepth, SizedTraitKind, Ty, TyCtxt, TyCtxtFeed, }; use crate::{mir, thir}; @@ -1643,9 +1643,9 @@ rustc_queries! { } /// Given a trait `trait_id`, return all known `impl` blocks. - query trait_impls_of(trait_id: DefId) -> &'tcx ty::trait_def::TraitImpls { + query trait_impls_of(key: (DefId, IncludeLocalImpls)) -> &'tcx ty::trait_def::TraitImpls { arena_cache - desc { "finding trait impls of `{}`", tcx.def_path_str(trait_id) } + desc { "finding trait impls of `{}`", tcx.def_path_str(key.0) } } query specialization_graph_of(trait_id: DefId) -> Result<&'tcx specialization_graph::Graph, ErrorGuaranteed> { diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index eae4148a30ed4..4c2d18e60080a 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -11,6 +11,7 @@ use rustc_hir::OwnerId; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalModId}; use rustc_span::def_id::ModId; use rustc_span::{DUMMY_SP, Ident, LocalExpnId, Span, Symbol}; +use rustc_type_ir::IncludeLocalImpls; use crate::dep_graph::DepNodeIndex; use crate::infer::canonical::CanonicalQueryInput; @@ -414,6 +415,12 @@ impl<'tcx> QueryKey for (ty::Instance<'tcx>, CollectionMode) { } } +impl QueryKey for (DefId, IncludeLocalImpls) { + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + self.0.default_span(tcx) + } +} + /// Gets a `DefId` associated with a type /// /// Visited set is needed to avoid full iteration over diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 6e838c4454c4c..ebc2f5ad91b41 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -12,8 +12,8 @@ use rustc_span::{DUMMY_SP, Span, Symbol, bug}; use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, SolverTraitLangItem}; use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ - BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, - VisitorResult, search_graph, try_visit, + BoundVar, CollectAndApply, DebruijnIndex, IncludeLocalImpls, Interner, RegionVid, TypeFoldable, + Unnormalized, VisitorResult, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -195,6 +195,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { ty::AliasConstKind::Anon { .. } => false, } } + fn is_isolated_const(self, def_id: LocalDefId) -> bool { + matches!(self.def_kind(def_id), DefKind::Const { .. }) + && rustc_hir::find_attr!(self, def_id, RustcIsolatedConst) + } fn const_of_item( self, alias: ty::AliasConstKind<'tcx>, @@ -526,6 +530,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { fn for_each_relevant_impl( self, trait_ref: ty::TraitRef<'tcx>, + include_local_impls: IncludeLocalImpls, f: impl FnMut(DefId) -> R, ) -> R { let self_ty = trait_ref.args.type_at(0); @@ -533,14 +538,15 @@ impl<'tcx> Interner for TyCtxt<'tcx> { !matches!(self_ty.kind(), ty::Infer(ty::TyVar(_)) | ty::Param(_) | ty::Bound(_, _)), "we should not have them as self ty in the next solver" ); - TyCtxt::for_each_relevant_impl(self, trait_ref.def_id, self_ty, f) + TyCtxt::for_each_relevant_impl(self, trait_ref.def_id, self_ty, include_local_impls, f) } fn for_each_blanket_impl( self, trait_def_id: DefId, + include_local_impls: IncludeLocalImpls, mut f: impl FnMut(DefId) -> R, ) -> R { - let trait_impls = self.trait_impls_of(trait_def_id); + let trait_impls = self.trait_impls_of((trait_def_id, include_local_impls)); for &impl_def_id in trait_impls.blanket_impls() { try_visit!(f(impl_def_id)); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 94345380a544e..017cd1511a28c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1173,6 +1173,13 @@ impl<'tcx> TypingEnv<'tcx> { TypingEnv::new(tcx.param_env_normalized_for_post_analysis(def_id), TypingMode::Codegen) } + pub fn isolated_const(tcx: TyCtxt<'tcx>, def_id: impl IntoQueryKey) -> TypingEnv<'tcx> { + TypingEnv::new( + tcx.param_env_normalized_for_post_analysis(def_id), + TypingMode::IsolatedConst, + ) + } + /// Modify the `typing_mode` to `PostAnalysis` or `Codegen` and eagerly reveal all opaque types /// in the `param_env`. pub fn with_post_analysis_normalized(self, tcx: TyCtxt<'tcx>) -> TypingEnv<'tcx> { @@ -1182,7 +1189,8 @@ impl<'tcx> TypingEnv<'tcx> { | TypingMode::Reflection | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } - | TypingMode::PostBorrowck { .. } => {} + | TypingMode::PostBorrowck { .. } + | TypingMode::IsolatedConst => {} TypingMode::PostAnalysis | TypingMode::Codegen => return self, } @@ -1200,7 +1208,8 @@ impl<'tcx> TypingEnv<'tcx> { | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } - | TypingMode::PostAnalysis => {} + | TypingMode::PostAnalysis + | TypingMode::IsolatedConst => {} TypingMode::Codegen => return self, } diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index fce9af1c465af..3b52107fdfcc9 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::{self as hir, find_attr}; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::{Span, bug}; +pub use rustc_type_ir::IncludeLocalImpls; use tracing::debug; use crate::query::LocalCrate; @@ -139,10 +140,11 @@ impl<'tcx> TyCtxt<'tcx> { self, trait_def_id: DefId, self_ty: Ty<'tcx>, + include_local_impls: IncludeLocalImpls, mut f: impl FnMut(DefId) -> R, ) -> R { let tcx = self; - let trait_impls = tcx.trait_impls_of(trait_def_id); + let trait_impls = tcx.trait_impls_of((trait_def_id, include_local_impls)); let mut consider_impls_for_simplified_type = |simp| { if let Some(impls_for_type) = trait_impls.non_blanket_impls().get(&simp) { for &impl_def_id in impls_for_type { @@ -270,7 +272,7 @@ impl<'tcx> TyCtxt<'tcx> { } #[allow(rustc::usage_of_type_ir_traits)] - self.for_each_blanket_impl(trait_def_id, f) + self.for_each_blanket_impl(trait_def_id, include_local_impls, f) } /// `trait_def_id` MUST BE the `DefId` of a trait. @@ -279,7 +281,7 @@ impl<'tcx> TyCtxt<'tcx> { trait_def_id: DefId, self_ty: Ty<'tcx>, ) -> impl Iterator { - let impls = self.trait_impls_of(trait_def_id); + let impls = self.trait_impls_of((trait_def_id, IncludeLocalImpls::Yes)); if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::InstantiateWithInfer) { @@ -294,15 +296,25 @@ impl<'tcx> TyCtxt<'tcx> { /// Returns an iterator containing all impls for `trait_def_id`. /// /// `trait_def_id` MUST BE the `DefId` of a trait. - pub fn all_impls(self, trait_def_id: DefId) -> impl Iterator { - let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(trait_def_id); + pub fn all_impls( + self, + trait_def_id: DefId, + include_local_impls: IncludeLocalImpls, + ) -> impl Iterator { + let TraitImpls { blanket_impls, non_blanket_impls } = + self.trait_impls_of((trait_def_id, include_local_impls)); blanket_impls.iter().chain(non_blanket_impls.iter().flat_map(|(_, v)| v)).cloned() } } /// Query provider for `trait_impls_of`. -pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> TraitImpls { +pub(super) fn trait_impls_of_provider( + tcx: TyCtxt<'_>, + key: (DefId, IncludeLocalImpls), +) -> TraitImpls { + let (trait_id, include_local_impls) = key; + let mut impls = TraitImpls::default(); // Traits defined in the current crate can't have impls in upstream @@ -325,17 +337,19 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait } } - for &impl_def_id in tcx.local_trait_impls(trait_id) { - let impl_def_id = impl_def_id.to_def_id(); + if matches!(include_local_impls, IncludeLocalImpls::Yes) { + for &impl_def_id in tcx.local_trait_impls(trait_id) { + let impl_def_id = impl_def_id.to_def_id(); - let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip(); + let impl_self_ty = tcx.type_of(impl_def_id).instantiate_identity().skip_norm_wip(); - if let Some(simplified_self_ty) = - fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer) - { - impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); - } else { - impls.blanket_impls.push(impl_def_id); + if let Some(simplified_self_ty) = + fast_reject::simplify_type(tcx, impl_self_ty, TreatParams::InstantiateWithInfer) + { + impls.non_blanket_impls.entry(simplified_self_ty).or_default().push(impl_def_id); + } else { + impls.blanket_impls.push(impl_def_id); + } } } diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index d9d9914d02bd4..72fcebaa1a9f8 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -783,7 +783,9 @@ where let tcx = self.tcx(); match self.elaborator.typing_env().typing_mode().assert_not_erased() { - ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => {} + ty::TypingMode::PostAnalysis + | ty::TypingMode::Codegen + | ty::TypingMode::IsolatedConst => {} ty::TypingMode::Coherence | ty::TypingMode::Reflection | ty::TypingMode::Typeck { .. } diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 485568850bee0..9292a92b40b91 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -14,9 +14,9 @@ use rustc_type_ir::solve::{ RerunNonErased, RerunReason, RerunResultExt, SizedTraitKind, StalledOnCoroutines, }; use rustc_type_ir::{ - self as ty, AliasTy, Interner, MayBeErased, Region, TypeFlags, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, - TypingMode, Unnormalized, Upcast, elaborate, + self as ty, AliasTy, IncludeLocalImpls, Interner, MayBeErased, Region, TypeFlags, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, + TypeVisitor, TypingMode, Unnormalized, Upcast, elaborate, }; use tracing::{debug, instrument}; @@ -537,7 +537,8 @@ where | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(MayBeErased) => !candidates.iter().any(|c| { + | TypingMode::ErasedNotCoherence(MayBeErased) + | TypingMode::IsolatedConst => !candidates.iter().any(|c| { matches!( c.source, CandidateSource::ParamEnv(ParamEnvSource::NonGlobal) @@ -591,18 +592,22 @@ where ) -> Result<(), RerunNonErased> { let cx = self.cx(); let goal_trait_ref = goal.predicate.trait_ref(cx); - cx.for_each_relevant_impl(goal_trait_ref, |impl_def_id| -> Result<_, _> { - match G::consider_impl_candidate(self, goal, goal_trait_ref, impl_def_id, |ecx| { - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) - .map_err_to_rerun()? - { - Ok(candidate) => candidates.push(candidate), - Err(NoSolution) => {} - } + cx.for_each_relevant_impl( + goal.predicate.trait_ref(cx), + self.typing_mode().include_local_impls(), + |impl_def_id| -> Result<_, _> { + match G::consider_impl_candidate(self, goal, goal_trait_ref, impl_def_id, |ecx| { + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) + .map_err_to_rerun()? + { + Ok(candidate) => candidates.push(candidate), + Err(NoSolution) => {} + } - Ok(()) - }) + Ok(()) + }, + ) } #[instrument(level = "trace", skip_all)] @@ -1132,6 +1137,7 @@ where | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Reflection + | TypingMode::IsolatedConst | TypingMode::Codegen => vec![], TypingMode::ErasedNotCoherence(MayBeErased) => { self.opaque_accesses @@ -1207,28 +1213,40 @@ where let cx = self.cx(); let goal_trait_ref = goal.predicate.trait_ref(cx); - cx.for_each_blanket_impl(goal.predicate.trait_def_id(cx), |impl_def_id| { - match G::consider_impl_candidate(self, goal, goal_trait_ref, impl_def_id, |ecx| { - if ecx.shallow_resolve(self_ty).is_ty_var() { - // We force the certainty of impl candidates to be `Maybe`. - ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) - } else { - // We don't want to use impls if they constrain the opaque. - // - // FIXME(trait-system-refactor-initiative#229): This isn't - // perfect yet as it still allows us to incorrectly constrain - // other inference variables. - Err(NoSolution.into()) + cx.for_each_blanket_impl( + goal.predicate.trait_def_id(cx), + IncludeLocalImpls::Yes, + |impl_def_id| { + match G::consider_impl_candidate( + self, + goal, + goal_trait_ref, + impl_def_id, + |ecx| { + if ecx.shallow_resolve(self_ty).is_ty_var() { + // We force the certainty of impl candidates to be `Maybe`. + ecx.evaluate_added_goals_and_make_canonical_response( + Certainty::AMBIGUOUS, + ) + } else { + // We don't want to use impls if they constrain the opaque. + // + // FIXME(trait-system-refactor-initiative#229): This isn't + // perfect yet as it still allows us to incorrectly constrain + // other inference variables. + Err(NoSolution.into()) + } + }, + ) + .map_err_to_rerun()? + { + Ok(candidate) => candidates.push(candidate), + Err(NoSolution) => {} } - }) - .map_err_to_rerun()? - { - Ok(candidate) => candidates.push(candidate), - Err(NoSolution) => {} - } - Ok(()) - })?; + Ok(()) + }, + )?; } if candidates.is_empty() { 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 3a4875c1d0951..8872c00afca2a 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 @@ -681,6 +681,7 @@ where | TypingMode::PostBorrowck { .. } | TypingMode::Codegen | TypingMode::PostAnalysis + | TypingMode::IsolatedConst | TypingMode::ErasedNotCoherence(_) => { let mut skip = false; if opaque_types.iter().any(|(_, ty)| ty.is_ty_var()) @@ -1866,7 +1867,10 @@ fn should_rerun_after_erased_canonicalization( // ============================= ( RerunCondition::OpaqueInStorage(..), - TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::Reflection, + TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::Reflection + | TypingMode::IsolatedConst, ) => RerunDecision::Yes, ( RerunCondition::OpaqueInStorage(defids), @@ -1884,12 +1888,16 @@ fn should_rerun_after_erased_canonicalization( | TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::Reflection + | TypingMode::IsolatedConst | TypingMode::PostTypeckUntilBorrowck { .. }, ) => RerunDecision::No, // ============================= ( RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(_), - TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::Reflection, + TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::Reflection + | TypingMode::IsolatedConst, ) => RerunDecision::Yes, ( RerunCondition::OpaqueInStorageOrAnyOpaqueHasInferAsHidden(defids), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index cb878f2c54878..17294aa328064 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -352,7 +352,8 @@ where | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::PostAnalysis | ty::TypingMode::Reflection - | ty::TypingMode::Codegen => { + | ty::TypingMode::Codegen + | ty::TypingMode::IsolatedConst => { ecx.instantiate_normalizes_to_as_rigid(goal)?; return ecx.evaluate_added_goals_and_make_canonical_response( Certainty::Yes, diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs index 2f56056449779..05d4bf8d9108a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs @@ -106,6 +106,7 @@ where TypingMode::Coherence | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis + | TypingMode::IsolatedConst | TypingMode::Reflection | TypingMode::Codegen => unreachable!(), } @@ -150,8 +151,12 @@ where self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) } + // FIXME(try_as_dyn): probably want to treat opaques opaquely and rigid - TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::Reflection + | TypingMode::IsolatedConst + | TypingMode::PostAnalysis + | TypingMode::Codegen => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args); let actual = self.normalize(GoalSource::Misc, goal.param_env, actual)?; diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index e147a139a65e1..aa5f86e5d23e7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -71,9 +71,8 @@ where | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(MayBeErased) => { - (Err(NoSolution), AccessedOpaques::default()) - } + | TypingMode::ErasedNotCoherence(MayBeErased) + | TypingMode::IsolatedConst => (Err(NoSolution), AccessedOpaques::default()), }, } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 79db6ba43e228..ecc3489724530 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1300,9 +1300,13 @@ where let self_ty = goal.predicate.self_ty(); let check_impls = || { let mut disqualifying_impl = None; - self.cx().for_each_relevant_impl(goal.predicate.trait_ref, |impl_def_id| { - disqualifying_impl = Some(impl_def_id); - }); + self.cx().for_each_relevant_impl( + goal.predicate.trait_ref, + self.typing_mode().include_local_impls(), + |impl_def_id| { + disqualifying_impl = Some(impl_def_id); + }, + ); if let Some(def_id) = disqualifying_impl { trace!(?def_id, ?goal, "disqualified auto-trait implementation"); // No need to actually consider the candidate here, @@ -1663,7 +1667,8 @@ where | TypingMode::Reflection | TypingMode::Codegen | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } - | TypingMode::PostBorrowck { defined_opaque_types: _ } => {} + | TypingMode::PostBorrowck { defined_opaque_types: _ } + | TypingMode::IsolatedConst => {} } } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f6bd780802401..61e5435899990 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -361,6 +361,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcInsignificantDtor => (), AttributeKind::RustcIntrinsic => (), AttributeKind::RustcIntrinsicConstStableIndirect => (), + AttributeKind::RustcIsolatedConst => (), AttributeKind::RustcLintOptDenyFieldAccess { .. } => (), AttributeKind::RustcLintOptTy => (), AttributeKind::RustcLintQueryInstability => (), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 098b6595f166e..b2f5431417834 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1851,6 +1851,7 @@ symbols! { rustc_insignificant_dtor, rustc_intrinsic, rustc_intrinsic_const_stable_indirect, + rustc_isolated_const, rustc_legacy_const_generics, rustc_lint_opt_deny_field_access, rustc_lint_opt_ty, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index de829a5c6ae1a..7618b5e7367c9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -401,13 +401,18 @@ impl Trait for X { } (ty::Dynamic(t, _), _) if let Some(def_id) = t.principal_def_id() => { let mut has_matching_impl = false; - tcx.for_each_relevant_impl(def_id, values.found, |did| { - if DeepRejectCtxt::relate_rigid_infer(tcx) - .types_may_unify(values.found, tcx.type_of(did).skip_binder()) - { - has_matching_impl = true; - } - }); + tcx.for_each_relevant_impl( + def_id, + values.found, + self.typing_mode_raw().include_local_impls(), + |did| { + if DeepRejectCtxt::relate_rigid_infer(tcx) + .types_may_unify(values.found, tcx.type_of(did).skip_binder()) + { + has_matching_impl = true; + } + }, + ); if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( @@ -420,13 +425,19 @@ impl Trait for X { } (_, ty::Dynamic(t, _)) if let Some(def_id) = t.principal_def_id() => { let mut has_matching_impl = false; - tcx.for_each_relevant_impl(def_id, values.expected, |did| { - if DeepRejectCtxt::relate_rigid_infer(tcx) - .types_may_unify(values.expected, tcx.type_of(did).skip_binder()) - { - has_matching_impl = true; - } - }); + tcx.for_each_relevant_impl( + def_id, + values.expected, + self.typing_mode_raw().include_local_impls(), + |did| { + if DeepRejectCtxt::relate_rigid_infer(tcx).types_may_unify( + values.expected, + tcx.type_of(did).skip_binder(), + ) { + has_matching_impl = true; + } + }, + ); if has_matching_impl { let trait_name = tcx.item_name(def_id); diag.help(format!( @@ -528,9 +539,12 @@ impl Trait for X { } let def_id = trait_predicate.def_id(); let mut impl_def_ids = vec![]; - tcx.for_each_relevant_impl(def_id, expected, |did| { - impl_def_ids.push(did) - }); + tcx.for_each_relevant_impl( + def_id, + expected, + self.typing_mode_raw().include_local_impls(), + |did| impl_def_ids.push(did), + ); if let [_] = &impl_def_ids[..] { let trait_name = tcx.item_name(def_id); diag.multipart_suggestion( @@ -574,10 +588,12 @@ impl Trait for X { && let ty::Dynamic(t, _) = boxed_ty.kind() && let Some(def_id) = t.principal_def_id() && let mut impl_def_ids = vec![] - && let _ = - tcx.for_each_relevant_impl(def_id, values.expected, |did| { - impl_def_ids.push(did) - }) + && let _ = tcx.for_each_relevant_impl( + def_id, + values.expected, + self.typing_mode_raw().include_local_impls(), + |did| impl_def_ids.push(did), + ) && let [_] = &impl_def_ids[..] => { // We have divergent if/else arms where the expected value is a type that diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 62ac12a8edd24..cd07a28aed1a6 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -12,6 +12,7 @@ use rustc_infer::traits::{ Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation, }; use rustc_middle::ty::print::PrintPolyTraitClauseExt; +use rustc_middle::ty::trait_def::IncludeLocalImpls; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _, Unnormalized}; use rustc_session::diagnostics::feature_err_unstable_feature_bound; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; @@ -137,6 +138,8 @@ pub fn compute_applicable_impls_for_diagnostics<'tcx>( tcx.for_each_relevant_impl( obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), + // FIXME(isolated_const): may cycle error in the diagnostic case + IncludeLocalImpls::Yes, |impl_def_id| { if infcx.probe(|_| impl_may_apply(impl_def_id)) { ambiguities.push(CandidateSource::DefId(impl_def_id)) @@ -289,7 +292,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut err = if let Some(term) = term { let candidates: Vec<_> = self .tcx - .all_impls(trait_pred.def_id()) + .all_impls( + trait_pred.def_id(), + self.typing_mode_raw().include_local_impls(), + ) .filter_map(|def_id| { let imp = self.tcx.impl_trait_header(def_id); if imp.polarity != ty::ImplPolarity::Positive @@ -446,7 +452,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { err.span_label(span, format!("cannot {verb} associated {noun} of trait")); - let trait_impls = self.tcx.trait_impls_of(data.trait_ref.def_id); + let trait_impls = self + .tcx + .trait_impls_of((data.trait_ref.def_id, IncludeLocalImpls::Yes)); if let Some(&impl_def_id) = trait_impls.non_blanket_impls().values().flatten().next() diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 5090e36af9d8a..d3b83831c0fa8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -29,6 +29,7 @@ use rustc_middle::ty::print::{ PrintPolyTraitClauseExt, PrintPolyTraitRefExt as _, PrintTraitClauseExt as _, PrintTraitRefExt as _, with_forced_trimmed_paths, }; +use rustc_middle::ty::trait_def::IncludeLocalImpls; use rustc_middle::ty::{ self, GenericArgKind, GenericParamDefKind, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, Unnormalized, Upcast, @@ -2123,7 +2124,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> Vec> { let mut candidates: Vec<_> = self .tcx - .all_impls(trait_pred.def_id()) + .all_impls(trait_pred.def_id(), self.typing_mode_raw().include_local_impls()) .filter_map(|def_id| { let imp = self.tcx.impl_trait_header(def_id); if imp.polarity != ty::ImplPolarity::Positive @@ -2161,7 +2162,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let alternative_candidates = |def_id: DefId| { let mut impl_candidates: Vec<_> = self .tcx - .all_impls(def_id) + .all_impls(def_id, self.typing_mode_raw().include_local_impls()) // ignore `do_not_recommend` items .filter(|def_id| !self.tcx.do_not_recommend_impl(*def_id)) // Ignore automatically derived impls and `!Trait` impls. @@ -2816,6 +2817,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.tcx.for_each_relevant_impl( trait_def_id, trait_pred.skip_binder().self_ty(), + self.typing_mode_raw().include_local_impls(), |impl_def_id| { let impl_trait_header = self.tcx.impl_trait_header(impl_def_id); trait_impls @@ -3460,7 +3462,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation.cause.body_def_id, ); } else if trait_def_id.is_local() - && self.tcx.trait_impls_of(trait_def_id).is_empty() + && self.tcx.trait_impls_of((trait_def_id, IncludeLocalImpls::Yes)).is_empty() && !self.tcx.trait_is_auto(trait_def_id) && !self.tcx.trait_is_alias(trait_def_id) && trait_predicate.polarity() == ty::ClausePolarity::Positive diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index c120df4e2c3ef..2353152f2e05b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -21,6 +21,7 @@ use rustc_infer::traits::{ PredicateObligation, SelectionError, }; use rustc_middle::ty::print::{PrintTraitRefExt as _, with_no_trimmed_paths}; +use rustc_middle::ty::trait_def::IncludeLocalImpls; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_next_trait_solver::solve::TyOrConstInferVar; use rustc_span::{DesugaringKind, ErrorGuaranteed, ExpnKind, Span}; @@ -778,7 +779,8 @@ fn attempt_dyn_to_enum_suggestion( trait_str: &str, err: &mut Diag<'_>, ) { - let impls_of = tcx.trait_impls_of(trait_def_id); + // FIXME(isolated_const): may cycle error in the diagnostic case + let impls_of = tcx.trait_impls_of((trait_def_id, IncludeLocalImpls::Yes)); if !impls_of.blanket_impls().is_empty() { return; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 5e9288fc7a592..86b1fc1adecc3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4044,7 +4044,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { with_no_trimmed_paths!(tcx.def_path_str(def_id)), )); let mut types = tcx - .all_impls(def_id) + .all_impls(def_id, self.typing_mode_raw().include_local_impls()) .map(|t| { with_no_trimmed_paths!(format!( " {}", diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index c67a4bdd329b0..b087859c16b7c 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -459,7 +459,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::Reflection | TypingMode::PostBorrowck { .. } => false, - TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::IsolatedConst => { let poly_trait_ref = self.deeply_resolve_ignoring_regions(goal_trait_ref); !poly_trait_ref.still_further_specializable() } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 7d3c0a4a6c1f1..bac24c96018e5 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -333,6 +333,7 @@ where | TypingMode::PostBorrowck { defined_opaque_types: _ } | TypingMode::Reflection | TypingMode::PostAnalysis + | TypingMode::IsolatedConst | TypingMode::Codegen => return Default::default(), }; diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 71dee3de72cb8..6fec55c059c78 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::{FxIndexMap, FxIndexSet, IndexEntry}; use rustc_data_structures::unord::UnordSet; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_infer::infer::DefineOpaqueTypes; -use rustc_middle::ty::{Region, RegionVid}; +use rustc_middle::ty::{IncludeLocalImpls, Region, RegionVid}; use rustc_span::DUMMY_SP; use tracing::debug; @@ -212,7 +212,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { }; let mut disqualifying_impl = None; - tcx.for_each_relevant_impl(trait_did, ty, |impl_def_id| { + tcx.for_each_relevant_impl(trait_did, ty, IncludeLocalImpls::Yes, |impl_def_id| { disqualifying_impl = Some(impl_def_id); }); if let Some(impl_def_id) = disqualifying_impl { diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index f5a4ec9ae0494..9876a32c5cf0f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -180,7 +180,8 @@ where | TypingMode::PostBorrowck { defined_opaque_types: _ } | TypingMode::Reflection | TypingMode::PostAnalysis - | TypingMode::Codegen => return Default::default(), + | TypingMode::Codegen + | TypingMode::IsolatedConst => return Default::default(), }; if stalled_coroutines.is_empty() { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index c220b35dd5f7d..ee9154bbc5196 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -143,7 +143,10 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), - TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => {} + TypingMode::Reflection + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::IsolatedConst => {} } value.has_type_flags(flags) @@ -430,7 +433,10 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.super_fold_with(self), - TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::Reflection + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::IsolatedConst => { let recursion_limit = self.cx().recursion_limit(); if !recursion_limit.value_within_limit(self.depth) { self.selcx.infcx.err_ctxt().report_overflow_error( diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c1f4e74119744..ccfb3d68c76c3 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1046,7 +1046,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( ); false } - TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::IsolatedConst => { // NOTE(eddyb) inference variables can resolve to parameters, so // assume `poly_trait_ref` isn't monomorphic, if it contains any. let poly_trait_ref = diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 782697782f94c..2bdffe32c8191 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -236,7 +236,10 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.try_super_fold_with(self)?, - TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { + TypingMode::Reflection + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::IsolatedConst => { let args = data.args.try_fold_with(self)?; let recursion_limit = self.cx().recursion_limit(); 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 8509be2fb6dec..4231448df36e1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -610,6 +610,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { self.tcx().for_each_relevant_impl( obligation.predicate.def_id(), obligation.predicate.skip_binder().trait_ref.self_ty(), + self.typing_mode().include_local_impls(), |impl_def_id| { // Before we create the generic parameters and everything, first // consider a "quick reject". This avoids creating more types @@ -760,7 +761,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // which may define impls for that type is either the crate defining the type // or the trait. This should be guaranteed by the orphan check. let mut has_impl = false; - self.tcx().for_each_relevant_impl(def_id, self_ty, |_| has_impl = true); + self.tcx().for_each_relevant_impl( + def_id, + self_ty, + self.typing_mode().include_local_impls(), + |_| has_impl = true, + ); if !has_impl { candidates.vec.push(AutoImplCandidate) } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f8619fcd120a2..ea93c81ca7da1 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1441,7 +1441,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis - | TypingMode::Codegen => return Ok(()), + | TypingMode::Codegen + | TypingMode::IsolatedConst => return Ok(()), } debug!("is_knowable()"); @@ -1501,7 +1502,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // FIXME(#132279): This is still incorrect as we treat opaque types // and default associated items differently between these two modes. - TypingMode::PostAnalysis | TypingMode::Codegen => true, + TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::IsolatedConst => true, } } @@ -2535,6 +2536,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TypingMode::Codegen | TypingMode::ErasedNotCoherence(_) | TypingMode::Reflection + | TypingMode::IsolatedConst | TypingMode::PostAnalysis => {} } @@ -2881,7 +2883,8 @@ impl<'tcx> SelectionContext<'_, 'tcx> { | TypingMode::Reflection | TypingMode::Codegen | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } - | TypingMode::PostBorrowck { defined_opaque_types: _ } => false, + | TypingMode::PostBorrowck { defined_opaque_types: _ } + | TypingMode::IsolatedConst => false, } } } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 987e2af81984b..a48541f67ea78 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -22,7 +22,7 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::fast_reject::{self, TreatParams}; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ - self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, + self, GenericArgsRef, IncludeLocalImpls, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, bug, sym}; use specialization_graph::GraphExt; @@ -397,7 +397,7 @@ pub(super) fn specialization_graph_provider( // `None`, is compared against every child, so then all buckets are kept; // pruning them would change error recovery (see impl-unpin.rs, `tait` // revision). - let all_impls = tcx.trait_impls_of(trait_id); + let all_impls = tcx.trait_impls_of((trait_id, IncludeLocalImpls::Yes)); let mut trait_impls: Vec = all_impls.blanket_impls().to_vec(); let has_local_blanket_impl = all_impls.blanket_impls().iter().any(|impl_def_id| impl_def_id.is_local()); diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index f0f0a66a8eeba..e64f5cfbcef23 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -166,9 +166,9 @@ fn resolve_associated_item<'tcx>( | ty::TypingMode::PostTypeckUntilBorrowck { .. } | ty::TypingMode::Reflection | ty::TypingMode::PostBorrowck { .. } => false, - ty::TypingMode::PostAnalysis | ty::TypingMode::Codegen => { - !trait_ref.still_further_specializable() - } + ty::TypingMode::PostAnalysis + | ty::TypingMode::Codegen + | ty::TypingMode::IsolatedConst => !trait_ref.still_further_specializable(), } }; if !eligible { diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index dee4b785e418d..e7a284441603c 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -92,7 +92,8 @@ fn layout_of<'tcx>( | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::Reflection | ty::TypingMode::ErasedNotCoherence(_) - | ty::TypingMode::PostAnalysis => {} + | ty::TypingMode::PostAnalysis + | ty::TypingMode::IsolatedConst => {} } let cx = LayoutCx::new(tcx, typing_env); @@ -558,7 +559,8 @@ fn layout_of_uncached<'tcx>( | ty::TypingMode::PostBorrowck { .. } | ty::TypingMode::Reflection | ty::TypingMode::ErasedNotCoherence(_) - | ty::TypingMode::PostAnalysis => { + | ty::TypingMode::PostAnalysis + | ty::TypingMode::IsolatedConst => { return Err(error(cx, LayoutError::TooGeneric(ty))); } } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index a86a07edb902f..4dcd692ad55a3 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -11,8 +11,8 @@ use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; use crate::solve::{TyOrConstInferVar, VisibleForLeakCheck}; use crate::{ - self as ty, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder, - TypeSuperFoldable, TypeVisitableExt, + self as ty, IncludeLocalImpls, Interner, PredicateProxy, Region, TyVid, TypeFoldable, + TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; mod private { @@ -143,6 +143,9 @@ pub enum TypingMode { /// layouts. Codegen, + /// During isolated const, forbid referring to traits defined in the current trait. + IsolatedConst, + /// The typing modes above (except coherence) only differ in how they handle /// /// - Generators @@ -203,6 +206,7 @@ impl PartialEq for TypingModeEqWrapper { TypingMode::ErasedNotCoherence(MayBeErased), TypingMode::ErasedNotCoherence(MayBeErased), ) => true, + (TypingMode::IsolatedConst, TypingMode::IsolatedConst) => true, ( TypingMode::Coherence | TypingMode::Reflection @@ -211,7 +215,8 @@ impl PartialEq for TypingModeEqWrapper { | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(MayBeErased), + | TypingMode::ErasedNotCoherence(MayBeErased) + | TypingMode::IsolatedConst, _, ) => false, } @@ -235,7 +240,8 @@ impl TypingMode { | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(_) => false, + | TypingMode::ErasedNotCoherence(_) + | TypingMode::IsolatedConst => false, } } @@ -253,7 +259,8 @@ impl TypingMode { | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(_) => false, + | TypingMode::ErasedNotCoherence(_) + | TypingMode::IsolatedConst => false, } } @@ -271,7 +278,8 @@ impl TypingMode { | TypingMode::Reflection | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis - | TypingMode::Codegen => false, + | TypingMode::Codegen + | TypingMode::IsolatedConst => false, } } } @@ -296,11 +304,28 @@ impl TypingMode { TypingMode::PostAnalysis => TypingMode::PostAnalysis, TypingMode::Codegen => TypingMode::Codegen, TypingMode::Reflection => TypingMode::Reflection, + TypingMode::IsolatedConst => TypingMode::IsolatedConst, TypingMode::ErasedNotCoherence(MayBeErased) => panic!( "Called `assert_not_erased` from a place that can be called by the trait solver in `TypingMode::ErasedNotCoherence`. `TypingMode` is `ErasedNotCoherence` in a place where that should be impossible" ), } } + + /// For isolated consts, do not look at local impls. + /// Convenience helper to go from TypingMode::IsolatedConst to IncludeLocalImpls::No. + pub fn include_local_impls(self) -> IncludeLocalImpls { + match self { + TypingMode::Coherence + | TypingMode::Typeck { defining_opaque_types_and_generators: _ } + | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } + | TypingMode::PostBorrowck { defined_opaque_types: _ } + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::Reflection + | TypingMode::ErasedNotCoherence(_) => IncludeLocalImpls::Yes, + TypingMode::IsolatedConst => IncludeLocalImpls::No, + } + } } impl TypingMode { @@ -310,9 +335,13 @@ impl TypingMode { } pub fn typeck_for_body(cx: I, body_def_id: I::LocalDefId) -> TypingMode { - TypingMode::Typeck { - defining_opaque_types_and_generators: cx - .opaque_types_and_coroutines_defined_by(body_def_id), + if cx.is_isolated_const(body_def_id) { + TypingMode::IsolatedConst + } else { + TypingMode::Typeck { + defining_opaque_types_and_generators: cx + .opaque_types_and_coroutines_defined_by(body_def_id), + } } } @@ -328,6 +357,9 @@ impl TypingMode { } pub fn borrowck(cx: I, body_def_id: I::LocalDefId) -> TypingMode { + if cx.is_isolated_const(body_def_id) { + return TypingMode::IsolatedConst; + } let defining_opaque_types = cx.opaque_types_defined_by(body_def_id); if defining_opaque_types.is_empty() { TypingMode::non_body_analysis() @@ -337,6 +369,9 @@ impl TypingMode { } pub fn post_borrowck_analysis(cx: I, body_def_id: I::LocalDefId) -> TypingMode { + if cx.is_isolated_const(body_def_id) { + return TypingMode::IsolatedConst; + } let defined_opaque_types = cx.opaque_types_defined_by(body_def_id); if defined_opaque_types.is_empty() { TypingMode::non_body_analysis() @@ -344,6 +379,22 @@ impl TypingMode { TypingMode::PostBorrowck { defined_opaque_types } } } + + /// For isolated consts, do not look at local impls. + /// Convenience helper to go from TypingMode::IsolatedConst to IncludeLocalImpls::No. + pub fn include_local_impls(self) -> IncludeLocalImpls { + match self { + TypingMode::Coherence + | TypingMode::Typeck { defining_opaque_types_and_generators: _ } + | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } + | TypingMode::PostBorrowck { defined_opaque_types: _ } + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::Reflection + | TypingMode::ErasedNotCoherence(_) => IncludeLocalImpls::Yes, + TypingMode::IsolatedConst => IncludeLocalImpls::No, + } + } } impl From> for TypingMode { @@ -362,6 +413,7 @@ impl From> for TypingMode TypingMode::PostAnalysis, TypingMode::Codegen => TypingMode::Codegen, TypingMode::Reflection => TypingMode::Reflection, + TypingMode::IsolatedConst => TypingMode::IsolatedConst, } } } @@ -630,6 +682,7 @@ where | TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::Reflection + | TypingMode::IsolatedConst | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis => infcx.cx().features().feature_bound_holds_in_crate(symbol), TypingMode::Codegen => true, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0a11a82c99e76..d0042e08d6980 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -8,6 +8,8 @@ use rustc_ast_ir::visit::VisitorResult; #[cfg(feature = "nightly")] use rustc_data_structures::stable_hash::StableHash; use rustc_index::bit_set::DenseBitSet; +#[cfg(feature = "nightly")] +use rustc_macros::StableHash; use crate::fold::TypeFoldable; use crate::inherent::*; @@ -25,6 +27,14 @@ use crate::{ Region, RegionKind, RegionVid, TraitRef, search_graph, }; +// FIXME(scrabsha): find an appropriate place to move this. +#[derive(Clone, Hash, Eq, PartialEq, Copy, Debug)] +#[cfg_attr(feature = "nightly", derive(StableHash))] +pub enum IncludeLocalImpls { + Yes, + No, +} + /// The central trait in the shared abstraction layer, specifying all implementation-specific /// details for rustc and rust-analyzer. /// @@ -282,6 +292,7 @@ pub trait Interner: def_id: Self::LocalOpaqueTyId, ) -> ty::EarlyBinder; fn is_direct_const(self, alias: ty::AliasConstKind) -> bool; + fn is_isolated_const(self, def_id: Self::LocalDefId) -> bool; fn const_of_item( self, alias: ty::AliasConstKind, @@ -462,11 +473,13 @@ pub trait Interner: fn for_each_relevant_impl( self, trait_ref: TraitRef, + include_local_impls: IncludeLocalImpls, f: impl FnMut(Self::ImplId) -> R, ) -> R; fn for_each_blanket_impl( self, trait_def_id: Self::TraitId, + include_local_impls: IncludeLocalImpls, f: impl FnMut(Self::ImplId) -> R, ) -> R; diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 0dd79d8d0449e..0f85c098624ae 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -1042,6 +1042,7 @@ fn rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handl | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis + | TypingMode::IsolatedConst | TypingMode::Codegen => (), }; diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 7b747141889fe..9a48db3ceb11b 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -132,6 +132,7 @@ where | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } | TypingMode::PostAnalysis + | TypingMode::IsolatedConst | TypingMode::Codegen => structurally_relate_tys(relation, a, b), } } diff --git a/src/librustdoc/clean/blanket_impl.rs b/src/librustdoc/clean/blanket_impl.rs index 7b4af6ac0dbcb..df909cadc81ce 100644 --- a/src/librustdoc/clean/blanket_impl.rs +++ b/src/librustdoc/clean/blanket_impl.rs @@ -2,6 +2,7 @@ use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; use rustc_infer::infer::{DefineOpaqueTypes, InferOk, TyCtxtInferExt}; use rustc_infer::traits; +use rustc_middle::ty::trait_def::IncludeLocalImpls; use rustc_middle::ty::{self, TypingMode, Unnormalized, Upcast}; use rustc_span::DUMMY_SP; use rustc_span::def_id::DefId; @@ -30,7 +31,7 @@ pub(crate) fn synthesize_blanket_impls( continue; } // NOTE: doesn't use `for_each_relevant_impl` to avoid looking at anything besides blanket impls - let trait_impls = tcx.trait_impls_of(trait_def_id); + let trait_impls = tcx.trait_impls_of((trait_def_id, IncludeLocalImpls::Yes)); 'blanket_impls: for &impl_def_id in trait_impls.blanket_impls() { trace!("considering impl `{impl_def_id:?}` for trait `{trait_def_id:?}`"); diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 1f6d15147dcb3..3459d5c37f6a7 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -845,7 +845,7 @@ fn trait_impls_for<'tcx>( let mut impls = FxIndexSet::default(); for &trait_ in tcx.doc_link_traits_in_scope(module) { - tcx.for_each_relevant_impl(trait_, ty, |impl_| { + tcx.for_each_relevant_impl(trait_, ty, ty::IncludeLocalImpls::Yes, |impl_| { let trait_ref = tcx.impl_trait_ref(impl_); // Check if these are the same type. let impl_type = trait_ref.skip_binder().self_ty(); diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 50017eec7cf65..c6f4413408023 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -19,6 +19,7 @@ use rustc_hir::{ }; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; +use rustc_middle::ty::trait_def::IncludeLocalImpls; use rustc_middle::ty::{self, AssocTag, Ty, TyCtxt, TypeVisitableExt as _, TypeckResults, Unnormalized}; use rustc_span::{Span, Symbol, SyntaxContext}; use std::borrow::Cow; @@ -421,7 +422,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { .is_some() || !cx .tcx - .trait_impls_of(trait_.def_id) + .trait_impls_of((trait_.def_id, IncludeLocalImpls::Yes)) .blanket_impls() .is_empty() }) diff --git a/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs b/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs index 2d7d09285c16d..3b1240afdb2fd 100644 --- a/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs +++ b/src/tools/clippy/clippy_lints/src/derive/derive_ord_xor_partial_ord.rs @@ -24,31 +24,36 @@ pub(super) fn check<'tcx>( && !fulfill_or_allowed(cx, DERIVE_ORD_XOR_PARTIAL_ORD, [adt_hir_id]) { // Look for the PartialOrd implementations for `ty` - cx.tcx.for_each_relevant_impl(partial_ord_trait_def_id, ty, |impl_id| { - let partial_ord_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id); + cx.tcx.for_each_relevant_impl( + partial_ord_trait_def_id, + ty, + cx.typing_mode().include_local_impls(), + |impl_id| { + let partial_ord_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id); - if partial_ord_is_automatically_derived == ord_is_automatically_derived { - return; - } + if partial_ord_is_automatically_derived == ord_is_automatically_derived { + return; + } - let trait_ref = cx.tcx.impl_trait_ref(impl_id); + let trait_ref = cx.tcx.impl_trait_ref(impl_id); - // Only care about `impl PartialOrd for Foo` - // For `impl PartialOrd for A, input_types is [A, B] - if trait_ref.instantiate_identity().skip_norm_wip().args.type_at(1) == ty { - let mess = if partial_ord_is_automatically_derived { - "you are implementing `Ord` explicitly but have derived `PartialOrd`" - } else { - "you are deriving `Ord` but have implemented `PartialOrd` explicitly" - }; + // Only care about `impl PartialOrd for Foo` + // For `impl PartialOrd for A, input_types is [A, B] + if trait_ref.instantiate_identity().skip_norm_wip().args.type_at(1) == ty { + let mess = if partial_ord_is_automatically_derived { + "you are implementing `Ord` explicitly but have derived `PartialOrd`" + } else { + "you are deriving `Ord` but have implemented `PartialOrd` explicitly" + }; - span_lint_hir_and_then(cx, DERIVE_ORD_XOR_PARTIAL_ORD, item_hir_id, item.span, mess, |diag| { - if let Some(local_def_id) = impl_id.as_local() { - let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id); - diag.span_note(cx.tcx.hir_span(hir_id), "`PartialOrd` implemented here"); - } - }); - } - }); + span_lint_hir_and_then(cx, DERIVE_ORD_XOR_PARTIAL_ORD, item_hir_id, item.span, mess, |diag| { + if let Some(local_def_id) = impl_id.as_local() { + let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id); + diag.span_note(cx.tcx.hir_span(hir_id), "`PartialOrd` implemented here"); + } + }); + } + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs b/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs index b57a47526b354..f68ae12ea1a13 100644 --- a/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs +++ b/src/tools/clippy/clippy_lints/src/derive/derived_hash_with_manual_eq.rs @@ -20,32 +20,37 @@ pub(super) fn check<'tcx>( && cx.tcx.is_diagnostic_item(sym::Hash, def_id) { // Look for the PartialEq implementations for `ty` - cx.tcx.for_each_relevant_impl(peq_trait_def_id, ty, |impl_id| { - let peq_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id); + cx.tcx.for_each_relevant_impl( + peq_trait_def_id, + ty, + cx.typing_mode().include_local_impls(), + |impl_id| { + let peq_is_automatically_derived = cx.tcx.is_automatically_derived(impl_id); - if !hash_is_automatically_derived || peq_is_automatically_derived { - return; - } + if !hash_is_automatically_derived || peq_is_automatically_derived { + return; + } - let trait_ref = cx.tcx.impl_trait_ref(impl_id); + let trait_ref = cx.tcx.impl_trait_ref(impl_id); - // Only care about `impl PartialEq for Foo` - // For `impl PartialEq for A, input_types is [A, B] - if trait_ref.instantiate_identity().skip_norm_wip().args.type_at(1) == ty { - span_lint_hir_and_then( - cx, - DERIVED_HASH_WITH_MANUAL_EQ, - adt_hir_id, - span, - "you are deriving `Hash` but have implemented `PartialEq` explicitly", - |diag| { - if let Some(local_def_id) = impl_id.as_local() { - let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id); - diag.span_note(cx.tcx.hir_span(hir_id), "`PartialEq` implemented here"); - } - }, - ); - } - }); + // Only care about `impl PartialEq for Foo` + // For `impl PartialEq for A, input_types is [A, B] + if trait_ref.instantiate_identity().skip_norm_wip().args.type_at(1) == ty { + span_lint_hir_and_then( + cx, + DERIVED_HASH_WITH_MANUAL_EQ, + adt_hir_id, + span, + "you are deriving `Hash` but have implemented `PartialEq` explicitly", + |diag| { + if let Some(local_def_id) = impl_id.as_local() { + let hir_id = cx.tcx.local_def_id_to_hir_id(local_def_id); + diag.span_note(cx.tcx.hir_span(hir_id), "`PartialEq` implemented here"); + } + }, + ); + } + }, + ); } } diff --git a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs index e3b76b2b83452..a87a4e5355f1b 100644 --- a/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs +++ b/src/tools/clippy/clippy_lints/src/unconditional_recursion.rs @@ -11,6 +11,7 @@ use rustc_hir::{Body, Expr, ExprKind, FnDecl, HirId, Item, ItemKind, Node, QPath use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::hir::nested_filter; +use rustc_middle::ty::trait_def::IncludeLocalImpls; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::Span; use rustc_span::symbol::{Ident, kw}; @@ -335,7 +336,7 @@ impl UnconditionalRecursion { if self.default_impl_for_type.is_empty() && let Some(default_trait_id) = cx.tcx.get_diagnostic_item(sym::Default) { - let impls = cx.tcx.trait_impls_of(default_trait_id); + let impls = cx.tcx.trait_impls_of((default_trait_id, IncludeLocalImpls::Yes)); for (ty, impl_def_ids) in impls.non_blanket_impls() { let Some(self_def_id) = ty.def() else { continue }; for &impl_def_id in impl_def_ids { diff --git a/tests/ui/reflection/rustc_isolated_const.rs b/tests/ui/reflection/rustc_isolated_const.rs new file mode 100644 index 0000000000000..b1a2e917ca97d --- /dev/null +++ b/tests/ui/reflection/rustc_isolated_const.rs @@ -0,0 +1,34 @@ +//! Ensure that adding rustc_isolated_const makes calls +//! to local methods fail. + +#![feature(const_trait_impl, rustc_attrs)] + +#[rustc_isolated_const] +const VAL: usize = { + <() as Foo>::bar() + //~^ ERROR the trait bound `(): Foo` is not satisfied +}; + +#[rustc_isolated_const] +const VAL2: () = { + Bar.bar() + //^ FIXME(isolated_const) should also error +}; + +const trait Foo { + fn bar() -> usize { + todo!() + } +} + +const impl Foo for () {} + +struct Bar; + +const impl Bar { + fn bar(&self) {} +} + +fn main() { + assert_eq!(VAL, 42); +} diff --git a/tests/ui/reflection/rustc_isolated_const.stderr b/tests/ui/reflection/rustc_isolated_const.stderr new file mode 100644 index 0000000000000..6a252005c678f --- /dev/null +++ b/tests/ui/reflection/rustc_isolated_const.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `(): Foo` is not satisfied + --> $DIR/rustc_isolated_const.rs:8:6 + | +LL | <() as Foo>::bar() + | ^^ the trait `Foo` is not implemented for `()` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/reflection/rustc_isolated_const_local.rs b/tests/ui/reflection/rustc_isolated_const_local.rs new file mode 100644 index 0000000000000..122a4147be661 --- /dev/null +++ b/tests/ui/reflection/rustc_isolated_const_local.rs @@ -0,0 +1,19 @@ +//@ build-pass + +#![feature(const_trait_impl, rustc_attrs)] + +#[rustc_isolated_const] +const VAL: usize = { 4 + std::mem::size_of::() }; + +// irrelevant local impls that should not fail the eval of VAL +const trait Foo { + fn bar() -> usize { + todo!() + } +} + +const impl Foo for () {} + +fn main() { + assert_eq!(VAL, 42); +}