1
Fork 0

Rollup merge of #124379 - compiler-errors:remove-new-solver-lookup-behavior, r=lcnr

Remove special-casing for `SimplifiedType` for next solver

It's unnecessary due to the way that we fully normalize the self type before assembly begins.

r? lcnr
This commit is contained in:
Michael Goulet 2024-04-25 20:07:41 -04:00 committed by GitHub
commit 4494140244
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 63 deletions

View file

@ -58,30 +58,6 @@ pub enum TreatParams {
/// This also treats projections with inference variables as infer vars /// This also treats projections with inference variables as infer vars
/// since they could be further normalized. /// since they could be further normalized.
ForLookup, 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. /// 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::FnPtr(f) => Some(SimplifiedType::Function(f.skip_binder().inputs().len())),
ty::Placeholder(..) => Some(SimplifiedType::Placeholder), ty::Placeholder(..) => Some(SimplifiedType::Placeholder),
ty::Param(_) => match treat_params { ty::Param(_) => match treat_params {
TreatParams::ForLookup | TreatParams::NextSolverLookup => { TreatParams::ForLookup => Some(SimplifiedType::Placeholder),
Some(SimplifiedType::Placeholder)
}
TreatParams::AsCandidateKey => None, TreatParams::AsCandidateKey => None,
}, },
ty::Alias(..) => match treat_params { ty::Alias(..) => match treat_params {
// When treating `ty::Param` as a placeholder, projections also // When treating `ty::Param` as a placeholder, projections also
// don't unify with anything else as long as they are fully normalized. // don't unify with anything else as long as they are fully normalized.
// // FIXME(-Znext-solver): Can remove this `if` and always simplify to `Placeholder`
// We will have to be careful with lazy normalization here. // when the new solver is enabled by default.
// FIXME(lazy_normalization): This is probably not right...
TreatParams::ForLookup if !ty.has_non_region_infer() => { TreatParams::ForLookup if !ty.has_non_region_infer() => {
Some(SimplifiedType::Placeholder) Some(SimplifiedType::Placeholder)
} }
TreatParams::NextSolverLookup => Some(SimplifiedType::Placeholder),
TreatParams::ForLookup | TreatParams::AsCandidateKey => None, TreatParams::ForLookup | TreatParams::AsCandidateKey => None,
}, },
ty::Foreign(def_id) => Some(SimplifiedType::Foreign(def_id)), 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 // Depending on the value of `treat_obligation_params`, we either
// treat generic parameters like placeholders or like inference variables. // treat generic parameters like placeholders or like inference variables.
ty::Param(_) => match self.treat_obligation_params { ty::Param(_) => match self.treat_obligation_params {
TreatParams::ForLookup | TreatParams::NextSolverLookup => false, TreatParams::ForLookup => false,
TreatParams::AsCandidateKey => true, TreatParams::AsCandidateKey => true,
}, },
@ -373,7 +345,7 @@ impl DeepRejectCtxt {
let k = impl_ct.kind(); let k = impl_ct.kind();
match obligation_ct.kind() { match obligation_ct.kind() {
ty::ConstKind::Param(_) => match self.treat_obligation_params { ty::ConstKind::Param(_) => match self.treat_obligation_params {
TreatParams::ForLookup | TreatParams::NextSolverLookup => false, TreatParams::ForLookup => false,
TreatParams::AsCandidateKey => true, TreatParams::AsCandidateKey => true,
}, },

View file

@ -1,5 +1,5 @@
use crate::traits::specialization_graph; 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 crate::ty::{Ident, Ty, TyCtxt};
use hir::def_id::LOCAL_CRATE; use hir::def_id::LOCAL_CRATE;
use rustc_hir as hir; use rustc_hir as hir;
@ -135,21 +135,6 @@ impl<'tcx> TyCtxt<'tcx> {
self, self,
trait_def_id: DefId, trait_def_id: DefId,
self_ty: Ty<'tcx>, 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), mut f: impl FnMut(DefId),
) { ) {
// FIXME: This depends on the set of all impls for the trait. That is // 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); 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 // 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 // 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 // `T: Clone` this is incredibly useful as we would otherwise look at all the impls
// of `Clone` for `Option<T>`, `Vec<T>`, `ConcreteType` and so on. // of `Clone` for `Option<T>`, `Vec<T>`, `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) { if let Some(impls) = impls.non_blanket_impls.get(&simp) {
for &impl_def_id in impls { for &impl_def_id in impls {
f(impl_def_id); f(impl_def_id);

View file

@ -14,7 +14,7 @@ use rustc_middle::traits::solve::{
CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult, CandidateSource, CanonicalResponse, Certainty, Goal, QueryResult,
}; };
use rustc_middle::traits::{BuiltinImplSource, Reveal}; 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::{self, ToPredicate, Ty, TyCtxt};
use rustc_middle::ty::{TraitPredicate, TypeVisitableExt}; use rustc_middle::ty::{TraitPredicate, TypeVisitableExt};
use rustc_span::{ErrorGuaranteed, DUMMY_SP}; 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 // For rigid types, any possible implementation that could apply to
// the type (even if after unification and processing nested goals // the type (even if after unification and processing nested goals
// it does not hold) will disqualify the built-in auto impl. // it does not hold) will disqualify the built-in auto impl.
@ -1072,15 +1078,11 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
| ty::CoroutineWitness(..) | ty::CoroutineWitness(..)
| ty::Never | ty::Never
| ty::Tuple(_) | ty::Tuple(_)
| ty::Adt(_, _) | ty::Adt(_, _) => {
// FIXME: Handling opaques here is kinda sus. Especially because we
// simplify them to SimplifiedType::Placeholder.
| ty::Alias(ty::Opaque, _) => {
let mut disqualifying_impl = None; 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.def_id(),
goal.predicate.self_ty(), goal.predicate.self_ty(),
TreatProjections::NextSolverLookup,
|impl_def_id| { |impl_def_id| {
disqualifying_impl = Some(impl_def_id); disqualifying_impl = Some(impl_def_id);
}, },