mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
update TypeFlags
to deal with missing ct substs
This commit is contained in:
parent
cc47998e28
commit
ab9108b70f
@ -499,7 +499,7 @@ impl DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
|
||||
ty::Adt(def, ..) if !def.is_box() => {
|
||||
// Again, only create type information if full debuginfo is enabled
|
||||
if cx.sess().opts.debuginfo == DebugInfo::Full
|
||||
&& !impl_self_ty.needs_subst()
|
||||
&& !impl_self_ty.needs_subst(cx.tcx)
|
||||
{
|
||||
Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
|
||||
} else {
|
||||
|
@ -1398,7 +1398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
|
||||
LocalRef::UnsizedPlace(_) => bug!("transmute must not involve unsized locals"),
|
||||
LocalRef::Operand(None) => {
|
||||
let dst_layout = bx.layout_of(self.monomorphized_place_ty(dst.as_ref()));
|
||||
assert!(!dst_layout.ty.has_erasable_regions());
|
||||
assert!(!dst_layout.ty.has_erasable_regions(self.cx.tcx()));
|
||||
let place = PlaceRef::alloca(bx, dst_layout);
|
||||
place.storage_live(bx);
|
||||
self.codegen_transmute_into(bx, src, place);
|
||||
|
@ -216,7 +216,7 @@ pub fn codegen_mir<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
|
||||
let mut allocate_local = |local| {
|
||||
let decl = &mir.local_decls[local];
|
||||
let layout = bx.layout_of(fx.monomorphize(decl.ty));
|
||||
assert!(!layout.ty.has_erasable_regions());
|
||||
assert!(!layout.ty.has_erasable_regions(cx.tcx()));
|
||||
|
||||
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
|
||||
debug!("alloc: {:?} (return place) -> place", local);
|
||||
|
@ -470,7 +470,7 @@ impl<'cx, 'tcx> Canonicalizer<'cx, 'tcx> {
|
||||
{
|
||||
let needs_canonical_flags = if canonicalize_region_mode.any() {
|
||||
TypeFlags::NEEDS_INFER |
|
||||
TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
|
||||
TypeFlags::HAS_POTENTIAL_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_xxx_FREE_REGIONS`
|
||||
TypeFlags::HAS_TY_PLACEHOLDER |
|
||||
TypeFlags::HAS_CT_PLACEHOLDER
|
||||
} else {
|
||||
|
@ -146,7 +146,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !t.needs_infer() && !t.has_erasable_regions() {
|
||||
if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
|
||||
return t;
|
||||
}
|
||||
|
||||
|
@ -1656,7 +1656,7 @@ impl<'tcx> LateLintPass<'tcx> for TrivialConstraints {
|
||||
ConstEquate(..) |
|
||||
TypeWellFormedFromEnv(..) => continue,
|
||||
};
|
||||
if predicate.is_global() {
|
||||
if predicate.is_global(cx.tcx) {
|
||||
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
|
||||
lint.build(&format!(
|
||||
"{} bound {} does not depend on any type \
|
||||
|
@ -62,7 +62,7 @@ impl<'tcx> LateLintPass<'tcx> for NoopMethodCall {
|
||||
_ => return,
|
||||
};
|
||||
let substs = cx.typeck_results().node_substs(expr.hir_id);
|
||||
if substs.needs_subst() {
|
||||
if substs.needs_subst(cx.tcx) {
|
||||
// We can't resolve on types that require monomorphization, so we don't handle them if
|
||||
// we need to perfom substitution.
|
||||
return;
|
||||
|
@ -242,6 +242,7 @@ pub struct Body<'tcx> {
|
||||
|
||||
impl<'tcx> Body<'tcx> {
|
||||
pub fn new(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||
source_scopes: IndexVec<SourceScope, SourceScopeData<'tcx>>,
|
||||
@ -284,7 +285,7 @@ impl<'tcx> Body<'tcx> {
|
||||
predecessor_cache: PredecessorCache::new(),
|
||||
is_cyclic: GraphIsCyclicCache::new(),
|
||||
};
|
||||
body.is_polymorphic = body.has_param_types_or_consts();
|
||||
body.is_polymorphic = body.has_param_types_or_consts(tcx);
|
||||
body
|
||||
}
|
||||
|
||||
@ -293,7 +294,10 @@ impl<'tcx> Body<'tcx> {
|
||||
/// The returned MIR contains no `LocalDecl`s (even for the return place) or source scopes. It
|
||||
/// is only useful for testing but cannot be `#[cfg(test)]` because it is used in a different
|
||||
/// crate.
|
||||
pub fn new_cfg_only(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
|
||||
pub fn new_cfg_only(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||
) -> Self {
|
||||
let mut body = Body {
|
||||
phase: MirPhase::Build,
|
||||
source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
|
||||
@ -311,7 +315,7 @@ impl<'tcx> Body<'tcx> {
|
||||
predecessor_cache: PredecessorCache::new(),
|
||||
is_cyclic: GraphIsCyclicCache::new(),
|
||||
};
|
||||
body.is_polymorphic = body.has_param_types_or_consts();
|
||||
body.is_polymorphic = body.has_param_types_or_consts(tcx);
|
||||
body
|
||||
}
|
||||
|
||||
|
@ -12,6 +12,12 @@ use rustc_target::abi::Size;
|
||||
|
||||
use super::ScalarInt;
|
||||
/// An unevaluated, potentially generic, constant.
|
||||
///
|
||||
/// If `substs_` is `None` it means that this anon const
|
||||
/// still has its default substs.
|
||||
///
|
||||
/// We check for all possible substs in `fn default_anon_const_substs`,
|
||||
/// so refer to that check for more info.
|
||||
#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable)]
|
||||
#[derive(Hash, HashStable)]
|
||||
pub struct Unevaluated<'tcx> {
|
||||
|
@ -21,7 +21,9 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
// If there's nothing to erase avoid performing the query at all
|
||||
if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
|
||||
if !value
|
||||
.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_POTENTIAL_FREE_REGIONS)
|
||||
{
|
||||
return value;
|
||||
}
|
||||
debug!("erase_regions({:?})", value);
|
||||
|
@ -34,6 +34,12 @@ impl FlagComputation {
|
||||
result.flags
|
||||
}
|
||||
|
||||
pub fn for_unevaluated_const(uv: ty::Unevaluated<'_>) -> TypeFlags {
|
||||
let mut result = FlagComputation::new();
|
||||
result.add_unevaluated_const(uv);
|
||||
result.flags
|
||||
}
|
||||
|
||||
fn add_flags(&mut self, flags: TypeFlags) {
|
||||
self.flags = self.flags | flags;
|
||||
}
|
||||
@ -91,7 +97,7 @@ impl FlagComputation {
|
||||
&ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
|
||||
|
||||
&ty::Param(_) => {
|
||||
self.add_flags(TypeFlags::HAS_TY_PARAM);
|
||||
self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM);
|
||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
}
|
||||
|
||||
@ -292,7 +298,7 @@ impl FlagComputation {
|
||||
self.add_bound_var(debruijn);
|
||||
}
|
||||
ty::ConstKind::Param(_) => {
|
||||
self.add_flags(TypeFlags::HAS_CT_PARAM);
|
||||
self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM);
|
||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
}
|
||||
ty::ConstKind::Placeholder(_) => {
|
||||
@ -305,8 +311,12 @@ impl FlagComputation {
|
||||
}
|
||||
|
||||
fn add_unevaluated_const(&mut self, ct: ty::Unevaluated<'tcx>) {
|
||||
// TODO
|
||||
self.add_substs(ct.substs_.unwrap());
|
||||
if let Some(substs) = ct.substs_ {
|
||||
self.add_substs(substs);
|
||||
} else {
|
||||
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
|
||||
self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS);
|
||||
}
|
||||
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
|
||||
}
|
||||
|
||||
|
@ -74,8 +74,14 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
self.has_vars_bound_at_or_above(ty::INNERMOST)
|
||||
}
|
||||
|
||||
fn definitely_has_type_flags(&self, tcx: TyCtxt<'tcx>, flags: TypeFlags) -> bool {
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { tcx: Some(tcx), flags }).break_value()
|
||||
== Some(FoundFlags)
|
||||
}
|
||||
|
||||
fn has_type_flags(&self, flags: TypeFlags) -> bool {
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
|
||||
self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value()
|
||||
== Some(FoundFlags)
|
||||
}
|
||||
fn has_projections(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_PROJECTION)
|
||||
@ -86,8 +92,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
fn references_error(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_ERROR)
|
||||
}
|
||||
fn has_param_types_or_consts(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
|
||||
fn has_potential_param_types_or_consts(&self) -> bool {
|
||||
self.has_type_flags(
|
||||
TypeFlags::HAS_KNOWN_TY_PARAM
|
||||
| TypeFlags::HAS_KNOWN_CT_PARAM
|
||||
| TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
|
||||
)
|
||||
}
|
||||
fn has_param_types_or_consts(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
self.definitely_has_type_flags(
|
||||
tcx,
|
||||
TypeFlags::HAS_KNOWN_TY_PARAM | TypeFlags::HAS_KNOWN_CT_PARAM,
|
||||
)
|
||||
}
|
||||
fn has_infer_regions(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_RE_INFER)
|
||||
@ -108,13 +124,18 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
| TypeFlags::HAS_CT_PLACEHOLDER,
|
||||
)
|
||||
}
|
||||
fn needs_subst(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::NEEDS_SUBST)
|
||||
fn potentially_needs_subst(&self) -> bool {
|
||||
self.has_type_flags(
|
||||
TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
|
||||
)
|
||||
}
|
||||
fn needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST)
|
||||
}
|
||||
/// "Free" regions in this context means that it has any region
|
||||
/// that is not (a) erased or (b) late-bound.
|
||||
fn has_free_regions(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
|
||||
fn has_free_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
|
||||
}
|
||||
|
||||
fn has_erased_regions(&self) -> bool {
|
||||
@ -122,15 +143,25 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
|
||||
}
|
||||
|
||||
/// True if there are any un-erased free regions.
|
||||
fn has_erasable_regions(&self) -> bool {
|
||||
self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
|
||||
fn has_erasable_regions(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
|
||||
}
|
||||
|
||||
/// Indicates whether this value definitely references only 'global'
|
||||
/// generic parameters that are the same regardless of what fn we are
|
||||
/// in. This is used for caching.
|
||||
///
|
||||
/// Note that this function is pessimistic and may incorrectly return
|
||||
/// `false`.
|
||||
fn is_known_global(&self) -> bool {
|
||||
!self.has_type_flags(TypeFlags::HAS_POTENTIAL_FREE_LOCAL_NAMES)
|
||||
}
|
||||
|
||||
/// Indicates whether this value references only 'global'
|
||||
/// generic parameters that are the same regardless of what fn we are
|
||||
/// in. This is used for caching.
|
||||
fn is_global(&self) -> bool {
|
||||
!self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
|
||||
fn is_global(&self, tcx: TyCtxt<'tcx>) -> bool {
|
||||
!self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES)
|
||||
}
|
||||
|
||||
/// True if there are any late-bound regions
|
||||
@ -217,6 +248,10 @@ pub trait TypeVisitor<'tcx>: Sized {
|
||||
c.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
uv.super_visit_with(self)
|
||||
}
|
||||
|
||||
fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
p.super_visit_with(self)
|
||||
}
|
||||
@ -369,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// We're only interested in types involving regions
|
||||
if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
|
||||
if ty.flags().intersects(TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
|
||||
ty.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
@ -1078,23 +1113,19 @@ impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
|
||||
struct FoundFlags;
|
||||
|
||||
// FIXME: Optimize for checking for infer flags
|
||||
struct HasTypeFlagsVisitor {
|
||||
struct HasTypeFlagsVisitor<'tcx> {
|
||||
tcx: Option<TyCtxt<'tcx>>,
|
||||
flags: ty::TypeFlags,
|
||||
}
|
||||
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> {
|
||||
type BreakTy = FoundFlags;
|
||||
fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
|
||||
// TypeFlagsVisitor must not look into the default anon const substs
|
||||
// as that would cause cycle errors, but we do care about them for
|
||||
// some flags.
|
||||
//
|
||||
// We therefore have to be very careful here.
|
||||
None
|
||||
self.tcx
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
|
||||
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
debug!(
|
||||
"HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
|
||||
t,
|
||||
@ -1103,6 +1134,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
);
|
||||
if t.flags().intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else if self.tcx.is_some()
|
||||
&& t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
|
||||
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
|
||||
{
|
||||
t.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
@ -1125,6 +1161,26 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
debug!("HasTypeFlagsVisitor: c={:?} c.flags={:?} self.flags={:?}", c, flags, self.flags);
|
||||
if flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else if self.tcx.is_some()
|
||||
&& flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
|
||||
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
|
||||
{
|
||||
c.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
let flags = FlagComputation::for_unevaluated_const(uv);
|
||||
debug!("HasTypeFlagsVisitor: uv={:?} uv.flags={:?} self.flags={:?}", uv, flags, self.flags);
|
||||
if flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else if self.tcx.is_some()
|
||||
&& flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
|
||||
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
|
||||
{
|
||||
uv.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
@ -1138,6 +1194,11 @@ impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
|
||||
);
|
||||
if predicate.inner.flags.intersects(self.flags) {
|
||||
ControlFlow::Break(FoundFlags)
|
||||
} else if self.tcx.is_some()
|
||||
&& predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS)
|
||||
&& self.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS)
|
||||
{
|
||||
predicate.super_visit_with(self)
|
||||
} else {
|
||||
ControlFlow::CONTINUE
|
||||
}
|
||||
|
@ -1727,7 +1727,9 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
|
||||
// Ignore layouts that are done with non-empty environments or
|
||||
// non-monomorphic layouts, as the user only wants to see the stuff
|
||||
// resulting from the final codegen session.
|
||||
if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() {
|
||||
if layout.ty.has_param_types_or_consts(self.tcx)
|
||||
|| !self.param_env.caller_bounds().is_empty()
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@ -1894,7 +1896,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
|
||||
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
|
||||
match tail.kind() {
|
||||
ty::Param(_) | ty::Projection(_) => {
|
||||
debug_assert!(tail.has_param_types_or_consts());
|
||||
debug_assert!(tail.has_param_types_or_consts(tcx));
|
||||
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
|
||||
}
|
||||
_ => bug!(
|
||||
|
@ -1292,7 +1292,7 @@ impl<'tcx> ParamEnv<'tcx> {
|
||||
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
|
||||
|
||||
Reveal::All => {
|
||||
if value.is_global() {
|
||||
if value.is_known_global() {
|
||||
ParamEnvAnd { param_env: self.without_caller_bounds(), value }
|
||||
} else {
|
||||
ParamEnvAnd { param_env: self, value }
|
||||
|
@ -1201,7 +1201,9 @@ pub trait PrettyPrinter<'tcx>:
|
||||
//
|
||||
// FIXME(eddyb) for `--emit=mir`/`-Z dump-mir`, we should provide the
|
||||
// correct `ty::ParamEnv` to allow printing *all* constant values.
|
||||
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_param_types_or_consts() => {
|
||||
(_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..))
|
||||
if !ty.has_potential_param_types_or_consts() =>
|
||||
{
|
||||
let contents = self.tcx().destructure_const(
|
||||
ty::ParamEnv::reveal_all()
|
||||
.and(self.tcx().mk_const(ty::Const { val: ty::ConstKind::Value(ct), ty })),
|
||||
|
@ -1086,6 +1086,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
visitor.visit_unevaluated_const(*self)
|
||||
}
|
||||
|
||||
fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> ControlFlow<V::BreakTy> {
|
||||
if let Some(tcx) = visitor.tcx_for_anon_const_substs() {
|
||||
self.substs(tcx).visit_with(visitor)
|
||||
|
@ -1565,26 +1565,26 @@ impl RegionKind {
|
||||
|
||||
match *self {
|
||||
ty::ReVar(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_RE_INFER;
|
||||
}
|
||||
ty::RePlaceholder(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
|
||||
}
|
||||
ty::ReEarlyBound(..) => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_RE_PARAM;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM;
|
||||
}
|
||||
ty::ReFree { .. } => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
|
||||
}
|
||||
ty::ReEmpty(_) | ty::ReStatic => {
|
||||
flags = flags | TypeFlags::HAS_FREE_REGIONS;
|
||||
flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
|
||||
}
|
||||
ty::ReLateBound(..) => {
|
||||
flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
|
||||
|
@ -486,7 +486,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
|
||||
if !t.needs_subst() {
|
||||
if !t.potentially_needs_subst() {
|
||||
return t;
|
||||
}
|
||||
|
||||
@ -497,10 +497,6 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
fn fold_const(&mut self, c: &'tcx ty::Const<'tcx>) -> &'tcx ty::Const<'tcx> {
|
||||
if !c.needs_subst() {
|
||||
return c;
|
||||
}
|
||||
|
||||
if let ty::ConstKind::Param(p) = c.val {
|
||||
self.const_for_param(p, c)
|
||||
} else {
|
||||
|
@ -171,7 +171,7 @@ impl LivenessResults<'me, 'typeck, 'flow, 'tcx> {
|
||||
for (local, location) in drop_used {
|
||||
if !live_locals.contains(&local) {
|
||||
let local_ty = self.cx.body.local_decls[local].ty;
|
||||
if local_ty.has_free_regions() {
|
||||
if local_ty.has_free_regions(self.cx.typeck.tcx()) {
|
||||
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
debug!("ensure_monomorphic_enough: ty={:?}", ty);
|
||||
if !ty.needs_subst() {
|
||||
if !ty.potentially_needs_subst() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
@ -25,19 +25,8 @@ where
|
||||
Some(self.tcx)
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !c.needs_subst() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
match c.val {
|
||||
ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
|
||||
_ => c.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !ty.needs_subst() {
|
||||
if !ty.potentially_needs_subst() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
@ -54,7 +43,7 @@ where
|
||||
let is_used = unused_params.contains(index).map_or(true, |unused| !unused);
|
||||
// Only recurse when generic parameters in fns, closures and generators
|
||||
// are used and require substitution.
|
||||
match (is_used, subst.needs_subst()) {
|
||||
match (is_used, subst.needs_subst(self.tcx)) {
|
||||
// Just in case there are closures or generators within this subst,
|
||||
// recurse.
|
||||
(true, true) => return subst.super_visit_with(self),
|
||||
@ -77,6 +66,13 @@ where
|
||||
_ => ty.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
|
||||
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
match c.val {
|
||||
ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam),
|
||||
_ => c.super_visit_with(self),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut vis = UsedParamsNeedSubstVisitor { tcx };
|
||||
|
@ -288,7 +288,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
}
|
||||
#[instrument(skip(self))]
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !c.has_param_types_or_consts() {
|
||||
if !c.has_potential_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
@ -321,7 +321,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !ty.has_param_types_or_consts() {
|
||||
if !ty.has_potential_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
@ -363,7 +363,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !c.has_param_types_or_consts() {
|
||||
if !c.has_potential_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
@ -381,7 +381,7 @@ impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
|
||||
|
||||
#[instrument(skip(self))]
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
if !ty.has_param_types_or_consts() {
|
||||
if !ty.has_potential_param_types_or_consts() {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -163,7 +163,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||
|
||||
let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty));
|
||||
let mut body =
|
||||
new_body(source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
|
||||
new_body(tcx, source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
|
||||
|
||||
if ty.is_some() {
|
||||
// The first argument (index 0), but add 1 for the return value.
|
||||
@ -202,6 +202,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option<Ty<'tcx>>)
|
||||
}
|
||||
|
||||
fn new_body<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
source: MirSource<'tcx>,
|
||||
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
|
||||
@ -209,6 +210,7 @@ fn new_body<'tcx>(
|
||||
span: Span,
|
||||
) -> Body<'tcx> {
|
||||
Body::new(
|
||||
tcx,
|
||||
source,
|
||||
basic_blocks,
|
||||
IndexVec::from_elem_n(
|
||||
@ -353,7 +355,14 @@ impl CloneShimBuilder<'tcx> {
|
||||
self.def_id,
|
||||
self.sig.inputs_and_output[0],
|
||||
));
|
||||
new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
|
||||
new_body(
|
||||
self.tcx,
|
||||
source,
|
||||
self.blocks,
|
||||
self.local_decls,
|
||||
self.sig.inputs().len(),
|
||||
self.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn source_info(&self) -> SourceInfo {
|
||||
@ -851,8 +860,14 @@ fn build_call_shim<'tcx>(
|
||||
block(&mut blocks, vec![], TerminatorKind::Resume, true);
|
||||
}
|
||||
|
||||
let mut body =
|
||||
new_body(MirSource::from_instance(instance), blocks, local_decls, sig.inputs().len(), span);
|
||||
let mut body = new_body(
|
||||
tcx,
|
||||
MirSource::from_instance(instance),
|
||||
blocks,
|
||||
local_decls,
|
||||
sig.inputs().len(),
|
||||
span,
|
||||
);
|
||||
|
||||
if let Abi::RustCall = sig.abi {
|
||||
body.spread_arg = Some(Local::new(sig.inputs().len()));
|
||||
@ -917,6 +932,7 @@ pub fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> {
|
||||
|
||||
let source = MirSource::item(ctor_id);
|
||||
let body = new_body(
|
||||
tcx,
|
||||
source,
|
||||
IndexVec::from_elem_n(start_block, 1),
|
||||
local_decls,
|
||||
|
@ -120,7 +120,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||
.predicates_of(def_id.to_def_id())
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||
.filter_map(|(p, _)| if p.is_global(tcx) { Some(*p) } else { None });
|
||||
if traits::impossible_predicates(
|
||||
tcx,
|
||||
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
||||
@ -132,6 +132,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||
trace!("ConstProp starting for {:?}", def_id);
|
||||
|
||||
let dummy_body = &Body::new(
|
||||
tcx,
|
||||
body.source,
|
||||
body.basic_blocks().clone(),
|
||||
body.source_scopes.clone(),
|
||||
@ -468,7 +469,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
/// Returns the value, if any, of evaluating `c`.
|
||||
fn eval_constant(&mut self, c: &Constant<'tcx>, source_info: SourceInfo) -> Option<OpTy<'tcx>> {
|
||||
// FIXME we need to revisit this for #67176
|
||||
if c.needs_subst() {
|
||||
if c.needs_subst(self.tcx) {
|
||||
return None;
|
||||
}
|
||||
|
||||
@ -488,9 +489,9 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}) => true,
|
||||
// Out of backwards compatibility we cannot report hard errors in unused
|
||||
// generic functions using associated constants of the generic parameters.
|
||||
_ => c.literal.needs_subst(),
|
||||
_ => c.literal.needs_subst(*tcx),
|
||||
},
|
||||
ConstantKind::Val(_, ty) => ty.needs_subst(),
|
||||
ConstantKind::Val(_, ty) => ty.needs_subst(*tcx),
|
||||
};
|
||||
if lint_only {
|
||||
// Out of backwards compatibility we cannot report hard errors in unused
|
||||
@ -720,7 +721,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
// FIXME we need to revisit this for #67176
|
||||
if rvalue.needs_subst() {
|
||||
if rvalue.needs_subst(self.tcx) {
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -89,7 +89,7 @@ crate fn mir_callgraph_reachable(
|
||||
// FIXME: A not fully substituted drop shim can cause ICEs if one attempts to
|
||||
// have its MIR built. Likely oli-obk just screwed up the `ParamEnv`s, so this
|
||||
// needs some more analysis.
|
||||
if callee.needs_subst() {
|
||||
if callee.needs_subst(tcx) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
@ -400,7 +400,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
|
||||
debug_assert!(!body.has_free_regions(tcx), "Free regions in MIR for CTFE");
|
||||
|
||||
body
|
||||
}
|
||||
@ -594,7 +594,7 @@ fn inner_optimized_mir(tcx: TyCtxt<'_>, did: LocalDefId) -> Body<'_> {
|
||||
tcx.mir_drops_elaborated_and_const_checked(ty::WithOptConstParam::unknown(did)).steal();
|
||||
run_optimization_passes(tcx, &mut body);
|
||||
|
||||
debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
|
||||
debug_assert!(!body.has_free_regions(tcx), "Free regions in optimized MIR");
|
||||
|
||||
body
|
||||
}
|
||||
@ -621,7 +621,7 @@ fn promoted_mir<'tcx>(
|
||||
run_post_borrowck_cleanup_passes(tcx, body);
|
||||
}
|
||||
|
||||
debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
|
||||
debug_assert!(!promoted.has_free_regions(tcx), "Free regions in promoted MIR");
|
||||
|
||||
tcx.arena.alloc(promoted)
|
||||
}
|
||||
|
@ -992,6 +992,7 @@ pub fn promote_candidates<'tcx>(
|
||||
scope.parent_scope = None;
|
||||
|
||||
let promoted = Body::new(
|
||||
tcx,
|
||||
body.source, // `promoted` gets filled in below
|
||||
IndexVec::new(),
|
||||
IndexVec::from_elem_n(scope, 1),
|
||||
|
@ -239,10 +239,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
|
||||
// The exception is `body.user_type_annotations`, which is used unmodified
|
||||
// by borrow checking.
|
||||
debug_assert!(
|
||||
!(body.local_decls.has_free_regions()
|
||||
|| body.basic_blocks().has_free_regions()
|
||||
|| body.var_debug_info.has_free_regions()
|
||||
|| body.yield_ty().has_free_regions()),
|
||||
!(body.local_decls.has_free_regions(tcx)
|
||||
|| body.basic_blocks().has_free_regions(tcx)
|
||||
|| body.var_debug_info.has_free_regions(tcx)
|
||||
|| body.yield_ty().has_free_regions(tcx)),
|
||||
"Unexpected free regions in MIR: {:?}",
|
||||
body,
|
||||
);
|
||||
@ -755,6 +755,7 @@ fn construct_error<'a, 'tcx>(
|
||||
cfg.terminate(START_BLOCK, source_info, TerminatorKind::Unreachable);
|
||||
|
||||
let mut body = Body::new(
|
||||
tcx,
|
||||
MirSource::item(def.did.to_def_id()),
|
||||
cfg.basic_blocks,
|
||||
source_scopes,
|
||||
@ -843,6 +844,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
|
||||
}
|
||||
|
||||
Body::new(
|
||||
self.tcx,
|
||||
MirSource::item(self.def_id),
|
||||
self.cfg.basic_blocks,
|
||||
self.source_scopes,
|
||||
|
@ -109,7 +109,7 @@ fn get_symbol_hash<'tcx>(
|
||||
// Include the main item-type. Note that, in this case, the
|
||||
// assertions about `needs_subst` may not hold, but this item-type
|
||||
// ought to be the same for every reference anyway.
|
||||
assert!(!item_type.has_erasable_regions());
|
||||
assert!(!item_type.has_erasable_regions(tcx));
|
||||
hcx.while_hashing_spans(false, |hcx| {
|
||||
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
|
||||
item_type.hash_stable(hcx, &mut hasher);
|
||||
|
@ -277,7 +277,8 @@ impl Printer<'tcx> for &mut SymbolMangler<'tcx> {
|
||||
|
||||
// Encode impl generic params if the substitutions contain parameters (implying
|
||||
// polymorphization is enabled) and this isn't an inherent impl.
|
||||
if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
|
||||
if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts(self.tcx))
|
||||
{
|
||||
self = self.path_generic_args(
|
||||
|this| {
|
||||
this.path_append_ns(
|
||||
|
@ -583,7 +583,7 @@ where
|
||||
|
||||
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
|
||||
// We're only interested in types involving regions
|
||||
if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
|
||||
if !ty.flags().intersects(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
|
||||
return ControlFlow::CONTINUE;
|
||||
}
|
||||
|
||||
|
@ -391,7 +391,7 @@ fn orphan_check_trait_ref<'tcx>(
|
||||
) -> Result<(), OrphanCheckErr<'tcx>> {
|
||||
debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
|
||||
|
||||
if trait_ref.needs_infer() && trait_ref.needs_subst() {
|
||||
if trait_ref.needs_infer() && trait_ref.needs_subst(tcx) {
|
||||
bug!(
|
||||
"can't orphan check a trait ref with both params and inference variables {:?}",
|
||||
trait_ref
|
||||
|
@ -91,7 +91,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
let leaf = leaf.subst(tcx, ct.substs);
|
||||
if leaf.has_infer_types_or_consts() {
|
||||
failure_kind = FailureKind::MentionsInfer;
|
||||
} else if leaf.has_param_types_or_consts() {
|
||||
} else if leaf.has_param_types_or_consts(tcx) {
|
||||
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
|
||||
}
|
||||
|
||||
@ -101,7 +101,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
let ty = ty.subst(tcx, ct.substs);
|
||||
if ty.has_infer_types_or_consts() {
|
||||
failure_kind = FailureKind::MentionsInfer;
|
||||
} else if ty.has_param_types_or_consts() {
|
||||
} else if ty.has_param_types_or_consts(tcx) {
|
||||
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
|
||||
}
|
||||
|
||||
@ -158,7 +158,7 @@ pub fn is_const_evaluatable<'cx, 'tcx>(
|
||||
let concrete =
|
||||
infcx.const_eval_resolve(param_env, ty::Unevaluated::new(def, substs), Some(span));
|
||||
|
||||
if concrete.is_ok() && substs.has_param_types_or_consts() {
|
||||
if concrete.is_ok() && substs.has_param_types_or_consts(infcx.tcx) {
|
||||
match infcx.tcx.def_kind(def.did) {
|
||||
DefKind::AnonConst => {
|
||||
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(def);
|
||||
|
@ -669,7 +669,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||
stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
|
||||
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
|
||||
let infcx = self.selcx.infcx();
|
||||
if obligation.predicate.is_global() {
|
||||
if obligation.predicate.is_known_global() {
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
//
|
||||
@ -728,7 +728,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> {
|
||||
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
|
||||
let tcx = self.selcx.tcx();
|
||||
|
||||
if obligation.predicate.is_global() {
|
||||
if obligation.predicate.is_global(tcx) {
|
||||
// no type variables present, can use evaluation for better caching.
|
||||
// FIXME: consider caching errors too.
|
||||
//
|
||||
|
@ -450,7 +450,7 @@ fn subst_and_check_impossible_predicates<'tcx>(
|
||||
debug!("subst_and_check_impossible_predicates(key={:?})", key);
|
||||
|
||||
let mut predicates = tcx.predicates_of(key.0).instantiate(tcx, key.1).predicates;
|
||||
predicates.retain(|predicate| !predicate.needs_subst());
|
||||
predicates.retain(|predicate| !predicate.needs_subst(tcx));
|
||||
let result = impossible_predicates(tcx, predicates);
|
||||
|
||||
debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
|
||||
|
@ -544,7 +544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
},
|
||||
|
||||
ty::PredicateKind::TypeOutlives(pred) => {
|
||||
if pred.0.is_global() {
|
||||
if pred.0.is_known_global() {
|
||||
Ok(EvaluatedToOk)
|
||||
} else {
|
||||
Ok(EvaluatedToOkModuloRegions)
|
||||
@ -692,8 +692,12 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
debug!(?obligation, "evaluate_trait_predicate_recursively");
|
||||
|
||||
if !self.intercrate
|
||||
&& obligation.is_global()
|
||||
&& obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
|
||||
&& obligation.is_global(self.tcx())
|
||||
&& obligation
|
||||
.param_env
|
||||
.caller_bounds()
|
||||
.iter()
|
||||
.all(|bound| bound.needs_subst(self.tcx()))
|
||||
{
|
||||
// If a param env has no global bounds, global obligations do not
|
||||
// depend on its particular value in order to work, so we can clear
|
||||
@ -1452,7 +1456,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||
// the param_env so that it can be given the lowest priority. See
|
||||
// #50825 for the motivation for this.
|
||||
let is_global =
|
||||
|cand: &ty::PolyTraitRef<'_>| cand.is_global() && !cand.has_late_bound_regions();
|
||||
|cand: &ty::PolyTraitRef<'_>| cand.is_known_global() && !cand.has_late_bound_regions();
|
||||
|
||||
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
|
||||
// and `DiscriminantKindCandidate` to anything else.
|
||||
|
@ -19,15 +19,15 @@ bitflags! {
|
||||
// Does this have parameters? Used to determine whether substitution is
|
||||
// required.
|
||||
/// Does this have `Param`?
|
||||
const HAS_TY_PARAM = 1 << 0;
|
||||
const HAS_KNOWN_TY_PARAM = 1 << 0;
|
||||
/// Does this have `ReEarlyBound`?
|
||||
const HAS_RE_PARAM = 1 << 1;
|
||||
const HAS_KNOWN_RE_PARAM = 1 << 1;
|
||||
/// Does this have `ConstKind::Param`?
|
||||
const HAS_CT_PARAM = 1 << 2;
|
||||
const HAS_KNOWN_CT_PARAM = 1 << 2;
|
||||
|
||||
const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits
|
||||
| TypeFlags::HAS_RE_PARAM.bits
|
||||
| TypeFlags::HAS_CT_PARAM.bits;
|
||||
const KNOWN_NEEDS_SUBST = TypeFlags::HAS_KNOWN_TY_PARAM.bits
|
||||
| TypeFlags::HAS_KNOWN_RE_PARAM.bits
|
||||
| TypeFlags::HAS_KNOWN_CT_PARAM.bits;
|
||||
|
||||
/// Does this have `Infer`?
|
||||
const HAS_TY_INFER = 1 << 3;
|
||||
@ -51,12 +51,12 @@ bitflags! {
|
||||
|
||||
/// `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_KNOWN_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
|
||||
const HAS_KNOWN_FREE_LOCAL_NAMES = TypeFlags::HAS_KNOWN_TY_PARAM.bits
|
||||
| TypeFlags::HAS_KNOWN_CT_PARAM.bits
|
||||
| TypeFlags::HAS_TY_INFER.bits
|
||||
| TypeFlags::HAS_CT_INFER.bits
|
||||
| TypeFlags::HAS_TY_PLACEHOLDER.bits
|
||||
@ -70,7 +70,10 @@ bitflags! {
|
||||
// which is different from how types/const are freshened.
|
||||
| TypeFlags::HAS_TY_FRESH.bits
|
||||
| TypeFlags::HAS_CT_FRESH.bits
|
||||
| TypeFlags::HAS_FREE_LOCAL_REGIONS.bits;
|
||||
| TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits;
|
||||
|
||||
const HAS_POTENTIAL_FREE_LOCAL_NAMES = TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES.bits
|
||||
| TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
|
||||
|
||||
/// Does this have `Projection`?
|
||||
const HAS_TY_PROJECTION = 1 << 10;
|
||||
@ -89,7 +92,10 @@ bitflags! {
|
||||
|
||||
/// Does this have any region that "appears free" in the type?
|
||||
/// Basically anything but `ReLateBound` and `ReErased`.
|
||||
const HAS_FREE_REGIONS = 1 << 14;
|
||||
const HAS_KNOWN_FREE_REGIONS = 1 << 14;
|
||||
|
||||
const HAS_POTENTIAL_FREE_REGIONS = TypeFlags::HAS_KNOWN_FREE_REGIONS.bits
|
||||
| TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
|
||||
|
||||
/// Does this have any `ReLateBound` regions? Used to check
|
||||
/// if a global bound is safe to evaluate.
|
||||
@ -100,6 +106,9 @@ bitflags! {
|
||||
|
||||
/// Does this value have parameters/placeholders/inference variables which could be
|
||||
/// replaced later, in a way that would change the results of `impl` specialization?
|
||||
///
|
||||
/// Note that this flag being set is not a guarantee, as it is also
|
||||
/// set if there are any anon consts with unknown default substs.
|
||||
const STILL_FURTHER_SPECIALIZABLE = 1 << 17;
|
||||
|
||||
/// Does this value have `InferTy::FreshTy/FreshIntTy/FreshFloatTy`?
|
||||
@ -107,6 +116,19 @@ bitflags! {
|
||||
|
||||
/// Does this value have `InferConst::Fresh`?
|
||||
const HAS_CT_FRESH = 1 << 19;
|
||||
|
||||
/// Does this value have unknown default anon const substs.
|
||||
///
|
||||
/// For more details refer to...
|
||||
/// FIXME(@lcnr): ask me for now, still have to write all of this.
|
||||
const HAS_UNKNOWN_DEFAULT_CONST_SUBSTS = 1 << 20;
|
||||
/// Flags which can be influenced by default anon const substs.
|
||||
const MAY_NEED_DEFAULT_CONST_SUBSTS = TypeFlags::HAS_KNOWN_RE_PARAM.bits
|
||||
| TypeFlags::HAS_KNOWN_TY_PARAM.bits
|
||||
| TypeFlags::HAS_KNOWN_CT_PARAM.bits
|
||||
| TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS.bits
|
||||
| TypeFlags::HAS_KNOWN_FREE_REGIONS.bits;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2204,7 +2204,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
|
||||
self.prohibit_generics(path.segments);
|
||||
// Try to evaluate any array length constants.
|
||||
let normalized_ty = self.normalize_ty(span, tcx.at(span).type_of(def_id));
|
||||
if forbid_generic && normalized_ty.needs_subst() {
|
||||
if forbid_generic && normalized_ty.needs_subst(tcx) {
|
||||
let mut err = tcx.sess.struct_span_err(
|
||||
path.span,
|
||||
"generic `Self` types are currently not permitted in anonymous constants",
|
||||
|
@ -239,7 +239,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
self.tag(),
|
||||
);
|
||||
|
||||
if Self::can_contain_user_lifetime_bounds((substs, user_self_ty)) {
|
||||
if self.can_contain_user_lifetime_bounds((substs, user_self_ty)) {
|
||||
let canonicalized = self.infcx.canonicalize_user_type_annotation(UserType::TypeOf(
|
||||
def_id,
|
||||
UserSubsts { substs, user_self_ty },
|
||||
@ -481,7 +481,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
let ty = self.to_ty(ast_ty);
|
||||
debug!("to_ty_saving_user_provided_ty: ty={:?}", ty);
|
||||
|
||||
if Self::can_contain_user_lifetime_bounds(ty) {
|
||||
if self.can_contain_user_lifetime_bounds(ty) {
|
||||
let c_ty = self.infcx.canonicalize_response(UserType::Ty(ty));
|
||||
debug!("to_ty_saving_user_provided_ty: c_ty={:?}", c_ty);
|
||||
self.typeck_results.borrow_mut().user_provided_types_mut().insert(ast_ty.hir_id, c_ty);
|
||||
@ -526,11 +526,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
// reader, although I have my doubts). Also pass in types with inference
|
||||
// types, because they may be repeated. Other sorts of things are already
|
||||
// sufficiently enforced with erased regions. =)
|
||||
fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
|
||||
fn can_contain_user_lifetime_bounds<T>(&self, t: T) -> bool
|
||||
where
|
||||
T: TypeFoldable<'tcx>,
|
||||
{
|
||||
t.has_free_regions() || t.has_projections() || t.has_infer_types()
|
||||
t.has_free_regions(self.tcx) || t.has_projections() || t.has_infer_types()
|
||||
}
|
||||
|
||||
pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
|
||||
|
@ -746,7 +746,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
// Ignore dependent defaults -- that is, where the default of one type
|
||||
// parameter includes another (e.g., `<T, U = T>`). In those cases, we can't
|
||||
// be sure if it will error or not as user might always specify the other.
|
||||
if !ty.needs_subst() {
|
||||
if !ty.needs_subst(tcx) {
|
||||
fcx.register_wf_obligation(
|
||||
ty.into(),
|
||||
tcx.def_span(param.def_id),
|
||||
@ -762,7 +762,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
// for `struct Foo<const N: usize, const M: usize = { 1 - 2 }>`
|
||||
// we should eagerly error.
|
||||
let default_ct = tcx.const_param_default(param.def_id);
|
||||
if !default_ct.needs_subst() {
|
||||
if !default_ct.needs_subst(tcx) {
|
||||
fcx.register_wf_obligation(
|
||||
default_ct.into(),
|
||||
tcx.def_span(param.def_id),
|
||||
@ -796,7 +796,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
if is_our_default(param) {
|
||||
let default_ty = tcx.type_of(param.def_id);
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ty.needs_subst() {
|
||||
if !default_ty.needs_subst(tcx) {
|
||||
// ... then substitute it with the default.
|
||||
return default_ty.into();
|
||||
}
|
||||
@ -809,7 +809,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
if is_our_default(param) {
|
||||
let default_ct = tcx.const_param_default(param.def_id);
|
||||
// ... and it's not a dependent default, ...
|
||||
if !default_ct.needs_subst() {
|
||||
if !default_ct.needs_subst(tcx) {
|
||||
// ... then substitute it with the default.
|
||||
return default_ct.into();
|
||||
}
|
||||
@ -858,7 +858,7 @@ fn check_where_clauses<'tcx, 'fcx>(
|
||||
let substituted_pred = pred.subst(tcx, substs);
|
||||
// Don't check non-defaulted params, dependent defaults (including lifetimes)
|
||||
// or preds with multiple params.
|
||||
if substituted_pred.has_param_types_or_consts()
|
||||
if substituted_pred.has_param_types_or_consts(tcx)
|
||||
|| param_count.params.len() > 1
|
||||
|| has_region
|
||||
{
|
||||
@ -1380,7 +1380,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
|
||||
for obligation in implied_obligations {
|
||||
let pred = obligation.predicate;
|
||||
// Match the existing behavior.
|
||||
if pred.is_global() && !pred.has_late_bound_regions() {
|
||||
if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
|
||||
let pred = fcx.normalize_associated_types_in(span, pred);
|
||||
let obligation = traits::Obligation::new(
|
||||
traits::ObligationCause::new(span, id, traits::TrivialBound),
|
||||
|
@ -130,7 +130,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
|
||||
fn write_ty_to_typeck_results(&mut self, hir_id: hir::HirId, ty: Ty<'tcx>) {
|
||||
debug!("write_ty_to_typeck_results({:?}, {:?})", hir_id, ty);
|
||||
assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
|
||||
assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions(self.tcx()));
|
||||
self.typeck_results.node_types_mut().insert(hir_id, ty);
|
||||
}
|
||||
|
||||
|
@ -275,7 +275,16 @@ fn get_path_containing_arg_in_pat<'hir>(
|
||||
}
|
||||
|
||||
pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
|
||||
InternalSubsts::identity_for_item(tcx, def_id)
|
||||
let substs = InternalSubsts::identity_for_item(tcx, def_id);
|
||||
// We only expect substs with the following type flags as default substs.
|
||||
//
|
||||
// Getting this wrong can lead to ICE and unsoundness, so we assert it here.
|
||||
for arg in substs.iter().flat_map(|s| s.walk(tcx)) {
|
||||
let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS
|
||||
| ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE;
|
||||
assert!(!arg.has_type_flags(!allowed_flags));
|
||||
}
|
||||
substs
|
||||
}
|
||||
|
||||
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
|
||||
|
@ -363,7 +363,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tc
|
||||
match predicate.kind().skip_binder() {
|
||||
// Global predicates are either always true or always false, so we
|
||||
// are fine to specialize on.
|
||||
_ if predicate.is_global() => (),
|
||||
_ if predicate.is_global(tcx) => (),
|
||||
// We allow specializing on explicitly marked traits with no associated
|
||||
// items.
|
||||
ty::PredicateKind::Trait(ty::TraitPredicate {
|
||||
|
@ -117,7 +117,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
|
||||
let fn_def_id = cx.tcx.hir().local_def_id(hir_id);
|
||||
|
||||
let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter())
|
||||
.filter(|p| !p.is_global())
|
||||
.filter(|p| !p.is_global(cx.tcx))
|
||||
.filter_map(|obligation| {
|
||||
// Note that we do not want to deal with qualified predicates here.
|
||||
match obligation.predicate.kind().no_bound_vars() {
|
||||
|
@ -1581,7 +1581,7 @@ pub fn fn_has_unsatisfiable_preds(cx: &LateContext<'_>, did: DefId) -> bool {
|
||||
.predicates_of(did)
|
||||
.predicates
|
||||
.iter()
|
||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||
.filter_map(|(p, _)| if p.is_global(cx.tcx) { Some(*p) } else { None });
|
||||
traits::impossible_predicates(
|
||||
cx.tcx,
|
||||
traits::elaborate_predicates(cx.tcx, predicates)
|
||||
|
Loading…
Reference in New Issue
Block a user