update TypeFlags to deal with missing ct substs

This commit is contained in:
lcnr 2021-07-17 18:48:07 +02:00
parent cc47998e28
commit ab9108b70f
44 changed files with 305 additions and 166 deletions

View File

@ -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 {

View File

@ -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);

View File

@ -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);

View File

@ -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 {

View File

@ -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;
}

View File

@ -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 \

View File

@ -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;

View File

@ -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
}

View File

@ -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> {

View File

@ -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);

View File

@ -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);
}

View File

@ -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
}

View File

@ -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!(

View File

@ -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 }

View File

@ -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 })),

View File

@ -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)

View File

@ -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;

View File

@ -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 {

View File

@ -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);
}
}

View File

@ -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 };

View File

@ -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;
}

View File

@ -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,

View File

@ -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;
}

View File

@ -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;
}
}

View File

@ -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)
}

View File

@ -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),

View File

@ -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,

View File

@ -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);

View File

@ -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(

View File

@ -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;
}

View File

@ -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

View File

@ -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);

View File

@ -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.
//

View File

@ -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);

View File

@ -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.

View File

@ -19,94 +19,116 @@ 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;
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_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
| TypeFlags::HAS_TY_INFER.bits
| TypeFlags::HAS_CT_INFER.bits
| TypeFlags::HAS_TY_PLACEHOLDER.bits
| TypeFlags::HAS_CT_PLACEHOLDER.bits
// We consider 'freshened' types and constants
// to depend on a particular fn.
// The freshening process throws away information,
// which can make things unsuitable for use in a global
// cache. Note that there is no 'fresh lifetime' flag -
// freshening replaces all lifetimes with `ReErased`,
// 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;
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
| TypeFlags::HAS_CT_PLACEHOLDER.bits
// We consider 'freshened' types and constants
// to depend on a particular fn.
// The freshening process throws away information,
// which can make things unsuitable for use in a global
// cache. Note that there is no 'fresh lifetime' flag -
// freshening replaces all lifetimes with `ReErased`,
// which is different from how types/const are freshened.
| TypeFlags::HAS_TY_FRESH.bits
| TypeFlags::HAS_CT_FRESH.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;
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;
/// Is an error type/const reachable?
const HAS_ERROR = 1 << 13;
const HAS_ERROR = 1 << 13;
/// 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.
const HAS_RE_LATE_BOUND = 1 << 15;
const HAS_RE_LATE_BOUND = 1 << 15;
/// Does this have any `ReErased` regions?
const HAS_RE_ERASED = 1 << 16;
const HAS_RE_ERASED = 1 << 16;
/// 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 << 17;
///
/// 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`?
const HAS_TY_FRESH = 1 << 18;
const HAS_TY_FRESH = 1 << 18;
/// Does this value have `InferConst::Fresh`?
const HAS_CT_FRESH = 1 << 19;
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;
}
}

View File

@ -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",

View File

@ -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> {

View File

@ -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),

View File

@ -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);
}

View File

@ -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<'_> {

View File

@ -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 {

View File

@ -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() {

View File

@ -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)