diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs index 8375d4c7ca5..2e8a9604017 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs @@ -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 { diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 58ce31e0c4c..673d348a2a8 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -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); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index 3bbc481b610..e2edd448267 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -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); diff --git a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs index 448dd662348..c6e150d114c 100644 --- a/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs +++ b/compiler/rustc_infer/src/infer/canonical/canonicalizer.rs @@ -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 { diff --git a/compiler/rustc_infer/src/infer/freshen.rs b/compiler/rustc_infer/src/infer/freshen.rs index 4af1bdf97a7..c40e409891b 100644 --- a/compiler/rustc_infer/src/infer/freshen.rs +++ b/compiler/rustc_infer/src/infer/freshen.rs @@ -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; } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index b4f11a8a044..8f848f54aad 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -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 \ diff --git a/compiler/rustc_lint/src/noop_method_call.rs b/compiler/rustc_lint/src/noop_method_call.rs index 479cc00199f..908d847915f 100644 --- a/compiler/rustc_lint/src/noop_method_call.rs +++ b/compiler/rustc_lint/src/noop_method_call.rs @@ -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; diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs index 00c2f0a0299..6a7758bedfb 100644 --- a/compiler/rustc_middle/src/mir/mod.rs +++ b/compiler/rustc_middle/src/mir/mod.rs @@ -242,6 +242,7 @@ pub struct Body<'tcx> { impl<'tcx> Body<'tcx> { pub fn new( + tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, basic_blocks: IndexVec>, source_scopes: IndexVec>, @@ -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>) -> Self { + pub fn new_cfg_only( + tcx: TyCtxt<'tcx>, + basic_blocks: IndexVec>, + ) -> 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 } diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs index ab2c57ac605..174c35dbc71 100644 --- a/compiler/rustc_middle/src/ty/consts/kind.rs +++ b/compiler/rustc_middle/src/ty/consts/kind.rs @@ -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> { diff --git a/compiler/rustc_middle/src/ty/erase_regions.rs b/compiler/rustc_middle/src/ty/erase_regions.rs index 759d1a017aa..63eb55ed1a6 100644 --- a/compiler/rustc_middle/src/ty/erase_regions.rs +++ b/compiler/rustc_middle/src/ty/erase_regions.rs @@ -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); diff --git a/compiler/rustc_middle/src/ty/flags.rs b/compiler/rustc_middle/src/ty/flags.rs index 89cba4aab83..41c2447cfc5 100644 --- a/compiler/rustc_middle/src/ty/flags.rs +++ b/compiler/rustc_middle/src/ty/flags.rs @@ -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); } diff --git a/compiler/rustc_middle/src/ty/fold.rs b/compiler/rustc_middle/src/ty/fold.rs index 6e70e8ddaed..0c5e292e6eb 100644 --- a/compiler/rustc_middle/src/ty/fold.rs +++ b/compiler/rustc_middle/src/ty/fold.rs @@ -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 { + uv.super_visit_with(self) + } + fn visit_predicate(&mut self, p: ty::Predicate<'tcx>) -> ControlFlow { p.super_visit_with(self) } @@ -369,7 +404,7 @@ impl<'tcx> TyCtxt<'tcx> { fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { // 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>, 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> { - // 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 { + fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow { 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 { + 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 } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 8f90c7a8845..6761fbaf536 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -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!( diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 62e093581b8..eccc1ebd805 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -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 } diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 13222363096..5c3da507e14 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -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 })), diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index fe7d46240cb..369dfaf32a0 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -1086,6 +1086,10 @@ impl<'tcx> TypeFoldable<'tcx> for ty::Unevaluated<'tcx> { } } + fn visit_with>(&self, visitor: &mut V) -> ControlFlow { + visitor.visit_unevaluated_const(*self) + } + fn super_visit_with>(&self, visitor: &mut V) -> ControlFlow { if let Some(tcx) = visitor.tcx_for_anon_const_substs() { self.substs(tcx).visit_with(visitor) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 8e0a2d4a28d..8b893b779c0 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -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; diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs index 84ec2e76c0b..2438d1a1602 100644 --- a/compiler/rustc_middle/src/ty/subst.rs +++ b/compiler/rustc_middle/src/ty/subst.rs @@ -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 { diff --git a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs index e411f1dc108..566c11811e6 100644 --- a/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs +++ b/compiler/rustc_mir/src/borrow_check/type_check/liveness/trace.rs @@ -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); } } diff --git a/compiler/rustc_mir/src/interpret/util.rs b/compiler/rustc_mir/src/interpret/util.rs index b9d6e002e2d..37c13c2d42a 100644 --- a/compiler/rustc_mir/src/interpret/util.rs +++ b/compiler/rustc_mir/src/interpret/util.rs @@ -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 { - 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 { - 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 { + match c.val { + ty::ConstKind::Param(..) => ControlFlow::Break(FoundParam), + _ => c.super_visit_with(self), + } + } } let mut vis = UsedParamsNeedSubstVisitor { tcx }; diff --git a/compiler/rustc_mir/src/monomorphize/polymorphize.rs b/compiler/rustc_mir/src/monomorphize/polymorphize.rs index b086053a0c1..368ac70b552 100644 --- a/compiler/rustc_mir/src/monomorphize/polymorphize.rs +++ b/compiler/rustc_mir/src/monomorphize/polymorphize.rs @@ -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 { - 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 { - 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 { - 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 { - if !ty.has_param_types_or_consts() { + if !ty.has_potential_param_types_or_consts() { return ControlFlow::CONTINUE; } diff --git a/compiler/rustc_mir/src/shim.rs b/compiler/rustc_mir/src/shim.rs index 8c3d828894c..8083ec95447 100644 --- a/compiler/rustc_mir/src/shim.rs +++ b/compiler/rustc_mir/src/shim.rs @@ -163,7 +163,7 @@ fn build_drop_shim<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId, ty: Option>) 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>) } fn new_body<'tcx>( + tcx: TyCtxt<'tcx>, source: MirSource<'tcx>, basic_blocks: IndexVec>, local_decls: IndexVec>, @@ -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, diff --git a/compiler/rustc_mir/src/transform/const_prop.rs b/compiler/rustc_mir/src/transform/const_prop.rs index 98581f76821..0d58625633f 100644 --- a/compiler/rustc_mir/src/transform/const_prop.rs +++ b/compiler/rustc_mir/src/transform/const_prop.rs @@ -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> { // 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; } diff --git a/compiler/rustc_mir/src/transform/inline/cycle.rs b/compiler/rustc_mir/src/transform/inline/cycle.rs index c9eafafff57..46628b928de 100644 --- a/compiler/rustc_mir/src/transform/inline/cycle.rs +++ b/compiler/rustc_mir/src/transform/inline/cycle.rs @@ -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; } } diff --git a/compiler/rustc_mir/src/transform/mod.rs b/compiler/rustc_mir/src/transform/mod.rs index fa648a6dd49..d4c2456e9a4 100644 --- a/compiler/rustc_mir/src/transform/mod.rs +++ b/compiler/rustc_mir/src/transform/mod.rs @@ -400,7 +400,7 @@ fn inner_mir_for_ctfe(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) - } } - 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) } diff --git a/compiler/rustc_mir/src/transform/promote_consts.rs b/compiler/rustc_mir/src/transform/promote_consts.rs index 14c9b3b0d47..1b43670ba3a 100644 --- a/compiler/rustc_mir/src/transform/promote_consts.rs +++ b/compiler/rustc_mir/src/transform/promote_consts.rs @@ -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), diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index bfebe860971..0a760a740dc 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -239,10 +239,10 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam) -> 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, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index 1b4e6b4e381..267e2d8808f 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -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); diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index c4c1ec8ce4e..3ac9d1e5745 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -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( diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index f89ca0fed03..b743c809ca2 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -583,7 +583,7 @@ where fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow { // 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; } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 9bb4af16a8f..6ab079ad404 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -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 diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 2f1e7e9d509..2cc74ca2abb 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -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); diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index 110d83cbe28..edf2274ab54 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -669,7 +669,7 @@ impl<'a, 'b, 'tcx> FulfillProcessor<'a, 'b, 'tcx> { stalled_on: &mut Vec>, ) -> ProcessResult, 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, 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. // diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index 477d29f1a4f..43ee1c3304a 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -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); diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index c150b222266..1c4e7e6c589 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -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. diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs index 2d102127dd9..c405bbe2d1f 100644 --- a/compiler/rustc_type_ir/src/lib.rs +++ b/compiler/rustc_type_ir/src/lib.rs @@ -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; + } } diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs index 2879b7fcd91..bbfceeeff48 100644 --- a/compiler/rustc_typeck/src/astconv/mod.rs +++ b/compiler/rustc_typeck/src/astconv/mod.rs @@ -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", diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs index 15fa696b6c4..25d1c8706e8 100644 --- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs +++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs @@ -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) -> bool + fn can_contain_user_lifetime_bounds(&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> { diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs index 0d121b9da87..057a15a4358 100644 --- a/compiler/rustc_typeck/src/check/wfcheck.rs +++ b/compiler/rustc_typeck/src/check/wfcheck.rs @@ -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., ``). 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` // 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), diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs index 2e59defdb7b..c57ec9ef78f 100644 --- a/compiler/rustc_typeck/src/check/writeback.rs +++ b/compiler/rustc_typeck/src/check/writeback.rs @@ -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); } diff --git a/compiler/rustc_typeck/src/collect/type_of.rs b/compiler/rustc_typeck/src/collect/type_of.rs index 98f5f73b7be..9b10874b8bc 100644 --- a/compiler/rustc_typeck/src/collect/type_of.rs +++ b/compiler/rustc_typeck/src/collect/type_of.rs @@ -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<'_> { diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs index 2d71c87bee7..d3e4be128a8 100644 --- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs @@ -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 { diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 5e559991c16..90b2aa16896 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -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() { diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 98f3937ba3d..ddff1686ba2 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -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)