diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 7c925d5fbb660..10b0909209a05 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -58,30 +58,6 @@ pub enum TreatParams { /// This also treats projections with inference variables as infer vars /// since they could be further normalized. ForLookup, - /// Treat parameters as placeholders in the given environment. This is the - /// correct mode for *lookup*, as during candidate selection. - /// - /// N.B. during deep rejection, this acts identically to `ForLookup`. - /// - /// FIXME(-Znext-solver): Remove this variant and cleanup - /// the code. - NextSolverLookup, -} - -/// During fast-rejection, we have the choice of treating projection types -/// as either simplifiable or not, depending on whether we expect the projection -/// to be normalized/rigid. -#[derive(PartialEq, Eq, Debug, Clone, Copy)] -pub enum TreatProjections { - /// In the old solver we don't try to normalize projections - /// when looking up impls and only access them by using the - /// current self type. This means that if the self type is - /// a projection which could later be normalized, we must not - /// treat it as rigid. - ForLookup, - /// We can treat projections in the self type as opaque as - /// we separately look up impls for the normalized self type. - NextSolverLookup, } /// Tries to simplify a type by only returning the outermost injective¹ layer, if one exists. @@ -139,21 +115,17 @@ pub fn simplify_type<'tcx>( ty::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())), ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Param(_) => match treat_params { - TreatParams::ForLookup | TreatParams::NextSolverLookup => { - Some(SimplifiedType::Placeholder) - } + TreatParams::ForLookup => Some(SimplifiedType::Placeholder), TreatParams::AsCandidateKey => None, }, ty::Alias(..) => match treat_params { // When treating `ty::Param` as a placeholder, projections also // don't unify with anything else as long as they are fully normalized. - // - // We will have to be careful with lazy normalization here. - // FIXME(lazy_normalization): This is probably not right... + // FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder` + // when the new solver is enabled by default. TreatParams::ForLookup if !ty.has_non_region_infer() => { Some(SimplifiedType::Placeholder) } - TreatParams::NextSolverLookup => Some(SimplifiedType::Placeholder), TreatParams::ForLookup | TreatParams::AsCandidateKey => None, }, ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), @@ -331,7 +303,7 @@ impl DeepRejectCtxt { // Depending on the value of `treat_obligation_params`, we either // treat generic parameters like placeholders or like inference variables. ty::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup | TreatParams::NextSolverLookup => false, + TreatParams::ForLookup => false, TreatParams::AsCandidateKey => true, }, @@ -373,7 +345,7 @@ impl DeepRejectCtxt { let k = impl_ct.kind(); match obligation_ct.kind() { ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::ForLookup | TreatParams::NextSolverLookup => false, + TreatParams::ForLookup => false, TreatParams::AsCandidateKey => true, }, diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index d85b541d36386..e06e3465eb2a8 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,5 +1,5 @@ use crate::traits::specialization_graph; -use crate::ty::fast_reject::{self, SimplifiedType, TreatParams, TreatProjections}; +use crate::ty::fast_reject::{self, SimplifiedType, TreatParams}; use crate::ty::{Ident, Ty, TyCtxt}; use hir::def_id::LOCAL_CRATE; use rustc_hir as hir; @@ -135,21 +135,6 @@ impl<'tcx> TyCtxt<'tcx> { self, trait_def_id: DefId, self_ty: Ty<'tcx>, - f: impl FnMut(DefId), - ) { - self.for_each_relevant_impl_treating_projections( - trait_def_id, - self_ty, - TreatProjections::ForLookup, - f, - ) - } - - pub fn for_each_relevant_impl_treating_projections( - self, - trait_def_id: DefId, - self_ty: Ty<'tcx>, - treat_projections: TreatProjections, mut f: impl FnMut(DefId), ) { // FIXME: This depends on the set of all impls for the trait. That is @@ -163,17 +148,13 @@ impl<'tcx> TyCtxt<'tcx> { f(impl_def_id); } - // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using - // `TreatParams::AsCandidateKey` while actually adding them. - let treat_params = match treat_projections { - TreatProjections::NextSolverLookup => TreatParams::NextSolverLookup, - TreatProjections::ForLookup => TreatParams::ForLookup, - }; // This way, when searching for some impl for `T: Trait`, we do not look at any impls // whose outer level is not a parameter or projection. Especially for things like // `T: Clone` this is incredibly useful as we would otherwise look at all the impls // of `Clone` for `Option`, `Vec`, `ConcreteType` and so on. - if let Some(simp) = fast_reject::simplify_type(self, self_ty, treat_params) { + // Note that we're using `TreatParams::ForLookup` to query `non_blanket_impls` while using + // `TreatParams::AsCandidateKey` while actually adding them. + if let Some(simp) = fast_reject::simplify_type(self, self_ty, TreatParams::ForLookup) { if let Some(impls) = impls.non_blanket_impls.get(&simp) { for &impl_def_id in impls { f(impl_def_id); diff --git a/compiler/rustc_trait_selection/src/solve/trait_goals.rs b/compiler/rustc_trait_selection/src/solve/trait_goals.rs index ed76ea74f08f9..f6d12a9a0138e 100644 --- a/compiler/rustc_trait_selection/src/solve/trait_goals.rs +++ b/compiler/rustc_trait_selection/src/solve/trait_goals.rs @@ -14,7 +14,7 @@ use rustc_middle::traits::solve::{ CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, }; use rustc_middle::traits::{BuiltinImplSource, Reveal}; -use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, TreatProjections}; +use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams}; use rustc_middle::ty::{self, ToPredicate, Ty, TyCtxt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, DUMMY_SP}; @@ -1045,6 +1045,12 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { } } + // If we still have an alias here, it must be rigid. For opaques, it's always + // okay to consider auto traits because that'll reveal its hidden type. For + // non-opaque aliases, we will not assemble any candidates since there's no way + // to further look into its type. + ty::Alias(..) => None, + // For rigid types, any possible implementation that could apply to // the type (even if after unification and processing nested goals // it does not hold) will disqualify the built-in auto impl. @@ -1072,15 +1078,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> { | ty::CoroutineWitness(..) | ty::Never | ty::Tuple(_) - | ty::Adt(_, _) - // FIXME: Handling opaques here is kinda sus. Especially because we - // simplify them to SimplifiedType::Placeholder. - | ty::Alias(ty::Opaque, _) => { + | ty::Adt(_, _) => { let mut disqualifying_impl = None; - self.tcx().for_each_relevant_impl_treating_projections( + self.tcx().for_each_relevant_impl( goal.predicate.def_id(), goal.predicate.self_ty(), - TreatProjections::NextSolverLookup, |impl_def_id| { disqualifying_impl = Some(impl_def_id); },