From c665eaeeb05d2149cd3ecfd8af62b6af7858a6a2 Mon Sep 17 00:00:00 2001 From: David Wood Date: Wed, 1 Apr 2020 16:20:27 +0100 Subject: [PATCH] add `STILL_FURTHER_SPECIALIZABLE` flag This commit adds a STILL_FURTHER_SPECIALIZABLE flag to `TypeFlags` which replaces `needs_infer` and `needs_subst` in `Instance::resolve` and `assemble_candidates_from_impls.` Signed-off-by: David Wood --- src/librustc_middle/ty/flags.rs | 16 ++- src/librustc_middle/ty/fold.rs | 7 ++ src/librustc_middle/ty/mod.rs | 109 +++++++++--------- src/librustc_middle/ty/sty.rs | 3 + .../traits/project.rs | 2 +- src/librustc_ty/instance.rs | 6 +- 6 files changed, 86 insertions(+), 57 deletions(-) diff --git a/src/librustc_middle/ty/flags.rs b/src/librustc_middle/ty/flags.rs index 5243e1fbf579b..99a6511b297ac 100644 --- a/src/librustc_middle/ty/flags.rs +++ b/src/librustc_middle/ty/flags.rs @@ -1,4 +1,4 @@ -use crate::ty::subst::{GenericArgKind, SubstsRef}; +use crate::ty::subst::{GenericArg, GenericArgKind}; use crate::ty::{self, InferConst, Ty, TypeFlags}; #[derive(Debug)] @@ -81,6 +81,7 @@ impl FlagComputation { &ty::Param(_) => { self.add_flags(TypeFlags::HAS_TY_PARAM); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } &ty::Generator(_, ref substs, _) => { @@ -99,14 +100,17 @@ impl FlagComputation { &ty::Bound(debruijn, _) => { self.add_binder(debruijn); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } &ty::Placeholder(..) => { self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } &ty::Infer(infer) => { self.add_flags(TypeFlags::HAS_TY_INFER); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {} @@ -218,17 +222,23 @@ impl FlagComputation { } ty::ConstKind::Infer(infer) => { self.add_flags(TypeFlags::HAS_CT_INFER); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); match infer { InferConst::Fresh(_) => {} InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX), } } - ty::ConstKind::Bound(debruijn, _) => self.add_binder(debruijn), + ty::ConstKind::Bound(debruijn, _) => { + self.add_binder(debruijn); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); + } ty::ConstKind::Param(_) => { self.add_flags(TypeFlags::HAS_CT_PARAM); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Placeholder(_) => { self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER); + self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE); } ty::ConstKind::Value(_) => {} } @@ -243,7 +253,7 @@ impl FlagComputation { self.add_substs(projection_ty.substs); } - fn add_substs(&mut self, substs: SubstsRef<'_>) { + fn add_substs(&mut self, substs: &[GenericArg<'_>]) { for kind in substs { match kind.unpack() { GenericArgKind::Type(ty) => self.add_ty(ty), diff --git a/src/librustc_middle/ty/fold.rs b/src/librustc_middle/ty/fold.rs index 3f4f2407f1e6e..a3d611a132592 100644 --- a/src/librustc_middle/ty/fold.rs +++ b/src/librustc_middle/ty/fold.rs @@ -142,6 +142,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone { self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND) } + /// Indicates whether this value still has parameters/placeholders/inference variables + /// which could be replaced later, in a way that would change the results of `impl` + /// specialization. + fn still_further_specializable(&self) -> bool { + self.has_type_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE) + } + /// A visitor that does not recurse into types, works like `fn walk_shallow` in `Ty`. fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool { pub struct Visitor(F); diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 43982439d47c8..2585de07a5b4f 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -524,101 +524,106 @@ bitflags! { // Does this have parameters? Used to determine whether substitution is // required. /// Does this have [Param]? - const HAS_TY_PARAM = 1 << 0; + const HAS_TY_PARAM = 1 << 0; /// Does this have [ReEarlyBound]? - const HAS_RE_PARAM = 1 << 1; + const HAS_RE_PARAM = 1 << 1; /// Does this have [ConstKind::Param]? - const HAS_CT_PARAM = 1 << 2; + const HAS_CT_PARAM = 1 << 2; - const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_RE_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits; + const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits + | TypeFlags::HAS_RE_PARAM.bits + | TypeFlags::HAS_CT_PARAM.bits; /// Does this have [Infer]? - const HAS_TY_INFER = 1 << 3; + const HAS_TY_INFER = 1 << 3; /// Does this have [ReVar]? - const HAS_RE_INFER = 1 << 4; + const HAS_RE_INFER = 1 << 4; /// Does this have [ConstKind::Infer]? - const HAS_CT_INFER = 1 << 5; + const HAS_CT_INFER = 1 << 5; /// Does this have inference variables? Used to determine whether /// inference is required. - const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_RE_INFER.bits - | TypeFlags::HAS_CT_INFER.bits; + const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_RE_INFER.bits + | TypeFlags::HAS_CT_INFER.bits; /// Does this have [Placeholder]? - const HAS_TY_PLACEHOLDER = 1 << 6; + const HAS_TY_PLACEHOLDER = 1 << 6; /// Does this have [RePlaceholder]? - const HAS_RE_PLACEHOLDER = 1 << 7; + const HAS_RE_PLACEHOLDER = 1 << 7; /// Does this have [ConstKind::Placeholder]? - const HAS_CT_PLACEHOLDER = 1 << 8; + const HAS_CT_PLACEHOLDER = 1 << 8; /// `true` if there are "names" of regions and so forth /// that are local to a particular fn/inferctxt - const HAS_FREE_LOCAL_REGIONS = 1 << 9; + const HAS_FREE_LOCAL_REGIONS = 1 << 9; /// `true` if there are "names" of types and regions and so forth /// that are local to a particular fn - const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits - | TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_CT_INFER.bits - | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits - | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; + const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits + | TypeFlags::HAS_CT_PARAM.bits + | TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_CT_INFER.bits + | TypeFlags::HAS_TY_PLACEHOLDER.bits + | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits; /// Does this have [Projection] or [UnnormalizedProjection]? - const HAS_TY_PROJECTION = 1 << 10; + const HAS_TY_PROJECTION = 1 << 10; /// Does this have [Opaque]? - const HAS_TY_OPAQUE = 1 << 11; + const HAS_TY_OPAQUE = 1 << 11; /// Does this have [ConstKind::Unevaluated]? - const HAS_CT_PROJECTION = 1 << 12; + const HAS_CT_PROJECTION = 1 << 12; /// Could this type be normalized further? - const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits - | TypeFlags::HAS_TY_OPAQUE.bits - | TypeFlags::HAS_CT_PROJECTION.bits; + const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits + | TypeFlags::HAS_TY_OPAQUE.bits + | TypeFlags::HAS_CT_PROJECTION.bits; /// Present if the type belongs in a local type context. /// Set for placeholders and inference variables that are not "Fresh". - const KEEP_IN_LOCAL_TCX = 1 << 13; + const KEEP_IN_LOCAL_TCX = 1 << 13; /// Is an error type reachable? - const HAS_TY_ERR = 1 << 14; + const HAS_TY_ERR = 1 << 14; /// Does this have any region that "appears free" in the type? /// Basically anything but [ReLateBound] and [ReErased]. - const HAS_FREE_REGIONS = 1 << 15; + const HAS_FREE_REGIONS = 1 << 15; /// Does this have any [ReLateBound] regions? Used to check /// if a global bound is safe to evaluate. - const HAS_RE_LATE_BOUND = 1 << 16; + const HAS_RE_LATE_BOUND = 1 << 16; /// Does this have any [ReErased] regions? - const HAS_RE_ERASED = 1 << 17; + const HAS_RE_ERASED = 1 << 17; + + /// Does this value have parameters/placeholders/inference variables which could be + /// replaced later, in a way that would change the results of `impl` specialization? + const STILL_FURTHER_SPECIALIZABLE = 1 << 18; /// Flags representing the nominal content of a type, /// computed by FlagsComputation. If you add a new nominal /// flag, it should be added here too. - const NOMINAL_FLAGS = TypeFlags::HAS_TY_PARAM.bits - | TypeFlags::HAS_RE_PARAM.bits - | TypeFlags::HAS_CT_PARAM.bits - | TypeFlags::HAS_TY_INFER.bits - | TypeFlags::HAS_RE_INFER.bits - | TypeFlags::HAS_CT_INFER.bits - | TypeFlags::HAS_TY_PLACEHOLDER.bits - | TypeFlags::HAS_RE_PLACEHOLDER.bits - | TypeFlags::HAS_CT_PLACEHOLDER.bits - | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits - | TypeFlags::HAS_TY_PROJECTION.bits - | TypeFlags::HAS_TY_OPAQUE.bits - | TypeFlags::HAS_CT_PROJECTION.bits - | TypeFlags::KEEP_IN_LOCAL_TCX.bits - | TypeFlags::HAS_TY_ERR.bits - | TypeFlags::HAS_FREE_REGIONS.bits - | TypeFlags::HAS_RE_LATE_BOUND.bits - | TypeFlags::HAS_RE_ERASED.bits; + const NOMINAL_FLAGS = TypeFlags::HAS_TY_PARAM.bits + | TypeFlags::HAS_RE_PARAM.bits + | TypeFlags::HAS_CT_PARAM.bits + | TypeFlags::HAS_TY_INFER.bits + | TypeFlags::HAS_RE_INFER.bits + | TypeFlags::HAS_CT_INFER.bits + | TypeFlags::HAS_TY_PLACEHOLDER.bits + | TypeFlags::HAS_RE_PLACEHOLDER.bits + | TypeFlags::HAS_CT_PLACEHOLDER.bits + | TypeFlags::HAS_FREE_LOCAL_REGIONS.bits + | TypeFlags::HAS_TY_PROJECTION.bits + | TypeFlags::HAS_TY_OPAQUE.bits + | TypeFlags::HAS_CT_PROJECTION.bits + | TypeFlags::KEEP_IN_LOCAL_TCX.bits + | TypeFlags::HAS_TY_ERR.bits + | TypeFlags::HAS_FREE_REGIONS.bits + | TypeFlags::HAS_RE_LATE_BOUND.bits + | TypeFlags::HAS_RE_ERASED.bits + | TypeFlags::STILL_FURTHER_SPECIALIZABLE.bits; } } diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs index 57df50dc1a05d..e98ea097c901e 100644 --- a/src/librustc_middle/ty/sty.rs +++ b/src/librustc_middle/ty/sty.rs @@ -1623,16 +1623,19 @@ impl RegionKind { flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_INFER; flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX; + flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE; } ty::RePlaceholder(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PLACEHOLDER; + flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE; } ty::ReEarlyBound(..) => { flags = flags | TypeFlags::HAS_FREE_REGIONS; flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS; flags = flags | TypeFlags::HAS_RE_PARAM; + flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE; } ty::ReFree { .. } | ty::ReScope { .. } => { flags = flags | TypeFlags::HAS_FREE_REGIONS; diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index aae0d46756331..3057b79547dc0 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -1028,7 +1028,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // assume `poly_trait_ref` isn't monomorphic, if it contains any. let poly_trait_ref = selcx.infcx().resolve_vars_if_possible(&poly_trait_ref); - !poly_trait_ref.needs_infer() && !poly_trait_ref.needs_subst() + !poly_trait_ref.still_further_specializable() } else { debug!( "assemble_candidates_from_impls: not eligible due to default: \ diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 47c4b1c41cdbd..e845cc9a15869 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -127,7 +127,11 @@ fn resolve_associated_item<'tcx>( // and the obligation is monomorphic, otherwise passes such as // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. - if param_env.reveal == Reveal::All { !trait_ref.needs_subst() } else { false } + if param_env.reveal == Reveal::All { + !trait_ref.still_further_specializable() + } else { + false + } }; if !eligible {