diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:20:29 +0000 |
commit | 631cd5845e8de329d0e227aaa707d7ea228b8f8f (patch) | |
tree | a1b87c8f8cad01cf18f7c5f57a08f102771ed303 /compiler/rustc_middle/src/ty/fast_reject.rs | |
parent | Adding debian version 1.69.0+dfsg1-1. (diff) | |
download | rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.tar.xz rustc-631cd5845e8de329d0e227aaa707d7ea228b8f8f.zip |
Merging upstream version 1.70.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_middle/src/ty/fast_reject.rs')
-rw-r--r-- | compiler/rustc_middle/src/ty/fast_reject.rs | 104 |
1 files changed, 67 insertions, 37 deletions
diff --git a/compiler/rustc_middle/src/ty/fast_reject.rs b/compiler/rustc_middle/src/ty/fast_reject.rs index 59deade0a..31d00b65e 100644 --- a/compiler/rustc_middle/src/ty/fast_reject.rs +++ b/compiler/rustc_middle/src/ty/fast_reject.rs @@ -1,6 +1,6 @@ use crate::mir::Mutability; use crate::ty::subst::GenericArgKind; -use crate::ty::{self, Ty, TyCtxt, TypeVisitableExt}; +use crate::ty::{self, SubstsRef, Ty, TyCtxt, TypeVisitableExt}; use rustc_hir::def_id::DefId; use std::fmt::Debug; use std::hash::Hash; @@ -51,15 +51,36 @@ pub enum SimplifiedType { /// generic parameters as if they were inference variables in that case. #[derive(PartialEq, Eq, Debug, Clone, Copy)] pub enum TreatParams { - /// Treat parameters as placeholders in the given environment. + /// Treat parameters as infer vars. This is the correct mode for caching + /// an impl's type for lookup. + AsCandidateKey, + /// Treat parameters as placeholders in the given environment. This is the + /// correct mode for *lookup*, as during candidate selection. /// - /// Note that this also causes us to treat projections as if they were - /// placeholders. This is only correct if the given projection cannot - /// be normalized in the current context. Even if normalization fails, - /// it may still succeed later if the projection contains any inference - /// variables. - AsPlaceholder, - AsInfer, + /// 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`. + NextSolverLookup, +} + +/// During fast-rejection, we have the choice of treating projection types +/// as either simplifyable 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. @@ -115,19 +136,20 @@ pub fn simplify_type<'tcx>( ty::FnPtr(f) => Some(FunctionSimplifiedType(f.skip_binder().inputs().len())), ty::Placeholder(..) => Some(PlaceholderSimplifiedType), ty::Param(_) => match treat_params { - TreatParams::AsPlaceholder => Some(PlaceholderSimplifiedType), - TreatParams::AsInfer => None, + TreatParams::ForLookup | TreatParams::NextSolverLookup => { + Some(PlaceholderSimplifiedType) + } + 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. - TreatParams::AsPlaceholder if !ty.has_non_region_infer() => { - debug!("treating `{}` as a placeholder", ty); - Some(PlaceholderSimplifiedType) - } - TreatParams::AsPlaceholder | TreatParams::AsInfer => None, + // FIXME(lazy_normalization): This is probably not right... + TreatParams::ForLookup if !ty.has_non_region_infer() => Some(PlaceholderSimplifiedType), + TreatParams::NextSolverLookup => Some(PlaceholderSimplifiedType), + TreatParams::ForLookup | TreatParams::AsCandidateKey => None, }, ty::Foreign(def_id) => Some(ForeignSimplifiedType(def_id)), ty::Bound(..) | ty::Infer(_) | ty::Error(_) => None, @@ -166,22 +188,24 @@ pub struct DeepRejectCtxt { } impl DeepRejectCtxt { - pub fn generic_args_may_unify<'tcx>( + pub fn substs_refs_may_unify<'tcx>( self, - obligation_arg: ty::GenericArg<'tcx>, - impl_arg: ty::GenericArg<'tcx>, + obligation_substs: SubstsRef<'tcx>, + impl_substs: SubstsRef<'tcx>, ) -> bool { - match (obligation_arg.unpack(), impl_arg.unpack()) { - // We don't fast reject based on regions for now. - (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true, - (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => { - self.types_may_unify(obl, imp) - } - (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => { - self.consts_may_unify(obl, imp) + iter::zip(obligation_substs, impl_substs).all(|(obl, imp)| { + match (obl.unpack(), imp.unpack()) { + // We don't fast reject based on regions for now. + (GenericArgKind::Lifetime(_), GenericArgKind::Lifetime(_)) => true, + (GenericArgKind::Type(obl), GenericArgKind::Type(imp)) => { + self.types_may_unify(obl, imp) + } + (GenericArgKind::Const(obl), GenericArgKind::Const(imp)) => { + self.consts_may_unify(obl, imp) + } + _ => bug!("kind mismatch: {obl} {imp}"), } - _ => bug!("kind mismatch: {obligation_arg} {impl_arg}"), - } + }) } pub fn types_may_unify<'tcx>(self, obligation_ty: Ty<'tcx>, impl_ty: Ty<'tcx>) -> bool { @@ -236,9 +260,7 @@ impl DeepRejectCtxt { }, ty::Adt(obl_def, obl_substs) => match k { &ty::Adt(impl_def, impl_substs) => { - obl_def == impl_def - && iter::zip(obl_substs, impl_substs) - .all(|(obl, imp)| self.generic_args_may_unify(obl, imp)) + obl_def == impl_def && self.substs_refs_may_unify(obl_substs, impl_substs) } _ => false, }, @@ -290,15 +312,20 @@ impl DeepRejectCtxt { // Impls cannot contain these types as these cannot be named directly. ty::FnDef(..) | ty::Closure(..) | ty::Generator(..) => false, + // Placeholder types don't unify with anything on their own ty::Placeholder(..) | ty::Bound(..) => false, // 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::AsPlaceholder => false, - TreatParams::AsInfer => true, + TreatParams::ForLookup | TreatParams::NextSolverLookup => false, + TreatParams::AsCandidateKey => true, }, + ty::Infer(ty::IntVar(_)) => impl_ty.is_integral(), + + ty::Infer(ty::FloatVar(_)) => impl_ty.is_floating_point(), + ty::Infer(_) => true, // As we're walking the whole type, it may encounter projections @@ -333,10 +360,13 @@ impl DeepRejectCtxt { let k = impl_ct.kind(); match obligation_ct.kind() { ty::ConstKind::Param(_) => match self.treat_obligation_params { - TreatParams::AsPlaceholder => false, - TreatParams::AsInfer => true, + TreatParams::ForLookup | TreatParams::NextSolverLookup => false, + TreatParams::AsCandidateKey => true, }, + // Placeholder consts don't unify with anything on their own + ty::ConstKind::Placeholder(_) => false, + // As we don't necessarily eagerly evaluate constants, // they might unify with any value. ty::ConstKind::Expr(_) | ty::ConstKind::Unevaluated(_) | ty::ConstKind::Error(_) => { @@ -349,7 +379,7 @@ impl DeepRejectCtxt { ty::ConstKind::Infer(_) => true, - ty::ConstKind::Bound(..) | ty::ConstKind::Placeholder(_) => { + ty::ConstKind::Bound(..) => { bug!("unexpected obl const: {:?}", obligation_ct) } } |