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 <david@davidtw.co>
This commit is contained in:
parent
b793f403bd
commit
c665eaeeb0
6 changed files with 86 additions and 57 deletions
|
@ -1,4 +1,4 @@
|
||||||
use crate::ty::subst::{GenericArgKind, SubstsRef};
|
use crate::ty::subst::{GenericArg, GenericArgKind};
|
||||||
use crate::ty::{self, InferConst, Ty, TypeFlags};
|
use crate::ty::{self, InferConst, Ty, TypeFlags};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -81,6 +81,7 @@ impl FlagComputation {
|
||||||
|
|
||||||
&ty::Param(_) => {
|
&ty::Param(_) => {
|
||||||
self.add_flags(TypeFlags::HAS_TY_PARAM);
|
self.add_flags(TypeFlags::HAS_TY_PARAM);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
&ty::Generator(_, ref substs, _) => {
|
&ty::Generator(_, ref substs, _) => {
|
||||||
|
@ -99,14 +100,17 @@ impl FlagComputation {
|
||||||
|
|
||||||
&ty::Bound(debruijn, _) => {
|
&ty::Bound(debruijn, _) => {
|
||||||
self.add_binder(debruijn);
|
self.add_binder(debruijn);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
&ty::Placeholder(..) => {
|
&ty::Placeholder(..) => {
|
||||||
self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
|
self.add_flags(TypeFlags::HAS_TY_PLACEHOLDER);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
&ty::Infer(infer) => {
|
&ty::Infer(infer) => {
|
||||||
self.add_flags(TypeFlags::HAS_TY_INFER);
|
self.add_flags(TypeFlags::HAS_TY_INFER);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
match infer {
|
match infer {
|
||||||
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {}
|
ty::FreshTy(_) | ty::FreshIntTy(_) | ty::FreshFloatTy(_) => {}
|
||||||
|
|
||||||
|
@ -218,17 +222,23 @@ impl FlagComputation {
|
||||||
}
|
}
|
||||||
ty::ConstKind::Infer(infer) => {
|
ty::ConstKind::Infer(infer) => {
|
||||||
self.add_flags(TypeFlags::HAS_CT_INFER);
|
self.add_flags(TypeFlags::HAS_CT_INFER);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
match infer {
|
match infer {
|
||||||
InferConst::Fresh(_) => {}
|
InferConst::Fresh(_) => {}
|
||||||
InferConst::Var(_) => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX),
|
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(_) => {
|
ty::ConstKind::Param(_) => {
|
||||||
self.add_flags(TypeFlags::HAS_CT_PARAM);
|
self.add_flags(TypeFlags::HAS_CT_PARAM);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Placeholder(_) => {
|
ty::ConstKind::Placeholder(_) => {
|
||||||
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
|
self.add_flags(TypeFlags::HAS_CT_PLACEHOLDER);
|
||||||
|
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||||
}
|
}
|
||||||
ty::ConstKind::Value(_) => {}
|
ty::ConstKind::Value(_) => {}
|
||||||
}
|
}
|
||||||
|
@ -243,7 +253,7 @@ impl FlagComputation {
|
||||||
self.add_substs(projection_ty.substs);
|
self.add_substs(projection_ty.substs);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_substs(&mut self, substs: SubstsRef<'_>) {
|
fn add_substs(&mut self, substs: &[GenericArg<'_>]) {
|
||||||
for kind in substs {
|
for kind in substs {
|
||||||
match kind.unpack() {
|
match kind.unpack() {
|
||||||
GenericArgKind::Type(ty) => self.add_ty(ty),
|
GenericArgKind::Type(ty) => self.add_ty(ty),
|
||||||
|
|
|
@ -142,6 +142,13 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||||
self.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND)
|
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`.
|
/// 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 {
|
fn visit_tys_shallow(&self, visit: impl FnMut(Ty<'tcx>) -> bool) -> bool {
|
||||||
pub struct Visitor<F>(F);
|
pub struct Visitor<F>(F);
|
||||||
|
|
|
@ -524,101 +524,106 @@ bitflags! {
|
||||||
// Does this have parameters? Used to determine whether substitution is
|
// Does this have parameters? Used to determine whether substitution is
|
||||||
// required.
|
// required.
|
||||||
/// Does this have [Param]?
|
/// Does this have [Param]?
|
||||||
const HAS_TY_PARAM = 1 << 0;
|
const HAS_TY_PARAM = 1 << 0;
|
||||||
/// Does this have [ReEarlyBound]?
|
/// Does this have [ReEarlyBound]?
|
||||||
const HAS_RE_PARAM = 1 << 1;
|
const HAS_RE_PARAM = 1 << 1;
|
||||||
/// Does this have [ConstKind::Param]?
|
/// 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
|
const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits
|
||||||
| TypeFlags::HAS_RE_PARAM.bits
|
| TypeFlags::HAS_RE_PARAM.bits
|
||||||
| TypeFlags::HAS_CT_PARAM.bits;
|
| TypeFlags::HAS_CT_PARAM.bits;
|
||||||
|
|
||||||
/// Does this have [Infer]?
|
/// Does this have [Infer]?
|
||||||
const HAS_TY_INFER = 1 << 3;
|
const HAS_TY_INFER = 1 << 3;
|
||||||
/// Does this have [ReVar]?
|
/// Does this have [ReVar]?
|
||||||
const HAS_RE_INFER = 1 << 4;
|
const HAS_RE_INFER = 1 << 4;
|
||||||
/// Does this have [ConstKind::Infer]?
|
/// 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
|
/// Does this have inference variables? Used to determine whether
|
||||||
/// inference is required.
|
/// inference is required.
|
||||||
const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits
|
const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits
|
||||||
| TypeFlags::HAS_RE_INFER.bits
|
| TypeFlags::HAS_RE_INFER.bits
|
||||||
| TypeFlags::HAS_CT_INFER.bits;
|
| TypeFlags::HAS_CT_INFER.bits;
|
||||||
|
|
||||||
/// Does this have [Placeholder]?
|
/// Does this have [Placeholder]?
|
||||||
const HAS_TY_PLACEHOLDER = 1 << 6;
|
const HAS_TY_PLACEHOLDER = 1 << 6;
|
||||||
/// Does this have [RePlaceholder]?
|
/// Does this have [RePlaceholder]?
|
||||||
const HAS_RE_PLACEHOLDER = 1 << 7;
|
const HAS_RE_PLACEHOLDER = 1 << 7;
|
||||||
/// Does this have [ConstKind::Placeholder]?
|
/// 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
|
/// `true` if there are "names" of regions and so forth
|
||||||
/// that are local to a particular fn/inferctxt
|
/// 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
|
/// `true` if there are "names" of types and regions and so forth
|
||||||
/// that are local to a particular fn
|
/// that are local to a particular fn
|
||||||
const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits
|
const HAS_FREE_LOCAL_NAMES = TypeFlags::HAS_TY_PARAM.bits
|
||||||
| TypeFlags::HAS_CT_PARAM.bits
|
| TypeFlags::HAS_CT_PARAM.bits
|
||||||
| TypeFlags::HAS_TY_INFER.bits
|
| TypeFlags::HAS_TY_INFER.bits
|
||||||
| TypeFlags::HAS_CT_INFER.bits
|
| TypeFlags::HAS_CT_INFER.bits
|
||||||
| TypeFlags::HAS_TY_PLACEHOLDER.bits
|
| TypeFlags::HAS_TY_PLACEHOLDER.bits
|
||||||
| TypeFlags::HAS_CT_PLACEHOLDER.bits
|
| TypeFlags::HAS_CT_PLACEHOLDER.bits
|
||||||
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
|
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
|
||||||
|
|
||||||
/// Does this have [Projection] or [UnnormalizedProjection]?
|
/// Does this have [Projection] or [UnnormalizedProjection]?
|
||||||
const HAS_TY_PROJECTION = 1 << 10;
|
const HAS_TY_PROJECTION = 1 << 10;
|
||||||
/// Does this have [Opaque]?
|
/// Does this have [Opaque]?
|
||||||
const HAS_TY_OPAQUE = 1 << 11;
|
const HAS_TY_OPAQUE = 1 << 11;
|
||||||
/// Does this have [ConstKind::Unevaluated]?
|
/// Does this have [ConstKind::Unevaluated]?
|
||||||
const HAS_CT_PROJECTION = 1 << 12;
|
const HAS_CT_PROJECTION = 1 << 12;
|
||||||
|
|
||||||
/// Could this type be normalized further?
|
/// Could this type be normalized further?
|
||||||
const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits
|
const HAS_PROJECTION = TypeFlags::HAS_TY_PROJECTION.bits
|
||||||
| TypeFlags::HAS_TY_OPAQUE.bits
|
| TypeFlags::HAS_TY_OPAQUE.bits
|
||||||
| TypeFlags::HAS_CT_PROJECTION.bits;
|
| TypeFlags::HAS_CT_PROJECTION.bits;
|
||||||
|
|
||||||
/// Present if the type belongs in a local type context.
|
/// Present if the type belongs in a local type context.
|
||||||
/// Set for placeholders and inference variables that are not "Fresh".
|
/// 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?
|
/// 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?
|
/// Does this have any region that "appears free" in the type?
|
||||||
/// Basically anything but [ReLateBound] and [ReErased].
|
/// 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
|
/// Does this have any [ReLateBound] regions? Used to check
|
||||||
/// if a global bound is safe to evaluate.
|
/// 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?
|
/// 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,
|
/// Flags representing the nominal content of a type,
|
||||||
/// computed by FlagsComputation. If you add a new nominal
|
/// computed by FlagsComputation. If you add a new nominal
|
||||||
/// flag, it should be added here too.
|
/// flag, it should be added here too.
|
||||||
const NOMINAL_FLAGS = TypeFlags::HAS_TY_PARAM.bits
|
const NOMINAL_FLAGS = TypeFlags::HAS_TY_PARAM.bits
|
||||||
| TypeFlags::HAS_RE_PARAM.bits
|
| TypeFlags::HAS_RE_PARAM.bits
|
||||||
| TypeFlags::HAS_CT_PARAM.bits
|
| TypeFlags::HAS_CT_PARAM.bits
|
||||||
| TypeFlags::HAS_TY_INFER.bits
|
| TypeFlags::HAS_TY_INFER.bits
|
||||||
| TypeFlags::HAS_RE_INFER.bits
|
| TypeFlags::HAS_RE_INFER.bits
|
||||||
| TypeFlags::HAS_CT_INFER.bits
|
| TypeFlags::HAS_CT_INFER.bits
|
||||||
| TypeFlags::HAS_TY_PLACEHOLDER.bits
|
| TypeFlags::HAS_TY_PLACEHOLDER.bits
|
||||||
| TypeFlags::HAS_RE_PLACEHOLDER.bits
|
| TypeFlags::HAS_RE_PLACEHOLDER.bits
|
||||||
| TypeFlags::HAS_CT_PLACEHOLDER.bits
|
| TypeFlags::HAS_CT_PLACEHOLDER.bits
|
||||||
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
|
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits
|
||||||
| TypeFlags::HAS_TY_PROJECTION.bits
|
| TypeFlags::HAS_TY_PROJECTION.bits
|
||||||
| TypeFlags::HAS_TY_OPAQUE.bits
|
| TypeFlags::HAS_TY_OPAQUE.bits
|
||||||
| TypeFlags::HAS_CT_PROJECTION.bits
|
| TypeFlags::HAS_CT_PROJECTION.bits
|
||||||
| TypeFlags::KEEP_IN_LOCAL_TCX.bits
|
| TypeFlags::KEEP_IN_LOCAL_TCX.bits
|
||||||
| TypeFlags::HAS_TY_ERR.bits
|
| TypeFlags::HAS_TY_ERR.bits
|
||||||
| TypeFlags::HAS_FREE_REGIONS.bits
|
| TypeFlags::HAS_FREE_REGIONS.bits
|
||||||
| TypeFlags::HAS_RE_LATE_BOUND.bits
|
| TypeFlags::HAS_RE_LATE_BOUND.bits
|
||||||
| TypeFlags::HAS_RE_ERASED.bits;
|
| TypeFlags::HAS_RE_ERASED.bits
|
||||||
|
| TypeFlags::STILL_FURTHER_SPECIALIZABLE.bits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1623,16 +1623,19 @@ impl RegionKind {
|
||||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||||
flags = flags | TypeFlags::HAS_RE_INFER;
|
flags = flags | TypeFlags::HAS_RE_INFER;
|
||||||
flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
|
flags = flags | TypeFlags::KEEP_IN_LOCAL_TCX;
|
||||||
|
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||||
}
|
}
|
||||||
ty::RePlaceholder(..) => {
|
ty::RePlaceholder(..) => {
|
||||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||||
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
|
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
|
||||||
|
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||||
}
|
}
|
||||||
ty::ReEarlyBound(..) => {
|
ty::ReEarlyBound(..) => {
|
||||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||||
flags = flags | TypeFlags::HAS_RE_PARAM;
|
flags = flags | TypeFlags::HAS_RE_PARAM;
|
||||||
|
flags = flags | TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||||
}
|
}
|
||||||
ty::ReFree { .. } | ty::ReScope { .. } => {
|
ty::ReFree { .. } | ty::ReScope { .. } => {
|
||||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||||
|
|
|
@ -1028,7 +1028,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
|
||||||
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
|
// assume `poly_trait_ref` isn't monomorphic, if it contains any.
|
||||||
let poly_trait_ref =
|
let poly_trait_ref =
|
||||||
selcx.infcx().resolve_vars_if_possible(&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 {
|
} else {
|
||||||
debug!(
|
debug!(
|
||||||
"assemble_candidates_from_impls: not eligible due to default: \
|
"assemble_candidates_from_impls: not eligible due to default: \
|
||||||
|
|
|
@ -127,7 +127,11 @@ fn resolve_associated_item<'tcx>(
|
||||||
// and the obligation is monomorphic, otherwise passes such as
|
// and the obligation is monomorphic, otherwise passes such as
|
||||||
// transmute checking and polymorphic MIR optimizations could
|
// transmute checking and polymorphic MIR optimizations could
|
||||||
// get a result which isn't correct for all monomorphizations.
|
// 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 {
|
if !eligible {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue