diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs index 44c817b33184e..80262e4fb4646 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs @@ -236,7 +236,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { }; let (infcx, param_env) = - self.tcx.infer_ctxt().build_with_typing_env(self.typing_env); + self.tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv { + typing_mode: ty::TypingMode::Reflection, + ..self.typing_env + }); let ocx = ObligationCtxt::new(&infcx); ocx.register_obligations(preds.iter().map(|pred: PolyExistentialPredicate<'_>| { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c60471848c892..162dd75a1e9f8 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1,6 +1,7 @@ // ignore-tidy-filelength use std::borrow::Cow; use std::fmt; +use std::ops::ControlFlow; use rustc_abi::ExternAbi; use rustc_ast::attr::AttributeExt; @@ -16,6 +17,7 @@ pub use rustc_ast::{ MetaItemInner, MetaItemLit, Movability, Mutability, Pinnedness, UnOp, }; use rustc_data_structures::fingerprint::Fingerprint; +use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_error_messages::{DiagArgValue, IntoDiagArg}; @@ -35,7 +37,7 @@ use crate::attrs::AttributeKind; use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; use crate::def_id::{DefId, LocalDefIdMap}; pub(crate) use crate::hir_id::{HirId, ItemLocalId, ItemLocalMap, OwnerId}; -use crate::intravisit::{FnKind, VisitorExt}; +use crate::intravisit::{FnKind, Visitor, VisitorExt}; use crate::lints::DelayedLints; #[derive(Debug, Copy, Clone, PartialEq, Eq, HashStable_Generic)] @@ -4445,6 +4447,70 @@ pub struct Impl<'hir> { pub constness: Constness, } +impl Impl<'_> { + pub fn is_fully_generic_for_reflection(&self) -> bool { + #[derive(Default)] + struct LifetimeFinder { + seen: FxHashSet, + } + impl<'v> Visitor<'v> for LifetimeFinder { + type Result = ControlFlow<()>; + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result { + match lifetime.kind { + LifetimeKind::Param(def_id) => { + if self.seen.insert(def_id) { + ControlFlow::Continue(()) + } else { + ControlFlow::Break(()) + } + } + LifetimeKind::ImplicitObjectLifetimeDefault + | LifetimeKind::Error + | LifetimeKind::Infer + | LifetimeKind::Static => ControlFlow::Break(()), + } + } + } + let mut ty_lifetimes = LifetimeFinder::default(); + if ty_lifetimes.visit_ty_unambig(self.self_ty).is_break() { + return false; + } + let ty_lifetimes = ty_lifetimes.seen; + + #[derive(Default)] + struct LifetimeChecker { + ty_lifetimes: FxHashSet, + } + impl<'v> Visitor<'v> for LifetimeChecker { + type Result = ControlFlow<()>; + fn visit_lifetime(&mut self, lifetime: &'v Lifetime) -> Self::Result { + match lifetime.kind { + LifetimeKind::Param(def_id) => { + if self.ty_lifetimes.contains(&def_id) { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } + LifetimeKind::ImplicitObjectLifetimeDefault + | LifetimeKind::Error + | LifetimeKind::Infer + | LifetimeKind::Static => ControlFlow::Continue(()), + } + } + } + + let mut checker = LifetimeChecker { ty_lifetimes }; + + // Pessimistic: if any of the lifetimes used in the type show up in where bounds + // don't allow this impl to be used. + self.generics + .predicates + .iter() + .all(|pred| checker.visit_where_predicate(pred).is_continue()) + } +} + #[derive(Debug, Clone, Copy, HashStable_Generic)] pub struct TraitImplHeader<'hir> { pub safety: Safety, diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 2e06684e0c7a8..fa644b627d5a1 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1345,6 +1345,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader .unwrap_or_else(|| panic!("expected impl trait, found inherent impl on {def_id:?}")); let selfty = tcx.type_of(def_id).instantiate_identity(); let is_rustc_reservation = tcx.has_attr(def_id, sym::rustc_reservation_impl); + let is_fully_generic_for_reflection = impl_.is_fully_generic_for_reflection(); check_impl_constness(tcx, impl_.constness, &of_trait.trait_ref); @@ -1355,6 +1356,7 @@ fn impl_trait_header(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::ImplTraitHeader safety: of_trait.safety, polarity: polarity_of_impl(tcx, of_trait, is_rustc_reservation), constness: impl_.constness, + is_fully_generic_for_reflection, } } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 53567c6071e3c..75adfabcb94dd 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1055,6 +1055,7 @@ impl<'tcx> InferCtxt<'tcx> { // and post-borrowck analysis mode. We may need to modify its uses // to support PostBorrowckAnalysis in the old solver as well. TypingMode::Coherence + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => false, } @@ -1379,6 +1380,7 @@ impl<'tcx> InferCtxt<'tcx> { } mode @ (ty::TypingMode::Coherence | ty::TypingMode::PostBorrowckAnalysis { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostAnalysis) => mode, }; ty::TypingEnv { typing_mode, param_env } diff --git a/compiler/rustc_infer/src/infer/opaque_types/mod.rs b/compiler/rustc_infer/src/infer/opaque_types/mod.rs index 9579abf7ec53c..d533876dbe8a7 100644 --- a/compiler/rustc_infer/src/infer/opaque_types/mod.rs +++ b/compiler/rustc_infer/src/infer/opaque_types/mod.rs @@ -276,7 +276,9 @@ impl<'tcx> InferCtxt<'tcx> { .map(|obligation| obligation.as_goal()), ); } - mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis) => { + mode @ (ty::TypingMode::PostBorrowckAnalysis { .. } + | ty::TypingMode::PostAnalysis + | ty::TypingMode::Reflection) => { bug!("insert hidden type in {mode:?}") } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 471bd1d937e94..f635537cb31e1 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -689,6 +689,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.impl_polarity(impl_def_id) } + fn is_fully_generic_for_reflection(self, impl_def_id: Self::ImplId) -> bool { + self.impl_trait_header(impl_def_id).is_fully_generic_for_reflection + } + fn trait_is_auto(self, trait_def_id: DefId) -> bool { self.trait_is_auto(trait_def_id) } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 2021f175cd848..b537a72da0d09 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -262,6 +262,10 @@ pub struct ImplTraitHeader<'tcx> { pub polarity: ImplPolarity, pub safety: hir::Safety, pub constness: hir::Constness, + /// Whether all generic parameters of the type are unique unconstrained generic parameters + /// of the impl. `Bar<'static>` or `Foo<'a, 'a>` or outlives bounds on the lifetimes cause + /// this boolean to be false and `try_as_dyn` to return `None`. + pub is_fully_generic_for_reflection: bool, } #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, HashStable, Debug)] 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 d27d80a086ad1..8b7404cdc3a75 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -928,6 +928,7 @@ where TypingMode::Coherence => return, TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => {} } @@ -991,6 +992,7 @@ where TypingMode::Analysis { .. } => self.opaques_with_sub_unified_hidden_type(self_ty), TypingMode::Coherence | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => vec![], }; diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index 2837b8565f603..342818da327ef 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -142,6 +142,7 @@ where TypingMode::Coherence => Certainty::AMBIGUOUS, TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), }, diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 52a1479d70a15..4baae58d549b3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -368,7 +368,7 @@ where fn opaque_type_is_rigid(&self, def_id: I::DefId) -> bool { match self.typing_mode() { // Opaques are never rigid outside of analysis mode. - TypingMode::Coherence | TypingMode::PostAnalysis => false, + TypingMode::Reflection | TypingMode::Coherence | TypingMode::PostAnalysis => false, // During analysis, opaques are rigid unless they may be defined by // the current body. TypingMode::Analysis { defining_opaque_types_and_generators: non_rigid_opaques } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index 70c28421c57ea..d17accf9c0ec7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -298,6 +298,7 @@ where // Outside of coherence, we treat the associated item as rigid instead. ty::TypingMode::Analysis { .. } | ty::TypingMode::Borrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis => { ecx.structurally_instantiate_normalizes_to_term( @@ -336,6 +337,7 @@ where } ty::TypingMode::Analysis { .. } | ty::TypingMode::Borrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostBorrowckAnalysis { .. } | ty::TypingMode::PostAnalysis => { ecx.structurally_instantiate_normalizes_to_term( 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 a5f857a1dd85b..0fe17eedf89da 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 @@ -126,7 +126,7 @@ where self.eq(goal.param_env, expected, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - TypingMode::PostAnalysis => { + TypingMode::Reflection | TypingMode::PostAnalysis => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(opaque_ty.def_id).instantiate(cx, opaque_ty.args); self.eq(goal.param_env, expected, 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 ea45d50969909..efe4f0d8683fe 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -68,6 +68,7 @@ where } TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => Err(NoSolution), }, 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 651f073efb828..02c4f5a7b70e6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -78,13 +78,22 @@ where TypingMode::Coherence => Certainty::AMBIGUOUS, TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => return Err(NoSolution), }, // Impl matches polarity (ty::ImplPolarity::Positive, ty::PredicatePolarity::Positive) - | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => Certainty::Yes, + | (ty::ImplPolarity::Negative, ty::PredicatePolarity::Negative) => { + if let TypingMode::Reflection = ecx.typing_mode() + && !cx.is_fully_generic_for_reflection(impl_def_id) + { + return Err(NoSolution); + } else { + Certainty::Yes + } + } // Impl doesn't match polarity (ty::ImplPolarity::Positive, ty::PredicatePolarity::Negative) @@ -1330,6 +1339,7 @@ where TypingMode::Coherence => return, TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => {} } @@ -1504,6 +1514,7 @@ where } TypingMode::Coherence | TypingMode::PostAnalysis + | TypingMode::Reflection | TypingMode::Borrowck { defining_opaque_types: _ } | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => {} } diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index b6bdf1067a35e..b70efceadd7ce 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -278,6 +278,7 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< TypingMode::Coherence | TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } => false, TypingMode::PostAnalysis => { let poly_trait_ref = self.resolve_vars_if_possible(goal_trait_ref); diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 7b61a653ae31e..97b167a82bad0 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -289,6 +289,7 @@ where TypingMode::Coherence | TypingMode::Borrowck { defining_opaque_types: _ } | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } + | TypingMode::Reflection | TypingMode::PostAnalysis => return Default::default(), }; diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 681f015c17990..b62afd37dc671 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -179,6 +179,7 @@ where TypingMode::Coherence | TypingMode::Borrowck { defining_opaque_types: _ } | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } + | TypingMode::Reflection | TypingMode::PostAnalysis => return Default::default(), }; diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 71e9914f93fa8..1c3b11d2a16b6 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -138,7 +138,7 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( | TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), - TypingMode::PostAnalysis => {} + TypingMode::Reflection | TypingMode::PostAnalysis => {} } value.has_type_flags(flags) @@ -402,7 +402,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx | TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => ty.super_fold_with(self), - TypingMode::PostAnalysis => { + TypingMode::Reflection | TypingMode::PostAnalysis => { 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 e5c2adaa261d3..1d707b6919062 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -954,6 +954,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( TypingMode::Coherence | TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } => { debug!( assoc_ty = ?selcx.tcx().def_path_str(node_item.item.def_id), diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 02438b24ca7f4..97d68c6ff48a5 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -222,7 +222,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } => ty.try_super_fold_with(self)?, - TypingMode::PostAnalysis => { + TypingMode::Reflection | TypingMode::PostAnalysis => { 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/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index ea903bac9d617..8da95518bbfd0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1467,6 +1467,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { TypingMode::Coherence => {} TypingMode::Analysis { .. } | TypingMode::Borrowck { .. } + | TypingMode::Reflection | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => return Ok(()), } @@ -1519,6 +1520,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { defining_opaque_types.is_empty() || (!pred.has_opaque_types() && !pred.has_coroutines()) } + // Impls that are not fully generic are completely ignored as "nonexistent" + // in this mode, so the results wildly differ from normal trait solving. + TypingMode::Reflection => false, // The hidden types of `defined_opaque_types` is not local to the current // inference context, so we can freely move this to the global cache. TypingMode::PostBorrowckAnalysis { .. } => true, @@ -2548,6 +2552,12 @@ impl<'tcx> SelectionContext<'_, 'tcx> { debug!("reservation impls only apply in intercrate mode"); return Err(()); } + if !impl_trait_header.is_fully_generic_for_reflection + && matches!(self.infcx.typing_mode(), TypingMode::Reflection) + { + debug!("reflection mode only allows fully generic impls"); + return Err(()); + } Ok(Normalized { value: impl_args, obligations: nested_obligations }) } @@ -2884,6 +2894,7 @@ impl<'tcx> SelectionContext<'_, 'tcx> { } TypingMode::Coherence | TypingMode::PostAnalysis + | TypingMode::Reflection | TypingMode::Borrowck { defining_opaque_types: _ } | TypingMode::PostBorrowckAnalysis { defined_opaque_types: _ } => false, } diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index 23bbd9ca6d639..5209956d00277 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -158,6 +158,7 @@ fn resolve_associated_item<'tcx>( ty::TypingMode::Coherence | ty::TypingMode::Analysis { .. } | ty::TypingMode::Borrowck { .. } + | ty::TypingMode::Reflection | ty::TypingMode::PostBorrowckAnalysis { .. } => false, ty::TypingMode::PostAnalysis => !trait_ref.still_further_specializable(), } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index feafcee7bad9e..912df806b4d7e 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -79,6 +79,10 @@ pub enum TypingMode { /// This is currently only used by the new solver, but should be implemented in /// the old solver as well. PostBorrowckAnalysis { defined_opaque_types: I::LocalDefIds }, + /// During the evaluation of reflection logic that ignores lifetimes, we can only + /// handle impls that are fully generic over all lifetimes without constraints on + /// those lifetimes (other than implied bounds). + Reflection, /// After analysis, mostly during codegen and MIR optimizations, we're able to /// reveal all opaque types. As the hidden type should *never* be observable /// directly by the user, this should not be used by checks which may expose diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 3884f29a4fc80..5f7077ee57b39 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -367,6 +367,8 @@ pub trait Interner: fn impl_polarity(self, impl_def_id: Self::ImplId) -> ty::ImplPolarity; + fn is_fully_generic_for_reflection(self, impl_def_id: Self::ImplId) -> bool; + fn trait_is_auto(self, trait_def_id: Self::TraitId) -> bool; fn trait_is_coinductive(self, trait_def_id: Self::TraitId) -> bool; diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 64b87fac77f94..f64faf1a9d5a3 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -140,6 +140,7 @@ where Ok(a) } TypingMode::Analysis { .. } + | TypingMode::Reflection | TypingMode::Borrowck { .. } | TypingMode::PostBorrowckAnalysis { .. } | TypingMode::PostAnalysis => structurally_relate_tys(relation, a, b), diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 42f332f7d8ba8..5ae34f58533f2 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -942,10 +942,7 @@ pub const fn type_name_of_val(_val: &T) -> &'static str { /// ``` #[must_use] #[unstable(feature = "try_as_dyn", issue = "144361")] -pub const fn try_as_dyn< - T: Any + 'static, - U: ptr::Pointee> + ?Sized + 'static, ->( +pub const fn try_as_dyn> + ?Sized>( t: &T, ) -> Option<&U> { let vtable: Option> = const { intrinsics::vtable_for::() }; @@ -995,10 +992,7 @@ pub const fn try_as_dyn< /// ``` #[must_use] #[unstable(feature = "try_as_dyn", issue = "144361")] -pub const fn try_as_dyn_mut< - T: Any + 'static, - U: ptr::Pointee> + ?Sized + 'static, ->( +pub const fn try_as_dyn_mut> + ?Sized>( t: &mut T, ) -> Option<&mut U> { let vtable: Option> = const { intrinsics::vtable_for::() }; diff --git a/tests/ui/any/non_static.rs b/tests/ui/any/non_static.rs new file mode 100644 index 0000000000000..5d9f6713aff89 --- /dev/null +++ b/tests/ui/any/non_static.rs @@ -0,0 +1,48 @@ +//@ revisions: next old +//@[next] compile-flags: -Znext-solver +//@check-pass +#![feature(try_as_dyn)] + +trait Trait {} + +impl<'a> Trait for &'a [(); 1] {} + +impl Trait for &() {} +impl Trait for () {} + +// Not fully generic impl -> returns None even tho +// implemented for *some* lifetimes +impl<'a> Trait for (&'a (), &'a ()) {} + +// Not fully generic impl -> returns None even tho +// implemented for *some* lifetimes +impl<'a, 'b: 'a> Trait for (&'a (), &'b (), ()) {} + +// Only valid for 'static lifetimes -> returns None +impl Trait for &'static u32 {} + +trait Trait2 {} + +struct Struct(T); + +// While this is the impl for `Trait`, in `Reflection` solver mode +// we reject the impl for `Trait2` below, and thus this impl also +// doesn't match. +impl Trait for Struct {} + +impl Trait2 for &'static u32 {} + +// Test that downcasting to a dyn trait works as expected +const _: () = { + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&42_i32).is_none()); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&()).is_some()); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&[()]).is_some()); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&()).is_some()); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&&42_u32).is_none()); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&(&(), &())).is_none()); + assert!(std::any::try_as_dyn::<_, dyn Trait>(&(&(), &(), ())).is_none()); + + assert!(std::any::try_as_dyn::<_, dyn Trait>(&Struct(&42_u32)).is_none()); +}; + +fn main() {}