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(self.cx.typeck.tcx()) {
+ if local_ty.has_free_regions() {
self.cx.add_drop_live_facts_for(local, local_ty, &[location], &locations);
}
}
self.cx.param_env.and(type_op::ascribe_user_type::AscribeUserType::new(
constant.literal.ty(),
uv.def.did,
- UserSubsts { substs: uv.substs(self.tcx()), user_self_ty: None },
+ UserSubsts { substs: uv.substs, user_self_ty: None },
)),
) {
span_mirbug!(
let predicates = self.prove_closure_bounds(
tcx,
def_id.expect_local(),
- uv.substs(tcx),
+ uv.substs,
location,
);
self.normalize_and_prove_instantiated_predicates(
};
let const_val = match const_.val {
ConstKind::Value(const_val) => const_val,
- ConstKind::Unevaluated(uv) if fx.tcx.is_static(uv.def.did) => {
- assert!(uv.substs(fx.tcx).is_empty());
- assert!(uv.promoted.is_none());
+ ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
+ if fx.tcx.is_static(def.did) =>
+ {
+ assert!(substs.is_empty());
+ assert!(promoted.is_none());
- return codegen_static_ref(fx, uv.def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
+ return codegen_static_ref(fx, def.did, fx.layout_of(const_.ty)).to_cvalue(fx);
}
ConstKind::Unevaluated(unevaluated) => {
match fx.tcx.const_eval_resolve(ParamEnv::reveal_all(), unevaluated, None) {
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.definitely_needs_subst(cx.tcx)
+ && !impl_self_ty.needs_subst()
{
Some(type_metadata(cx, impl_self_ty, rustc_span::DUMMY_SP))
} else {
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(self.cx.tcx()));
+ assert!(!dst_layout.ty.has_erasable_regions());
let place = PlaceRef::alloca(bx, dst_layout);
place.storage_live(bx);
self.codegen_transmute_into(bx, src, place);
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(cx.tcx()));
+ assert!(!layout.ty.has_erasable_regions());
if local == mir::RETURN_PLACE && fx.fn_abi.ret.is_indirect() {
debug!("alloc: {:?} (return place) -> place", local);
ty::ConstKind::Param(_) | ty::ConstKind::Bound(..) => throw_inval!(TooGeneric),
ty::ConstKind::Error(_) => throw_inval!(AlreadyReported(ErrorReported)),
ty::ConstKind::Unevaluated(uv) => {
- let instance = self.resolve(uv.def, uv.substs(*self.tcx))?;
+ let instance = self.resolve(uv.def, uv.substs)?;
Ok(self.eval_to_allocation(GlobalId { instance, promoted: uv.promoted })?.into())
}
ty::ConstKind::Infer(..) | ty::ConstKind::Placeholder(..) => {
T: TypeFoldable<'tcx>,
{
debug!("ensure_monomorphic_enough: ty={:?}", ty);
- if !ty.potentially_needs_subst() {
+ if !ty.needs_subst() {
return Ok(());
}
impl<'tcx> TypeVisitor<'tcx> for UsedParamsNeedSubstVisitor<'tcx> {
type BreakTy = FoundParam;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.potentially_needs_subst() {
+ if !ty.needs_subst() {
return ControlFlow::CONTINUE;
}
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.definitely_needs_subst(self.tcx)) {
+ match (is_used, subst.needs_subst()) {
// Just in case there are closures or generators within this subst,
// recurse.
(true, true) => return subst.super_visit_with(self),
fn check_local_or_return_ty(&mut self, ty: Ty<'tcx>, local: Local) {
let kind = self.body.local_kind(local);
- for ty in ty.walk(self.tcx) {
+ for ty in ty.walk() {
let ty = match ty.unpack() {
GenericArgKind::Type(ty) => ty,
// Check the qualifs of the value of `const` items.
if let Some(ct) = constant.literal.const_for_ty() {
- if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) = ct.val {
+ if let ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) = ct.val {
// Use qualifs of the type for the promoted. Promoteds in MIR body should be possible
// only for `NeedsNonConstDrop` with precise drop checking. This is the only const
// check performed after the promotion. Verify that with an assertion.
ty,
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def,
- substs_: Some(InternalSubsts::for_item(
- tcx,
- def.did,
- |param, _| {
- if let ty::GenericParamDefKind::Lifetime = param.kind {
- tcx.lifetimes.re_erased.into()
- } else {
- tcx.mk_param_from_def(param)
- }
- },
- )),
+ substs: InternalSubsts::for_item(tcx, def.did, |param, _| {
+ if let ty::GenericParamDefKind::Lifetime = param.kind {
+ tcx.lifetimes.re_erased.into()
+ } else {
+ tcx.mk_param_from_def(param)
+ }
+ }),
promoted: Some(promoted_id),
}),
})
scope.parent_scope = None;
let promoted = Body::new(
- tcx,
body.source, // `promoted` gets filled in below
IndexVec::new(),
IndexVec::from_elem_n(scope, 1),
{
let needs_canonical_flags = if canonicalize_region_mode.any() {
TypeFlags::NEEDS_INFER |
- TypeFlags::HAS_POTENTIAL_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_POTENTIAL_FREE_REGIONS`
+ TypeFlags::HAS_FREE_REGIONS | // `HAS_RE_PLACEHOLDER` implies `HAS_FREE_REGIONS`
TypeFlags::HAS_TY_PLACEHOLDER |
TypeFlags::HAS_CT_PLACEHOLDER
} else {
where
R: ConstEquateRelation<'tcx>,
{
- let a = self.tcx.expose_default_const_substs(a);
- let b = self.tcx.expose_default_const_substs(b);
debug!("{}.consts({:?}, {:?})", relation.tag(), a, b);
if a == b {
return Ok(a);
}
}
}
- ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
- assert_eq!(uv.promoted, None);
- let substs = uv.substs(self.tcx());
+ ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
+ if self.tcx().lazy_normalization() =>
+ {
+ assert_eq!(promoted, None);
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
)?;
Ok(self.tcx().mk_const(ty::Const {
ty: c.ty,
- val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
+ val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
}))
}
_ => relate::super_relate_consts(self, c, c),
}
}
}
- ty::ConstKind::Unevaluated(uv) if self.tcx().lazy_normalization() => {
- assert_eq!(uv.promoted, None);
- let substs = uv.substs(self.tcx());
+ ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted })
+ if self.tcx().lazy_normalization() =>
+ {
+ assert_eq!(promoted, None);
let substs = self.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
)?;
Ok(self.tcx().mk_const(ty::Const {
ty: c.ty,
- val: ty::ConstKind::Unevaluated(ty::Unevaluated::new(uv.def, substs)),
+ val: ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted }),
}))
}
_ => relate::super_relate_consts(self, c, c),
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypesVisitor<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let Some((kind, def_id)) = TyCategory::from_ty(self.tcx, t) {
let span = self.tcx.def_span(def_id);
fn node_ty_contains_target(&self, hir_id: HirId) -> Option<Ty<'tcx>> {
self.node_type_opt(hir_id).map(|ty| self.infcx.resolve_vars_if_possible(ty)).filter(|ty| {
- ty.walk(self.infcx.tcx).any(|inner| {
+ ty.walk().any(|inner| {
inner == self.target
|| match (inner.unpack(), self.target.unpack()) {
(GenericArgKind::Type(inner_ty), GenericArgKind::Type(target_ty)) => {
parent: None,
}
}
- ty::ConstKind::Unevaluated(ty::Unevaluated {
- substs_: Some(substs), ..
- }) => {
+ ty::ConstKind::Unevaluated(ty::Unevaluated { substs, .. }) => {
assert!(substs.has_infer_types_or_consts());
// FIXME: We only use the first inference variable we encounter in
pub(super) struct TraitObjectVisitor(pub(super) FxHashSet<DefId>);
impl<'tcx> TypeVisitor<'tcx> for TraitObjectVisitor {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // The default anon const substs cannot include
- // trait objects, so we don't have to bother looking.
- None
- }
-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Dynamic(preds, RegionKind::ReStatic) => {
// Mark all unnamed regions in the type with a number.
// This diagnostic is called in response to lifetime errors, so be informative.
- struct HighlightBuilder<'tcx> {
+ struct HighlightBuilder {
highlight: RegionHighlightMode,
- tcx: TyCtxt<'tcx>,
counter: usize,
}
- impl<'tcx> HighlightBuilder<'tcx> {
- fn build(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> RegionHighlightMode {
+ impl HighlightBuilder {
+ fn build(ty: Ty<'_>) -> RegionHighlightMode {
let mut builder =
- HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1, tcx };
+ HighlightBuilder { highlight: RegionHighlightMode::default(), counter: 1 };
builder.visit_ty(ty);
builder.highlight
}
}
- impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
+ impl<'tcx> ty::fold::TypeVisitor<'tcx> for HighlightBuilder {
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
if !r.has_name() && self.counter <= 3 {
self.highlight.highlighting_region(r, self.counter);
}
}
- let expected_highlight = HighlightBuilder::build(self.tcx(), expected);
+ let expected_highlight = HighlightBuilder::build(expected);
let expected = self
.infcx
.extract_inference_diagnostics_data(expected.into(), Some(expected_highlight))
.name;
- let found_highlight = HighlightBuilder::build(self.tcx(), found);
+ let found_highlight = HighlightBuilder::build(found);
let found =
self.infcx.extract_inference_diagnostics_data(found.into(), Some(found_highlight)).name;
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if !t.needs_infer() && !t.has_erasable_regions(self.tcx()) {
+ if !t.needs_infer() && !t.has_erasable_regions() {
return t;
}
unevaluated: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
- let mut substs = unevaluated.substs(self.tcx);
- substs = self.resolve_vars_if_possible(substs);
+ let substs = self.resolve_vars_if_possible(unevaluated.substs);
// Postpone the evaluation of constants whose substs depend on inference
// variables
let unevaluated = ty::Unevaluated {
def: unevaluated.def,
- substs_: Some(substs_erased),
+ substs: substs_erased,
promoted: unevaluated.promoted,
};
};
value.skip_binder().visit_with(&mut ScopeInstantiator {
- tcx: self.infcx.tcx,
next_region: &mut next_region,
target_index: ty::INNERMOST,
bound_region_scope: &mut scope,
/// `for<..`>. For each of those, it creates an entry in
/// `bound_region_scope`.
struct ScopeInstantiator<'me, 'tcx> {
- tcx: TyCtxt<'tcx>,
next_region: &'me mut dyn FnMut(ty::BoundRegion) -> ty::Region<'tcx>,
// The debruijn index of the scope we are instantiating.
target_index: ty::DebruijnIndex,
}
impl<'me, 'tcx> TypeVisitor<'tcx> for ScopeInstantiator<'me, 'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &ty::Binder<'tcx, T>,
);
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
- tcx: self.tcx,
op: |r| {
self.member_constraint(
opaque_type_key.def_id,
//
// We ignore any type parameters because impl trait values are assumed to
// capture all the in-scope type parameters.
-struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP> {
- tcx: TyCtxt<'tcx>,
+struct ConstrainOpaqueTypeRegionVisitor<OP> {
op: OP,
}
-impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
where
OP: FnMut(ty::Region<'tcx>),
{
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &ty::Binder<'tcx, T>,
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_POTENTIAL_FREE_REGIONS) {
+ if !ty.flags().intersects(ty::TypeFlags::HAS_FREE_REGIONS) {
return ControlFlow::CONTINUE;
}
out: &mut SmallVec<[Component<'tcx>; 4]>,
visited: &mut SsoHashSet<GenericArg<'tcx>>,
) {
- for child in parent.walk_shallow(tcx, visited) {
+ for child in parent.walk_shallow(visited) {
match child.unpack() {
GenericArgKind::Type(ty) => {
compute_components(tcx, ty, out, visited);
visited: &mut SsoHashSet<GenericArg<'tcx>>,
) -> VerifyBound<'tcx> {
let mut bounds = parent
- .walk_shallow(self.tcx, visited)
+ .walk_shallow(visited)
.filter_map(|child| match child.unpack() {
GenericArgKind::Type(ty) => Some(self.type_bound(ty, visited)),
GenericArgKind::Lifetime(lt) => {
impl<'a, 'tcx> TypeVisitor<'tcx> for UnresolvedTypeFinder<'a, 'tcx> {
type BreakTy = (Ty<'tcx>, Option<Span>);
-
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.infcx.tcx)
- }
-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
let t = self.infcx.shallow_resolve(t);
if t.has_infer_types() {
declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
impl BoxPointers {
- fn check_heap_type<'tcx>(&self, cx: &LateContext<'tcx>, span: Span, ty: Ty<'tcx>) {
- for leaf in ty.walk(cx.tcx) {
+ fn check_heap_type(&self, cx: &LateContext<'_>, span: Span, ty: Ty<'_>) {
+ for leaf in ty.walk() {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
if leaf_ty.is_box() {
cx.struct_span_lint(BOX_POINTERS, span, |lint| {
ConstEquate(..) |
TypeWellFormedFromEnv(..) => continue,
};
- if predicate.is_global(cx.tcx) {
+ if predicate.is_global() {
cx.struct_span_lint(TRIVIAL_BOUNDS, span, |lint| {
lint.build(&format!(
"{} bound {} does not depend on any type \
/// Returns `true` if we know for sure that the given type is not an enum. Note that for cases where
/// the type is generic, we can't be certain if it will be an enum so we have to assume that it is.
fn is_non_enum(t: Ty<'_>) -> bool {
- !t.is_enum() && !t.potentially_needs_subst()
+ !t.is_enum() && !t.needs_subst()
}
fn enforce_mem_discriminant(
_ => return,
};
let substs = cx.typeck_results().node_substs(expr.hir_id);
- if substs.definitely_needs_subst(cx.tcx) {
+ if substs.needs_subst() {
// We can't resolve on types that require monomorphization, so we don't handle them if
// we need to perfom substitution.
return;
impl<'a, 'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueTypes<'a, 'tcx> {
type BreakTy = Ty<'tcx>;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.cx.tcx)
- }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match ty.kind() {
ct: ty::Unevaluated<'tcx>,
span: Option<Span>,
) -> EvalToConstValueResult<'tcx> {
- match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs(self)) {
+ match ty::Instance::resolve_opt_const_arg(self, param_env, ct.def, ct.substs) {
Ok(Some(instance)) => {
let cid = GlobalId { instance, promoted: ct.promoted };
self.const_eval_global_id(param_env, cid, span)
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>>,
predecessor_cache: PredecessorCache::new(),
is_cyclic: GraphIsCyclicCache::new(),
};
- body.is_polymorphic = body.definitely_has_param_types_or_consts(tcx);
+ body.is_polymorphic = body.has_param_types_or_consts();
body
}
/// 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 {
- Body {
+ let mut body = Body {
phase: MirPhase::Build,
source: MirSource::item(DefId::local(CRATE_DEF_INDEX)),
basic_blocks,
is_polymorphic: false,
predecessor_cache: PredecessorCache::new(),
is_cyclic: GraphIsCyclicCache::new(),
- }
+ };
+ body.is_polymorphic = body.has_param_types_or_consts();
+ body
}
#[inline]
ty::ConstKind::Unevaluated(uv) => format!(
"Unevaluated({}, {:?}, {:?})",
self.tcx.def_path_str(uv.def.did),
- uv.substs(self.tcx),
- uv.promoted
+ uv.substs,
+ uv.promoted,
),
ty::ConstKind::Value(val) => format!("Value({:?})", val),
ty::ConstKind::Error(_) => "Error".to_string(),
}
struct CollectAllocIds(BTreeSet<AllocId>);
impl<'tcx> TypeVisitor<'tcx> for CollectAllocIds {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // `AllocId`s are only inside of `ConstKind::Value` which
- // can't be part of the anon const default substs.
- None
- }
-
fn visit_const(&mut self, c: &'tcx ty::Const<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::ConstKind::Value(val) = c.val {
self.0.extend(alloc_ids_from_const(val));
separate_provide_extern
}
- query default_anon_const_substs(key: DefId) -> SubstsRef<'tcx> {
- desc { |tcx| "computing the default generic arguments for `{}`", tcx.def_path_str(key) }
- }
-
/// Records the type of every item.
query type_of(key: DefId) -> Ty<'tcx> {
desc { |tcx|
None => tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: def.to_global(),
- substs_: None,
+ substs: InternalSubsts::identity_for_item(tcx, def.did.to_def_id()),
promoted: None,
}),
ty,
tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: ty::WithOptConstParam::unknown(def_id).to_global(),
- substs_: Some(substs),
+ substs,
promoted: None,
}),
ty,
})
}
};
- debug_assert!(!ret.has_free_regions(tcx));
+ debug_assert!(!ret.has_free_regions());
ret
}
use std::convert::TryInto;
-use std::fmt;
use crate::mir::interpret::{AllocId, ConstValue, Scalar};
use crate::mir::Promoted;
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, Lift)]
#[derive(Hash, HashStable)]
pub struct Unevaluated<'tcx, P = Option<Promoted>> {
pub def: ty::WithOptConstParam<DefId>,
- pub substs_: Option<SubstsRef<'tcx>>,
+ pub substs: SubstsRef<'tcx>,
pub promoted: P,
}
#[inline]
pub fn shrink(self) -> Unevaluated<'tcx, ()> {
debug_assert_eq!(self.promoted, None);
- Unevaluated { def: self.def, substs_: self.substs_, promoted: () }
+ Unevaluated { def: self.def, substs: self.substs, promoted: () }
}
}
impl<'tcx> Unevaluated<'tcx, ()> {
#[inline]
pub fn expand(self) -> Unevaluated<'tcx> {
- Unevaluated { def: self.def, substs_: self.substs_, promoted: None }
+ Unevaluated { def: self.def, substs: self.substs, promoted: None }
}
}
impl<'tcx, P: Default> Unevaluated<'tcx, P> {
#[inline]
pub fn new(def: ty::WithOptConstParam<DefId>, substs: SubstsRef<'tcx>) -> Unevaluated<'tcx, P> {
- Unevaluated { def, substs_: Some(substs), promoted: Default::default() }
- }
-}
-
-impl<'tcx, P: Default + PartialEq + fmt::Debug> Unevaluated<'tcx, P> {
- #[inline]
- pub fn substs(self, tcx: TyCtxt<'tcx>) -> SubstsRef<'tcx> {
- self.substs_.unwrap_or_else(|| {
- // We must not use the parents default substs for promoted constants
- // as that can result in incorrect substs and calls the `default_anon_const_substs`
- // for something that might not actually be a constant.
- debug_assert_eq!(self.promoted, Default::default());
- tcx.default_anon_const_substs(self.def.did)
- })
+ Unevaluated { def, substs, promoted: Default::default() }
}
}
let param_env_and = if param_env_and.needs_infer() {
tcx.param_env(unevaluated.def.did).and(ty::Unevaluated {
def: unevaluated.def,
- substs_: Some(InternalSubsts::identity_for_item(tcx, unevaluated.def.did)),
+ substs: InternalSubsts::identity_for_item(tcx, unevaluated.def.did),
promoted: unevaluated.promoted,
})
} else {
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_POTENTIAL_FREE_REGIONS)
- {
+ if !value.has_type_flags(TypeFlags::HAS_RE_LATE_BOUND | TypeFlags::HAS_FREE_REGIONS) {
return value;
}
debug!("erase_regions({:?})", value);
&ty::Error(_) => self.add_flags(TypeFlags::HAS_ERROR),
&ty::Param(_) => {
- self.add_flags(TypeFlags::HAS_KNOWN_TY_PARAM);
+ self.add_flags(TypeFlags::HAS_TY_PARAM);
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
self.add_bound_var(debruijn);
}
ty::ConstKind::Param(_) => {
- self.add_flags(TypeFlags::HAS_KNOWN_CT_PARAM);
+ self.add_flags(TypeFlags::HAS_CT_PARAM);
self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
}
ty::ConstKind::Placeholder(_) => {
}
fn add_unevaluated_const<P>(&mut self, ct: ty::Unevaluated<'_, P>) {
- // The generic arguments of unevaluated consts are a bit special,
- // see the `rustc-dev-guide` for more information.
- //
- // FIXME(@lcnr): Actually add a link here.
- if let Some(substs) = ct.substs_ {
- // If they are available, we treat them as ordinary generic arguments.
- self.add_substs(substs);
- } else {
- // Otherwise, we add `HAS_UNKNOWN_DEFAULT_CONST_SUBSTS` to signify
- // that our const may potentially refer to generic parameters.
- //
- // Note that depending on which generic parameters are actually
- // used in this constant, we may not actually refer to any generic
- // parameters at all.
- self.add_flags(TypeFlags::STILL_FURTHER_SPECIALIZABLE);
- self.add_flags(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS);
- }
+ self.add_substs(ct.substs);
self.add_flags(TypeFlags::HAS_CT_PROJECTION);
}
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)
- }
-
#[instrument(level = "trace")]
fn has_type_flags(&self, flags: TypeFlags) -> bool {
- self.visit_with(&mut HasTypeFlagsVisitor { tcx: None, flags }).break_value()
- == Some(FoundFlags)
+ self.visit_with(&mut HasTypeFlagsVisitor { flags }).break_value() == Some(FoundFlags)
}
fn has_projections(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_PROJECTION)
fn references_error(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_ERROR)
}
- fn potentially_has_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 definitely_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_param_types_or_consts(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_TY_PARAM | TypeFlags::HAS_CT_PARAM)
}
fn has_infer_regions(&self) -> bool {
self.has_type_flags(TypeFlags::HAS_RE_INFER)
| TypeFlags::HAS_CT_PLACEHOLDER,
)
}
- fn potentially_needs_subst(&self) -> bool {
- self.has_type_flags(
- TypeFlags::KNOWN_NEEDS_SUBST | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS,
- )
- }
- fn definitely_needs_subst(&self, tcx: TyCtxt<'tcx>) -> bool {
- self.definitely_has_type_flags(tcx, TypeFlags::KNOWN_NEEDS_SUBST)
+ fn needs_subst(&self) -> bool {
+ self.has_type_flags(TypeFlags::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, tcx: TyCtxt<'tcx>) -> bool {
- self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_REGIONS)
+ fn has_free_regions(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
}
fn has_erased_regions(&self) -> bool {
}
/// True if there are any un-erased 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)
+ fn has_erasable_regions(&self) -> bool {
+ self.has_type_flags(TypeFlags::HAS_FREE_REGIONS)
}
/// 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, tcx: TyCtxt<'tcx>) -> bool {
- !self.definitely_has_type_flags(tcx, TypeFlags::HAS_KNOWN_FREE_LOCAL_NAMES)
+ fn is_global(&self) -> bool {
+ !self.has_type_flags(TypeFlags::HAS_FREE_LOCAL_NAMES)
}
/// True if there are any late-bound regions
pub trait TypeVisitor<'tcx>: Sized {
type BreakTy = !;
- /// Supplies the `tcx` for an unevaluated anonymous constant in case its default substs
- /// are not yet supplied.
- ///
- /// Returning `None` for this method is only recommended if the `TypeVisitor`
- /// does not care about default anon const substs, as it ignores generic parameters,
- /// and fetching the default substs would cause a query cycle.
- ///
- /// For visitors which return `None` we completely skip the default substs in `ty::Unevaluated::super_visit_with`.
- /// This means that incorrectly returning `None` can very quickly lead to ICE or other critical bugs, so be careful and
- /// try to return an actual `tcx` if possible.
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>>;
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
value: &impl TypeFoldable<'tcx>,
callback: impl FnMut(ty::Region<'tcx>) -> bool,
) -> bool {
- struct RegionVisitor<'tcx, F> {
- tcx: TyCtxt<'tcx>,
+ struct RegionVisitor<F> {
/// The index of a binder *just outside* the things we have
/// traversed. If we encounter a bound region bound by this
/// binder or one outer to it, it appears free. Example:
callback: F,
}
- impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<'tcx, F>
+ impl<'tcx, F> TypeVisitor<'tcx> for RegionVisitor<F>
where
F: FnMut(ty::Region<'tcx>) -> bool,
{
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
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_POTENTIAL_FREE_REGIONS) {
+ if ty.flags().intersects(TypeFlags::HAS_FREE_REGIONS) {
ty.super_visit_with(self)
} else {
ControlFlow::CONTINUE
}
}
- value
- .visit_with(&mut RegionVisitor { tcx: self, outer_index: ty::INNERMOST, callback })
- .is_break()
+ value.visit_with(&mut RegionVisitor { outer_index: ty::INNERMOST, callback }).is_break()
}
}
where
T: TypeFoldable<'tcx>,
{
- let mut collector = LateBoundRegionsCollector::new(self, just_constraint);
+ let mut collector = LateBoundRegionsCollector::new(just_constraint);
let result = value.as_ref().skip_binder().visit_with(&mut collector);
assert!(result.is_continue()); // should never have stopped early
collector.regions
impl<'tcx> TypeVisitor<'tcx> for ValidateBoundVars<'tcx> {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // Anonymous constants do not contain bound vars in their substs by default.
- None
- }
-
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
impl<'tcx> TypeVisitor<'tcx> for HasEscapingVarsVisitor {
type BreakTy = FoundEscapingVars;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // Anonymous constants do not contain bound vars in their substs by default.
- None
- }
-
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
struct FoundFlags;
// FIXME: Optimize for checking for infer flags
-struct HasTypeFlagsVisitor<'tcx> {
- tcx: Option<TyCtxt<'tcx>>,
+struct HasTypeFlagsVisitor {
flags: ty::TypeFlags,
}
-impl<'tcx> std::fmt::Debug for HasTypeFlagsVisitor<'tcx> {
+impl std::fmt::Debug for HasTypeFlagsVisitor {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.flags.fmt(fmt)
}
}
-impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor<'tcx> {
+impl<'tcx> TypeVisitor<'tcx> for HasTypeFlagsVisitor {
type BreakTy = FoundFlags;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- bug!("we shouldn't call this method as we manually look at ct substs");
- }
#[inline]
#[instrument(level = "trace")]
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- let flags = t.flags();
- trace!(t.flags=?t.flags());
- if flags.intersects(self.flags) {
+ fn visit_ty(&mut self, t: Ty<'_>) -> ControlFlow<Self::BreakTy> {
+ debug!(
+ "HasTypeFlagsVisitor: t={:?} t.flags={:?} self.flags={:?}",
+ t,
+ t.flags(),
+ self.flags
+ );
+ if t.flags().intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, t),
- _ => ControlFlow::CONTINUE,
- }
+ ControlFlow::CONTINUE
}
}
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, c),
- _ => ControlFlow::CONTINUE,
- }
+ ControlFlow::CONTINUE
}
}
if flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
} else {
- match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, uv),
- _ => ControlFlow::CONTINUE,
- }
+ ControlFlow::CONTINUE
}
}
#[inline]
#[instrument(level = "trace")]
fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- let flags = predicate.inner.flags;
- trace!(predicate.flags=?flags);
- if flags.intersects(self.flags) {
+ debug!(
+ "HasTypeFlagsVisitor: predicate={:?} predicate.flags={:?} self.flags={:?}",
+ predicate, predicate.inner.flags, self.flags
+ );
+ if predicate.inner.flags.intersects(self.flags) {
ControlFlow::Break(FoundFlags)
- } else {
- match flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- true if self.tcx.is_some() => UnknownConstSubstsVisitor::search(&self, predicate),
- _ => ControlFlow::CONTINUE,
- }
- }
- }
-}
-
-struct UnknownConstSubstsVisitor<'tcx> {
- tcx: TyCtxt<'tcx>,
- flags: ty::TypeFlags,
-}
-
-impl<'tcx> UnknownConstSubstsVisitor<'tcx> {
- /// This is fairly cold and we don't want to
- /// bloat the size of the `HasTypeFlagsVisitor`.
- #[inline(never)]
- pub fn search<T: TypeFoldable<'tcx>>(
- visitor: &HasTypeFlagsVisitor<'tcx>,
- v: T,
- ) -> ControlFlow<FoundFlags> {
- if visitor.flags.intersects(TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS) {
- v.super_visit_with(&mut UnknownConstSubstsVisitor {
- tcx: visitor.tcx.unwrap(),
- flags: visitor.flags,
- })
} else {
ControlFlow::CONTINUE
}
}
}
-impl<'tcx> TypeVisitor<'tcx> for UnknownConstSubstsVisitor<'tcx> {
- type BreakTy = FoundFlags;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- bug!("we shouldn't call this method as we manually look at ct substs");
- }
-
- fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if t.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- t.super_visit_with(self)
- } else {
- ControlFlow::CONTINUE
- }
- }
-
- #[inline]
- fn visit_unevaluated_const(&mut self, uv: ty::Unevaluated<'tcx>) -> ControlFlow<Self::BreakTy> {
- if uv.substs_.is_none() {
- self.tcx
- .default_anon_const_substs(uv.def.did)
- .visit_with(&mut HasTypeFlagsVisitor { tcx: Some(self.tcx), flags: self.flags })
- } else {
- ControlFlow::CONTINUE
- }
- }
-
- #[inline]
- fn visit_predicate(&mut self, predicate: ty::Predicate<'tcx>) -> ControlFlow<Self::BreakTy> {
- if predicate.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- predicate.super_visit_with(self)
- } else {
- ControlFlow::CONTINUE
- }
- }
-}
-
-impl<'tcx> TyCtxt<'tcx> {
- /// This is a HACK(const_generics) and should probably not be needed.
- /// Might however be perf relevant, so who knows.
- ///
- /// FIXME(@lcnr): explain this function a bit more
- pub fn expose_default_const_substs<T: TypeFoldable<'tcx>>(self, v: T) -> T {
- v.fold_with(&mut ExposeDefaultConstSubstsFolder { tcx: self })
- }
-}
-
-struct ExposeDefaultConstSubstsFolder<'tcx> {
- tcx: TyCtxt<'tcx>,
-}
-
-impl<'tcx> TypeFolder<'tcx> for ExposeDefaultConstSubstsFolder<'tcx> {
- fn tcx(&self) -> TyCtxt<'tcx> {
- self.tcx
- }
-
- fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if ty.flags().intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- ty.super_fold_with(self)
- } else {
- ty
- }
- }
-
- fn fold_predicate(&mut self, pred: ty::Predicate<'tcx>) -> ty::Predicate<'tcx> {
- if pred.inner.flags.intersects(TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS) {
- pred.super_fold_with(self)
- } else {
- pred
- }
- }
-}
-
/// Collects all the late-bound regions at the innermost binding level
/// into a hash set.
-struct LateBoundRegionsCollector<'tcx> {
- tcx: TyCtxt<'tcx>,
+struct LateBoundRegionsCollector {
current_index: ty::DebruijnIndex,
regions: FxHashSet<ty::BoundRegionKind>,
just_constrained: bool,
}
-impl<'tcx> LateBoundRegionsCollector<'tcx> {
- fn new(tcx: TyCtxt<'tcx>, just_constrained: bool) -> Self {
+impl LateBoundRegionsCollector {
+ fn new(just_constrained: bool) -> Self {
LateBoundRegionsCollector {
- tcx,
current_index: ty::INNERMOST,
regions: Default::default(),
just_constrained,
}
}
-impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
+impl<'tcx> TypeVisitor<'tcx> for LateBoundRegionsCollector {
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
// 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.definitely_has_param_types_or_consts(self.tcx)
- || !self.param_env.caller_bounds().is_empty()
- {
+ if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() {
return;
}
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
match tail.kind() {
ty::Param(_) | ty::Projection(_) => {
- debug_assert!(tail.definitely_has_param_types_or_consts(tcx));
+ debug_assert!(tail.has_param_types_or_consts());
Ok(SizeSkeleton::Pointer { non_zero, tail: tcx.erase_regions(tail) })
}
_ => bug!(
Reveal::UserFacing => ParamEnvAnd { param_env: self, value },
Reveal::All => {
- if value.is_known_global() {
+ if value.is_global() {
ParamEnvAnd { param_env: self.without_caller_bounds(), value }
} else {
ParamEnvAnd { param_env: self, value }
}
match ct.val {
- ty::ConstKind::Unevaluated(uv) => {
- if let Some(promoted) = uv.promoted {
- let substs = uv.substs_.unwrap();
- p!(print_value_path(uv.def.did, substs));
- p!(write("::{:?}", promoted));
- } else {
- let tcx = self.tcx();
- match tcx.def_kind(uv.def.did) {
- DefKind::Static | DefKind::Const | DefKind::AssocConst => {
- p!(print_value_path(uv.def.did, uv.substs(tcx)))
- }
- _ => {
- if uv.def.is_local() {
- let span = tcx.def_span(uv.def.did);
- if let Ok(snip) = tcx.sess.source_map().span_to_snippet(span) {
- p!(write("{}", snip))
- } else {
- print_underscore!()
- }
+ ty::ConstKind::Unevaluated(ty::Unevaluated {
+ def,
+ substs,
+ promoted: Some(promoted),
+ }) => {
+ p!(print_value_path(def.did, substs));
+ p!(write("::{:?}", promoted));
+ }
+ ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs, promoted: None }) => {
+ match self.tcx().def_kind(def.did) {
+ DefKind::Static | DefKind::Const | DefKind::AssocConst => {
+ p!(print_value_path(def.did, substs))
+ }
+ _ => {
+ if def.is_local() {
+ let span = self.tcx().def_span(def.did);
+ if let Ok(snip) = self.tcx().sess.source_map().span_to_snippet(span) {
+ p!(write("{}", snip))
} else {
print_underscore!()
}
+ } else {
+ print_underscore!()
}
}
}
// Aggregates, printed as array/tuple/struct/variant construction syntax.
//
- // NB: the `potentially_has_param_types_or_consts` check ensures that we can use
+ // NB: the `has_param_types_or_consts` check ensures that we can use
// the `destructure_const` query with an empty `ty::ParamEnv` without
// introducing ICEs (e.g. via `layout_of`) from missing bounds.
// E.g. `transmute([0usize; 2]): (u8, *mut T)` needs to know `T: Sized`
//
// 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.potentially_has_param_types_or_consts() =>
- {
+ (_, ty::Array(..) | ty::Tuple(..) | ty::Adt(..)) if !ty.has_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 })),
T: TypeFoldable<'tcx>,
{
struct LateBoundRegionNameCollector<'a, 'tcx> {
- tcx: TyCtxt<'tcx>,
used_region_names: &'a mut FxHashSet<Symbol>,
type_collector: SsoHashSet<Ty<'tcx>>,
}
impl<'tcx> ty::fold::TypeVisitor<'tcx> for LateBoundRegionNameCollector<'_, 'tcx> {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
#[instrument(skip(self), level = "trace")]
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
trace!("address: {:p}", r);
self.used_region_names.clear();
let mut collector = LateBoundRegionNameCollector {
- tcx: self.tcx,
used_region_names: &mut self.used_region_names,
type_collector: SsoHashSet::new(),
};
write("` implements the trait `{}`", kind))
}
ty::PredicateKind::ConstEvaluatable(uv) => {
- p!("the constant `", print_value_path(uv.def.did, uv.substs_.map_or(&[], |x| x)), "` can be evaluated")
+ p!("the constant `", print_value_path(uv.def.did, uv.substs), "` can be evaluated")
}
ty::PredicateKind::ConstEquate(c1, c2) => {
p!("the constant `", print(c1), "` equals `", print(c2), "`")
let substs = relation.relate_with_variance(
ty::Variance::Invariant,
ty::VarianceDiagInfo::default(),
- au.substs(tcx),
- bu.substs(tcx),
+ au.substs,
+ bu.substs,
)?;
return Ok(tcx.mk_const(ty::Const {
val: ty::ConstKind::Unevaluated(ty::Unevaluated {
def: au.def,
- substs_: Some(substs),
+ substs,
promoted: au.promoted,
}),
ty: a.ty,
write!(f, "ClosureKind({:?}, {:?}, {:?})", closure_def_id, closure_substs, kind)
}
ty::PredicateKind::ConstEvaluatable(uv) => {
- write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs_)
+ write!(f, "ConstEvaluatable({:?}, {:?})", uv.def, uv.substs)
}
ty::PredicateKind::ConstEquate(c1, c2) => write!(f, "ConstEquate({:?}, {:?})", c1, c2),
ty::PredicateKind::TypeWellFormedFromEnv(ty) => {
) -> Result<Self, F::Error> {
Ok(ty::Unevaluated {
def: self.def,
- substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?),
+ substs: self.substs.try_fold_with(folder)?,
promoted: self.promoted,
})
}
}
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)
- } else if let Some(substs) = self.substs_ {
- substs.visit_with(visitor)
- } else {
- debug!("ignoring default substs of `{:?}`", self.def);
- ControlFlow::CONTINUE
- }
+ self.substs.visit_with(visitor)
}
}
) -> Result<Self, F::Error> {
Ok(ty::Unevaluated {
def: self.def,
- substs_: Some(self.substs(folder.tcx()).try_fold_with(folder)?),
+ substs: self.substs.try_fold_with(folder)?,
promoted: self.promoted,
})
}
}
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)
- } else if let Some(substs) = self.substs_ {
- substs.visit_with(visitor)
- } else {
- debug!("ignoring default substs of `{:?}`", self.def);
- ControlFlow::CONTINUE
- }
+ self.substs.visit_with(visitor)
}
}
match *self {
ty::ReVar(..) => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_INFER;
}
ty::RePlaceholder(..) => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
flags = flags | TypeFlags::HAS_RE_PLACEHOLDER;
}
ty::ReEarlyBound(..) => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_RE_PARAM;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_RE_PARAM;
}
ty::ReFree { .. } => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
- flags = flags | TypeFlags::HAS_KNOWN_FREE_LOCAL_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_LOCAL_REGIONS;
}
ty::ReEmpty(_) | ty::ReStatic => {
- flags = flags | TypeFlags::HAS_KNOWN_FREE_REGIONS;
+ flags = flags | TypeFlags::HAS_FREE_REGIONS;
}
ty::ReLateBound(..) => {
flags = flags | TypeFlags::HAS_RE_LATE_BOUND;
}
fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
- if !t.potentially_needs_subst() {
+ if !t.needs_subst() {
return t;
}
//! An iterator over the type substructure.
//! WARNING: this does not keep track of the region depth.
+use crate::ty;
use crate::ty::subst::{GenericArg, GenericArgKind};
-use crate::ty::{self, TyCtxt};
use rustc_data_structures::sso::SsoHashSet;
use smallvec::{self, SmallVec};
type TypeWalkerStack<'tcx> = SmallVec<[GenericArg<'tcx>; 8]>;
pub struct TypeWalker<'tcx> {
- expose_default_const_substs: Option<TyCtxt<'tcx>>,
stack: TypeWalkerStack<'tcx>,
last_subtree: usize,
pub visited: SsoHashSet<GenericArg<'tcx>>,
/// It maintains a set of visited types and
/// skips any types that are already there.
impl<'tcx> TypeWalker<'tcx> {
- fn new(expose_default_const_substs: Option<TyCtxt<'tcx>>, root: GenericArg<'tcx>) -> Self {
- Self {
- expose_default_const_substs,
- stack: smallvec![root],
- last_subtree: 1,
- visited: SsoHashSet::new(),
- }
+ pub fn new(root: GenericArg<'tcx>) -> Self {
+ Self { stack: smallvec![root], last_subtree: 1, visited: SsoHashSet::new() }
}
/// Skips the subtree corresponding to the last type
let next = self.stack.pop()?;
self.last_subtree = self.stack.len();
if self.visited.insert(next) {
- push_inner(self.expose_default_const_substs, &mut self.stack, next);
+ push_inner(&mut self.stack, next);
debug!("next: stack={:?}", self.stack);
return Some(next);
}
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
/// [isize] => { [isize], isize }
/// ```
- pub fn walk(self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> {
- TypeWalker::new(Some(tcx), self)
+ pub fn walk(self) -> TypeWalker<'tcx> {
+ TypeWalker::new(self)
}
/// Iterator that walks the immediate children of `self`. Hence
/// and skips any types that are already there.
pub fn walk_shallow(
self,
- tcx: TyCtxt<'tcx>,
visited: &mut SsoHashSet<GenericArg<'tcx>>,
) -> impl Iterator<Item = GenericArg<'tcx>> {
let mut stack = SmallVec::new();
- push_inner(Some(tcx), &mut stack, self);
+ push_inner(&mut stack, self);
stack.retain(|a| visited.insert(*a));
stack.into_iter()
}
}
impl<'tcx> super::TyS<'tcx> {
- pub fn walk_ignoring_default_const_substs(&'tcx self) -> TypeWalker<'tcx> {
- TypeWalker::new(None, self.into())
- }
-
/// Iterator that walks `self` and any types reachable from
/// `self`, in depth-first order. Note that just walks the types
/// that appear in `self`, it does not descend into the fields of
/// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize }
/// [isize] => { [isize], isize }
/// ```
- pub fn walk(&'tcx self, tcx: TyCtxt<'tcx>) -> TypeWalker<'tcx> {
- TypeWalker::new(Some(tcx), self.into())
+ pub fn walk(&'tcx self) -> TypeWalker<'tcx> {
+ TypeWalker::new(self.into())
}
}
/// known to be significant to any code, but it seems like the
/// natural order one would expect (basically, the order of the
/// types as they are written).
-fn push_inner<'tcx>(
- expose_default_const_substs: Option<TyCtxt<'tcx>>,
- stack: &mut TypeWalkerStack<'tcx>,
- parent: GenericArg<'tcx>,
-) {
+fn push_inner<'tcx>(stack: &mut TypeWalkerStack<'tcx>, parent: GenericArg<'tcx>) {
match parent.unpack() {
GenericArgKind::Type(parent_ty) => match *parent_ty.kind() {
ty::Bool
| ty::ConstKind::Error(_) => {}
ty::ConstKind::Unevaluated(ct) => {
- if let Some(tcx) = expose_default_const_substs {
- stack.extend(ct.substs(tcx).iter().rev());
- } else if let Some(substs) = ct.substs_ {
- stack.extend(substs.iter().rev());
- }
+ stack.extend(ct.substs.iter().rev());
}
}
}
// The exception is `body.user_type_annotations`, which is used unmodified
// by borrow checking.
debug_assert!(
- !(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)),
+ !(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()),
"Unexpected free regions in MIR: {:?}",
body,
);
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,
}
Body::new(
- self.tcx,
MirSource::item(self.def_id),
self.cfg.basic_blocks,
self.source_scopes,
// code at the moment, because types like `for <'a> fn(&'a ())` do
// not *yet* implement `PartialEq`. So for now we leave this here.
has_impl
- || ty.walk(self.tcx()).any(|t| match t.unpack() {
+ || ty.walk().any(|t| match t.unpack() {
ty::subst::GenericArgKind::Lifetime(_) => false,
ty::subst::GenericArgKind::Type(t) => t.is_fn_ptr(),
ty::subst::GenericArgKind::Const(_) => false,
.predicates_of(def_id.to_def_id())
.predicates
.iter()
- .filter_map(|(p, _)| if p.is_global(tcx) { Some(*p) } else { None });
+ .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
if traits::impossible_predicates(
tcx,
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
trace!("ConstProp starting for {:?}", def_id);
let dummy_body = &Body::new(
- tcx,
body.source,
body.basic_blocks().clone(),
body.source_scopes.clone(),
/// 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.definitely_needs_subst(self.tcx) {
+ if c.needs_subst() {
return None;
}
// Promoteds must lint and not error as the user didn't ask for them
ConstKind::Unevaluated(ty::Unevaluated {
def: _,
- substs_: _,
+ substs: _,
promoted: Some(_),
}) => true,
// Out of backwards compatibility we cannot report hard errors in unused
// generic functions using associated constants of the generic parameters.
- _ => c.literal.definitely_needs_subst(*tcx),
+ _ => c.literal.needs_subst(),
},
- ConstantKind::Val(_, ty) => ty.definitely_needs_subst(*tcx),
+ ConstantKind::Val(_, ty) => ty.needs_subst(),
};
if lint_only {
// Out of backwards compatibility we cannot report hard errors in unused
}
// FIXME we need to revisit this for #67176
- if rvalue.definitely_needs_subst(self.tcx) {
+ if rvalue.needs_subst() {
return None;
}
// Handle calls to `transmute`
if self.tcx.is_diagnostic_item(sym::transmute, def_id) {
let arg_ty = args[0].ty(self.body, self.tcx);
- for generic_inner_ty in arg_ty.walk(self.tcx) {
+ for generic_inner_ty in arg_ty.walk() {
if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
if let Some((fn_id, fn_substs)) =
FunctionItemRefChecker::is_fn_ref(inner_ty)
let arg_defs = self.tcx.fn_sig(def_id).skip_binder().inputs();
for (arg_num, arg_def) in arg_defs.iter().enumerate() {
// For all types reachable from the argument type in the fn sig
- for generic_inner_ty in arg_def.walk(self.tcx) {
+ for generic_inner_ty in arg_def.walk() {
if let GenericArgKind::Type(inner_ty) = generic_inner_ty.unpack() {
// If the inner type matches the type bound by `Pointer`
if TyS::same_type(inner_ty, bound_ty) {
// 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.definitely_needs_subst(tcx) {
+ if callee.needs_subst() {
continue;
}
}
}
}
- debug_assert!(!body.has_free_regions(tcx), "Free regions in MIR for CTFE");
+ debug_assert!(!body.has_free_regions(), "Free regions in MIR for CTFE");
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(tcx), "Free regions in optimized MIR");
+ debug_assert!(!body.has_free_regions(), "Free regions in optimized MIR");
body
}
run_post_borrowck_cleanup_passes(tcx, body);
}
- debug_assert!(!promoted.has_free_regions(tcx), "Free regions in promoted MIR");
+ debug_assert!(!promoted.has_free_regions(), "Free regions in promoted MIR");
tcx.arena.alloc(promoted)
}
let source = MirSource::from_instance(ty::InstanceDef::DropGlue(def_id, ty));
let mut body =
- new_body(tcx, source, blocks, local_decls_for_sig(&sig, span), sig.inputs().len(), span);
+ new_body(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.
}
fn new_body<'tcx>(
- tcx: TyCtxt<'tcx>,
source: MirSource<'tcx>,
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
local_decls: IndexVec<Local, LocalDecl<'tcx>>,
span: Span,
) -> Body<'tcx> {
Body::new(
- tcx,
source,
basic_blocks,
IndexVec::from_elem_n(
self.def_id,
self.sig.inputs_and_output[0],
));
- new_body(
- self.tcx,
- source,
- self.blocks,
- self.local_decls,
- self.sig.inputs().len(),
- self.span,
- )
+ new_body(source, self.blocks, self.local_decls, self.sig.inputs().len(), self.span)
}
fn source_info(&self) -> SourceInfo {
block(&mut blocks, vec![], TerminatorKind::Resume, true);
}
- let mut body = new_body(
- tcx,
- MirSource::from_instance(instance),
- blocks,
- local_decls,
- sig.inputs().len(),
- span,
- );
+ let mut body =
+ new_body(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()));
let source = MirSource::item(ctor_id);
let body = new_body(
- tcx,
source,
IndexVec::from_elem_n(start_block, 1),
local_decls,
let type_length = instance
.substs
.iter()
- .flat_map(|arg| arg.walk(tcx))
+ .flat_map(|arg| arg.walk())
.filter(|arg| match arg.unpack() {
GenericArgKind::Type(_) | GenericArgKind::Const(_) => true,
GenericArgKind::Lifetime(_) => false,
// When polymorphization is enabled, methods which do not depend on their generic
// parameters, but the self-type of their impl block do will fail to normalize.
- if !tcx.sess.opts.debugging_opts.polymorphize
- || !instance.definitely_needs_subst(tcx)
- {
+ if !tcx.sess.opts.debugging_opts.polymorphize || !instance.needs_subst() {
// This is a method within an impl, find out what the self-type is:
let impl_self_ty = tcx.subst_and_normalize_erasing_regions(
instance.substs,
}
impl<'a, 'tcx> TypeVisitor<'tcx> for MarkUsedGenericParams<'a, 'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !c.potentially_has_param_types_or_consts() {
+ if !c.has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
self.unused_parameters.clear(param.index);
ControlFlow::CONTINUE
}
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted: Some(p)})
+ ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted: Some(p)})
// Avoid considering `T` unused when constants are of the form:
// `<Self as Foo<T>>::foo::promoted[p]`
if self.def_id == def.did && !self.tcx.generics_of(def.did).has_self =>
ty::ConstKind::Unevaluated(uv)
if matches!(self.tcx.def_kind(uv.def.did), DefKind::AnonConst | DefKind::InlineConst) =>
{
- self.visit_child_body(uv.def.did, uv.substs(self.tcx));
+ self.visit_child_body(uv.def.did, uv.substs);
ControlFlow::CONTINUE
}
_ => c.super_visit_with(self),
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.potentially_has_param_types_or_consts() {
+ if !ty.has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
}
/// Visitor used to check if a generic parameter is used.
-struct HasUsedGenericParams<'a, 'tcx> {
- tcx: TyCtxt<'tcx>,
+struct HasUsedGenericParams<'a> {
unused_parameters: &'a FiniteBitSet<u32>,
}
-impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a, 'tcx> {
+impl<'a, 'tcx> TypeVisitor<'tcx> for HasUsedGenericParams<'a> {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
#[instrument(level = "debug", skip(self))]
fn visit_const(&mut self, c: &'tcx Const<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !c.potentially_has_param_types_or_consts() {
+ if !c.has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
#[instrument(level = "debug", skip(self))]
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
- if !ty.potentially_has_param_types_or_consts() {
+ if !ty.has_param_types_or_consts() {
return ControlFlow::CONTINUE;
}
{
type BreakTy = V::BreakTy;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.def_id_visitor.tcx())
- }
-
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<V::BreakTy> {
let tcx = self.def_id_visitor.tcx();
// InternalSubsts are not visited here because they are visited below in `super_visit_with`.
tcx.def_path_hash(def_id).hash_stable(&mut hcx, &mut hasher);
// Include the main item-type. Note that, in this case, the
- // assertions about `definitely_needs_subst` may not hold, but this item-type
+ // 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(tcx));
+ assert!(!item_type.has_erasable_regions());
hcx.while_hashing_spans(false, |hcx| {
hcx.with_node_id_hashing_mode(NodeIdHashingMode::HashDefPath, |hcx| {
item_type.hash_stable(hcx, &mut hasher);
// 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.definitely_has_param_types_or_consts(self.tcx))
- {
+ if impl_trait_ref.is_some() && substs.iter().any(|a| a.has_param_types_or_consts()) {
self = self.path_generic_args(
|this| {
this.path_append_ns(
) -> Result<(), OrphanCheckErr<'tcx>> {
debug!("orphan_check_trait_ref(trait_ref={:?}, in_crate={:?})", trait_ref, in_crate);
- if trait_ref.needs_infer() && trait_ref.definitely_needs_subst(tcx) {
+ if trait_ref.needs_infer() && trait_ref.needs_subst() {
bug!(
"can't orphan check a trait ref with both params and inference variables {:?}",
trait_ref
Node::Leaf(leaf) => {
if leaf.has_infer_types_or_consts() {
failure_kind = FailureKind::MentionsInfer;
- } else if leaf.definitely_has_param_types_or_consts(tcx) {
+ } else if leaf.has_param_types_or_consts() {
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}
Node::Cast(_, _, ty) => {
if ty.has_infer_types_or_consts() {
failure_kind = FailureKind::MentionsInfer;
- } else if ty.definitely_has_param_types_or_consts(tcx) {
+ } else if ty.has_param_types_or_consts() {
failure_kind = cmp::min(failure_kind, FailureKind::MentionsParam);
}
// See #74595 for more details about this.
let concrete = infcx.const_eval_resolve(param_env, uv.expand(), Some(span));
- if concrete.is_ok() && uv.substs(infcx.tcx).definitely_has_param_types_or_consts(infcx.tcx) {
+ if concrete.is_ok() && uv.substs.has_param_types_or_consts() {
match infcx.tcx.def_kind(uv.def.did) {
DefKind::AnonConst | DefKind::InlineConst => {
let mir_body = infcx.tcx.mir_for_ctfe_opt_const_arg(uv.def);
) -> Result<Option<AbstractConst<'tcx>>, ErrorReported> {
let inner = tcx.thir_abstract_const_opt_const_arg(uv.def)?;
debug!("AbstractConst::new({:?}) = {:?}", uv, inner);
- Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs(tcx) }))
+ Ok(inner.map(|inner| AbstractConst { inner, substs: uv.substs }))
}
pub fn from_const(
struct IsThirPolymorphic<'a, 'tcx> {
is_poly: bool,
thir: &'a thir::Thir<'tcx>,
- tcx: TyCtxt<'tcx>,
}
use thir::visit;
}
fn visit_expr(&mut self, expr: &thir::Expr<'tcx>) {
- self.is_poly |= expr.ty.definitely_has_param_types_or_consts(self.tcx);
+ self.is_poly |= expr.ty.has_param_types_or_consts();
if !self.is_poly {
visit::walk_expr(self, expr)
}
}
fn visit_pat(&mut self, pat: &thir::Pat<'tcx>) {
- self.is_poly |= pat.ty.definitely_has_param_types_or_consts(self.tcx);
+ self.is_poly |= pat.ty.has_param_types_or_consts();
if !self.is_poly {
visit::walk_pat(self, pat);
}
}
fn visit_const(&mut self, ct: &'tcx ty::Const<'tcx>) {
- self.is_poly |= ct.definitely_has_param_types_or_consts(self.tcx);
+ self.is_poly |= ct.has_param_types_or_consts();
}
}
- let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body, tcx };
+ let mut is_poly_vis = IsThirPolymorphic { is_poly: false, thir: body };
visit::walk_expr(&mut is_poly_vis, &body[body_id]);
debug!("AbstractConstBuilder: is_poly={}", is_poly_vis.is_poly);
if !is_poly_vis.is_poly {
Err(NotConstEvaluatable::MentionsInfer) => {
pending_obligation.stalled_on.clear();
pending_obligation.stalled_on.extend(
- uv.substs(infcx.tcx)
+ uv.substs
.iter()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
Err(ErrorHandled::TooGeneric) => {
stalled_on.extend(
unevaluated
- .substs(tcx)
+ .substs
.iter()
.filter_map(TyOrConstInferVar::maybe_from_generic_arg),
);
stalled_on: &mut Vec<TyOrConstInferVar<'tcx>>,
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let infcx = self.selcx.infcx();
- if obligation.predicate.is_known_global() {
+ if obligation.predicate.is_global() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if infcx.predicate_must_hold_considering_regions(obligation) {
) -> ProcessResult<PendingPredicateObligation<'tcx>, FulfillmentErrorCode<'tcx>> {
let tcx = self.selcx.tcx();
- if obligation.predicate.is_global(tcx) {
+ if obligation.predicate.is_global() {
// no type variables present, can use evaluation for better caching.
// FIXME: consider caching errors too.
if self.selcx.infcx().predicate_must_hold_considering_regions(obligation) {
selcx: &mut SelectionContext<'a, 'tcx>,
substs: ty::Binder<'tcx, SubstsRef<'tcx>>,
) -> impl Iterator<Item = TyOrConstInferVar<'tcx>> {
- let tcx = selcx.tcx();
selcx
.infcx()
.resolve_vars_if_possible(substs)
.skip_binder() // ok because this check doesn't care about regions
.iter()
.filter(|arg| arg.has_infer_types_or_consts())
- .flat_map(move |arg| {
- let mut walker = arg.walk(tcx);
+ .flat_map(|arg| {
+ let mut walker = arg.walk();
while let Some(c) = walker.next() {
if !c.has_infer_types_or_consts() {
walker.visited.remove(&c);
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.definitely_needs_subst(tcx));
+ predicates.retain(|predicate| !predicate.needs_subst());
let result = impossible_predicates(tcx, predicates);
debug!("subst_and_check_impossible_predicates(key={:?}) = {:?}", key, result);
(predicate, sp): (ty::Predicate<'tcx>, Span),
) -> Option<Span> {
let self_ty = tcx.types.self_param;
- let has_self_ty = |arg: &GenericArg<'tcx>| arg.walk(tcx).any(|arg| arg == self_ty.into());
+ let has_self_ty = |arg: &GenericArg<'_>| arg.walk().any(|arg| arg == self_ty.into());
match predicate.kind().skip_binder() {
ty::PredicateKind::Trait(ref data) => {
// In the case of a trait predicate, we can skip the "self" type.
impl<'tcx> TypeVisitor<'tcx> for IllegalSelfTypeVisitor<'tcx> {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
// The rest of the code is already set up to be lazy about replacing bound vars,
// and only when we actually have to normalize.
if value.has_escaping_bound_vars() {
- let mut max_visitor = MaxEscapingBoundVarVisitor {
- tcx: self.infcx.tcx,
- outer_index: ty::INNERMOST,
- escaping: 0,
- };
+ let mut max_visitor =
+ MaxEscapingBoundVarVisitor { outer_index: ty::INNERMOST, escaping: 0 };
value.visit_with(&mut max_visitor);
if max_visitor.escaping > 0 {
normalizer.universes.extend((0..max_visitor.escaping).map(|_| None));
}
/// Visitor to find the maximum escaping bound var
-struct MaxEscapingBoundVarVisitor<'tcx> {
- tcx: TyCtxt<'tcx>,
+struct MaxEscapingBoundVarVisitor {
// The index which would count as escaping
outer_index: ty::DebruijnIndex,
escaping: usize,
}
-impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
+impl<'tcx> TypeVisitor<'tcx> for MaxEscapingBoundVarVisitor {
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &ty::Binder<'tcx, T>,
let tail_field_ty = tcx.type_of(tail_field.did);
let mut unsizing_params = GrowableBitSet::new_empty();
- for arg in tail_field_ty.walk(tcx) {
+ for arg in tail_field_ty.walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
unsizing_params.insert(i);
}
// Ensure none of the other fields mention the parameters used
// in unsizing.
for field in prefix_fields {
- for arg in tcx.type_of(field.did).walk(tcx) {
+ for arg in tcx.type_of(field.did).walk() {
if let Some(i) = maybe_unsizing_param_idx(arg) {
unsizing_params.remove(i);
}
// contain the "'static" lifetime (any other lifetime
// would either be late-bound or local), so it is guaranteed
// to outlive any other lifetime
- if pred.0.is_global(self.infcx.tcx) && !pred.0.has_late_bound_regions() {
+ if pred.0.is_global() && !pred.0.has_late_bound_regions() {
Ok(EvaluatedToOk)
} else {
Ok(EvaluatedToOkModuloRegions)
mut obligation: TraitObligation<'tcx>,
) -> Result<EvaluationResult, OverflowError> {
if !self.intercrate
- && obligation.is_global(self.tcx())
- && obligation
- .param_env
- .caller_bounds()
- .iter()
- .all(|bound| bound.definitely_needs_subst(self.tcx()))
+ && obligation.is_global()
+ && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst())
{
// 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
// the param_env so that it can be given the lowest priority. See
// #50825 for the motivation for this.
let is_global = |cand: &ty::PolyTraitPredicate<'tcx>| {
- cand.is_global(self.infcx.tcx) && !cand.has_late_bound_regions()
+ cand.is_global() && !cand.has_late_bound_regions()
};
// (*) Prefer `BuiltinCandidate { has_nested: false }`, `PointeeCandidate`,
impl<'a, 'tcx> TypeVisitor<'tcx> for Search<'a, 'tcx> {
type BreakTy = NonStructuralMatchTy<'tcx>;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx())
- }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("Search visiting ty: {:?}", ty);
wf.compute(b.into());
}
ty::PredicateKind::ConstEvaluatable(uv) => {
- let substs = uv.substs(wf.tcx());
- let obligations = wf.nominal_obligations(uv.def.did, substs);
+ let obligations = wf.nominal_obligations(uv.def.did, uv.substs);
wf.out.extend(obligations);
- for arg in substs.iter() {
+ for arg in uv.substs.iter() {
wf.compute(arg);
}
}
/// Pushes all the predicates needed to validate that `ty` is WF into `out`.
fn compute(&mut self, arg: GenericArg<'tcx>) {
- let mut walker = arg.walk(self.tcx());
+ let mut walker = arg.walk();
let param_env = self.param_env;
let depth = self.recursion_depth;
while let Some(arg) = walker.next() {
GenericArgKind::Const(constant) => {
match constant.val {
ty::ConstKind::Unevaluated(uv) => {
- assert!(uv.promoted.is_none());
- let substs = uv.substs(self.tcx());
-
- let obligations = self.nominal_obligations(uv.def.did, substs);
+ let obligations = self.nominal_obligations(uv.def.did, uv.substs);
self.out.extend(obligations);
- let predicate = ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(
- ty::Unevaluated::new(uv.def, substs),
- ))
- .to_predicate(self.tcx());
+ let predicate =
+ ty::Binder::dummy(ty::PredicateKind::ConstEvaluatable(uv.shrink()))
+ .to_predicate(self.tcx());
let cause = self.cause(traits::MiscObligation);
self.out.push(traits::Obligation::with_depth(
cause,
tcx: TyCtxt<'tcx>,
ty: Binder<'tcx, T>,
) -> (T, chalk_ir::VariableKinds<RustInterner<'tcx>>, BTreeMap<DefId, u32>) {
- let mut bound_vars_collector = BoundVarsCollector::new(tcx);
+ let mut bound_vars_collector = BoundVarsCollector::new();
ty.as_ref().skip_binder().visit_with(&mut bound_vars_collector);
let mut parameters = bound_vars_collector.parameters;
let named_parameters: BTreeMap<DefId, u32> = bound_vars_collector
}
crate struct BoundVarsCollector<'tcx> {
- tcx: TyCtxt<'tcx>,
binder_index: ty::DebruijnIndex,
crate parameters: BTreeMap<u32, chalk_ir::VariableKind<RustInterner<'tcx>>>,
crate named_parameters: Vec<DefId>,
}
impl<'tcx> BoundVarsCollector<'tcx> {
- crate fn new(tcx: TyCtxt<'tcx>) -> Self {
+ crate fn new() -> Self {
BoundVarsCollector {
- tcx,
binder_index: ty::INNERMOST,
parameters: BTreeMap::new(),
named_parameters: vec![],
}
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
}
impl<'tcx> TypeVisitor<'tcx> for PlaceholdersCollector {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // Anon const substs do not contain placeholders by default.
- None
- }
-
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match t.kind() {
ty::Placeholder(p) if p.universe == self.universe_index => {
impl<'tcx> TypeVisitor<'tcx> for BoundVarsCollector<'tcx> {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // Anon const substs do not contain bound vars by default.
- None
- }
fn visit_binder<T: TypeFoldable<'tcx>>(
&mut self,
t: &Binder<'tcx, T>,
predicates.extend(environment);
}
- // It's important that we include the default substs in unevaluated
- // constants, since `Unevaluated` instances in predicates whose substs are None
- // can lead to "duplicate" caller bounds candidates during trait selection,
- // duplicate in the sense that both have their default substs, but the
- // candidate that resulted from a superpredicate still uses `None` in its
- // `substs_` field of `Unevaluated` to indicate that it has its default substs,
- // whereas the other candidate has `substs_: Some(default_substs)`, see
- // issue #89334
- predicates = tcx.expose_default_const_substs(predicates);
-
let local_did = def_id.as_local();
let hir_id = local_did.map(|def_id| tcx.hir().local_def_id_to_hir_id(def_id));
// constituents are well-formed.
NodeKind::InherentImpl => {
let self_ty = tcx.type_of(def_id);
- inputs.extend(self_ty.walk(tcx));
+ inputs.extend(self_ty.walk());
}
// In an fn, we assume that the arguments and all their constituents are
let fn_sig = tcx.fn_sig(def_id);
let fn_sig = tcx.liberate_late_bound_regions(def_id, fn_sig);
- inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk(tcx)));
+ inputs.extend(fn_sig.inputs().iter().flat_map(|ty| ty.walk()));
}
NodeKind::Other => (),
// Does this have parameters? Used to determine whether substitution is
// required.
/// Does this have `Param`?
- const HAS_KNOWN_TY_PARAM = 1 << 0;
+ const HAS_TY_PARAM = 1 << 0;
/// Does this have `ReEarlyBound`?
- const HAS_KNOWN_RE_PARAM = 1 << 1;
+ const HAS_RE_PARAM = 1 << 1;
/// Does this have `ConstKind::Param`?
- const HAS_KNOWN_CT_PARAM = 1 << 2;
+ const HAS_CT_PARAM = 1 << 2;
- const KNOWN_NEEDS_SUBST = TypeFlags::HAS_KNOWN_TY_PARAM.bits
- | TypeFlags::HAS_KNOWN_RE_PARAM.bits
- | TypeFlags::HAS_KNOWN_CT_PARAM.bits;
+ const NEEDS_SUBST = TypeFlags::HAS_TY_PARAM.bits
+ | TypeFlags::HAS_RE_PARAM.bits
+ | TypeFlags::HAS_CT_PARAM.bits;
/// Does this have `Infer`?
- const HAS_TY_INFER = 1 << 3;
+ const HAS_TY_INFER = 1 << 3;
/// Does this have `ReVar`?
- const HAS_RE_INFER = 1 << 4;
+ const HAS_RE_INFER = 1 << 4;
/// Does this have `ConstKind::Infer`?
- const HAS_CT_INFER = 1 << 5;
+ const HAS_CT_INFER = 1 << 5;
/// Does this have inference variables? Used to determine whether
/// inference is required.
- const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits
- | TypeFlags::HAS_RE_INFER.bits
- | TypeFlags::HAS_CT_INFER.bits;
+ const NEEDS_INFER = TypeFlags::HAS_TY_INFER.bits
+ | TypeFlags::HAS_RE_INFER.bits
+ | TypeFlags::HAS_CT_INFER.bits;
/// Does this have `Placeholder`?
- const HAS_TY_PLACEHOLDER = 1 << 6;
+ const HAS_TY_PLACEHOLDER = 1 << 6;
/// Does this have `RePlaceholder`?
- const HAS_RE_PLACEHOLDER = 1 << 7;
+ const HAS_RE_PLACEHOLDER = 1 << 7;
/// Does this have `ConstKind::Placeholder`?
- const HAS_CT_PLACEHOLDER = 1 << 8;
+ const HAS_CT_PLACEHOLDER = 1 << 8;
/// `true` if there are "names" of regions and so forth
/// that are local to a particular fn/inferctxt
- const HAS_KNOWN_FREE_LOCAL_REGIONS = 1 << 9;
+ const HAS_FREE_LOCAL_REGIONS = 1 << 9;
/// `true` if there are "names" of types and regions and so forth
/// that are local to a particular fn
- const HAS_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;
+ 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;
/// 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_KNOWN_FREE_REGIONS = 1 << 14;
-
- const HAS_POTENTIAL_FREE_REGIONS = TypeFlags::HAS_KNOWN_FREE_REGIONS.bits
- | TypeFlags::HAS_UNKNOWN_DEFAULT_CONST_SUBSTS.bits;
+ const HAS_FREE_REGIONS = 1 << 14;
/// 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?
- ///
- /// 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;
+ 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;
-
- /// 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;
-
+ const HAS_CT_FRESH = 1 << 19;
}
}
if self.is_object && has_default {
let default_ty = tcx.at(self.span).type_of(param.def_id);
let self_param = tcx.types.self_param;
- if default_ty.walk(tcx).any(|arg| arg == self_param.into()) {
+ if default_ty.walk().any(|arg| arg == self_param.into()) {
// There is no suitable inference default for a type parameter
// that references self, in an object type.
return true;
// A `Self` within the original bound will be substituted with a
// `trait_object_dummy_self`, so check for that.
let references_self =
- pred.skip_binder().ty.walk(tcx).any(|arg| arg == dummy_self.into());
+ pred.skip_binder().ty.walk().any(|arg| arg == dummy_self.into());
// If the projection output contains `Self`, force the user to
// elaborate it explicitly to avoid a lot of complexity.
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.definitely_needs_subst(tcx) {
+ if forbid_generic && normalized_ty.needs_subst() {
let mut err = tcx.sess.struct_span_err(
path.span,
"generic `Self` types are currently not permitted in anonymous constants",
debug!(?item, ?span);
struct FoundParentLifetime;
- struct FindParentLifetimeVisitor<'tcx>(TyCtxt<'tcx>, &'tcx ty::Generics);
+ struct FindParentLifetimeVisitor<'tcx>(&'tcx ty::Generics);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for FindParentLifetimeVisitor<'tcx> {
type BreakTy = FoundParentLifetime;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.0)
- }
fn visit_region(&mut self, r: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("FindParentLifetimeVisitor: r={:?}", r);
if let RegionKind::ReEarlyBound(ty::EarlyBoundRegion { index, .. }) = r {
- if *index < self.1.parent_count as u32 {
+ if *index < self.0.parent_count as u32 {
return ControlFlow::Break(FoundParentLifetime);
} else {
return ControlFlow::CONTINUE;
impl<'tcx> ty::fold::TypeVisitor<'tcx> for ProhibitOpaqueVisitor<'tcx> {
type BreakTy = Ty<'tcx>;
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
debug!("check_opaque_for_inheriting_lifetimes: (visit_ty) t={:?}", t);
if t == self.opaque_identity_ty {
ControlFlow::CONTINUE
} else {
- t.super_visit_with(&mut FindParentLifetimeVisitor(self.tcx, self.generics))
+ t.super_visit_with(&mut FindParentLifetimeVisitor(self.generics))
.map_break(|FoundParentLifetime| t)
}
}
return;
}
- for leaf in ty.walk(tcx) {
+ for leaf in ty.walk() {
if let GenericArgKind::Type(leaf_ty) = leaf.unpack() {
if let ty::Param(param) = leaf_ty.kind() {
debug!("found use of ty param {:?}", param);
{
struct OpaqueTypeCollector(Vec<DefId>);
impl<'tcx> ty::fold::TypeVisitor<'tcx> for OpaqueTypeCollector {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- // Default anon const substs cannot contain opaque types.
- None
- }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
ty::Opaque(def, _) => {
) {
debug!("fcx {}", 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 },
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);
// 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>(&self, t: T) -> bool
+ fn can_contain_user_lifetime_bounds<T>(t: T) -> bool
where
T: TypeFoldable<'tcx>,
{
- t.has_free_regions(self.tcx) || t.has_projections() || t.has_infer_types()
+ t.has_free_regions() || t.has_projections() || t.has_infer_types()
}
pub fn node_ty(&self, id: hir::HirId) -> Ty<'tcx> {
let ty = self.resolve_vars_if_possible(ty);
// We walk the argument type because the argument's type could have
// been `Option<T>`, but the `FulfillmentError` references `T`.
- if ty.walk(self.tcx).any(|arg| arg == self_) { Some(i) } else { None }
+ if ty.walk().any(|arg| arg == self_) { Some(i) } else { None }
})
.collect::<Vec<usize>>();
}
}
if let Some(missing_trait) = missing_trait {
- let mut visitor = TypeParamVisitor(self.tcx, vec![]);
+ let mut visitor = TypeParamVisitor(vec![]);
visitor.visit_ty(lhs_ty);
if op.node == hir::BinOpKind::Add
// This has nothing here because it means we did string
// concatenation (e.g., "Hello " + "World!"). This means
// we don't want the note in the else clause to be emitted
- } else if let [ty] = &visitor.1[..] {
+ } else if let [ty] = &visitor.0[..] {
if let ty::Param(p) = *ty.kind() {
// Check if the method would be found if the type param wasn't
// involved. If so, it means that adding a trait bound to the param is
}
}
-struct TypeParamVisitor<'tcx>(TyCtxt<'tcx>, Vec<Ty<'tcx>>);
+struct TypeParamVisitor<'tcx>(Vec<Ty<'tcx>>);
impl<'tcx> TypeVisitor<'tcx> for TypeParamVisitor<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.0)
- }
fn visit_ty(&mut self, ty: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(_) = ty.kind() {
- self.1.push(ty);
+ self.0.push(ty);
}
ty.super_visit_with(self)
}
// of the function signature. In our example, the GAT in the return
// type is `<Self as LendingIterator>::Item<'a>`, so 'a and Self are arguments.
let (regions, types) =
- GATSubstCollector::visit(tcx, trait_item.def_id.to_def_id(), sig.output());
+ GATSubstCollector::visit(trait_item.def_id.to_def_id(), sig.output());
// If both regions and types are empty, then this GAT isn't in the
// return type, and we shouldn't try to do clause analysis
/// the two vectors, `regions` and `types` (depending on their kind). For each
/// parameter `Pi` also track the index `i`.
struct GATSubstCollector<'tcx> {
- tcx: TyCtxt<'tcx>,
gat: DefId,
// Which region appears and which parameter index its subsituted for
regions: FxHashSet<(ty::Region<'tcx>, usize)>,
impl<'tcx> GATSubstCollector<'tcx> {
fn visit<T: TypeFoldable<'tcx>>(
- tcx: TyCtxt<'tcx>,
gat: DefId,
t: T,
) -> (FxHashSet<(ty::Region<'tcx>, usize)>, FxHashSet<(Ty<'tcx>, usize)>) {
- let mut visitor = GATSubstCollector {
- tcx,
- gat,
- regions: FxHashSet::default(),
- types: FxHashSet::default(),
- };
+ let mut visitor =
+ GATSubstCollector { gat, regions: FxHashSet::default(), types: FxHashSet::default() };
t.visit_with(&mut visitor);
(visitor.regions, visitor.types)
}
}
t.super_visit_with(self)
}
-
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
}
fn could_be_self(trait_def_id: LocalDefId, ty: &hir::Ty<'_>) -> bool {
// 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.definitely_needs_subst(tcx) {
+ if !ty.needs_subst() {
fcx.register_wf_obligation(
ty.into(),
tcx.def_span(param.def_id),
// 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.definitely_needs_subst(tcx) {
+ if !default_ct.needs_subst() {
fcx.register_wf_obligation(
default_ct.into(),
tcx.def_span(param.def_id),
if is_our_default(param) {
let default_ty = tcx.type_of(param.def_id);
// ... and it's not a dependent default, ...
- if !default_ty.definitely_needs_subst(tcx) {
+ if !default_ty.needs_subst() {
// ... then substitute it with the default.
return default_ty.into();
}
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.definitely_needs_subst(tcx) {
+ if !default_ct.needs_subst() {
// ... then substitute it with the default.
return default_ct.into();
}
.predicates
.iter()
.flat_map(|&(pred, sp)| {
- struct CountParams<'tcx> {
- tcx: TyCtxt<'tcx>,
+ #[derive(Default)]
+ struct CountParams {
params: FxHashSet<u32>,
}
- impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams<'tcx> {
+ impl<'tcx> ty::fold::TypeVisitor<'tcx> for CountParams {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
if let ty::Param(param) = t.kind() {
c.super_visit_with(self)
}
}
- let mut param_count = CountParams { tcx: fcx.tcx, params: FxHashSet::default() };
+ let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
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.definitely_has_param_types_or_consts(tcx)
+ if substituted_pred.has_param_types_or_consts()
|| param_count.params.len() > 1
|| has_region
{
for obligation in implied_obligations {
let pred = obligation.predicate;
// Match the existing behavior.
- if pred.is_global(fcx.tcx) && !pred.has_late_bound_regions() {
+ if pred.is_global() && !pred.has_late_bound_regions() {
let pred = fcx.normalize_associated_types_in(span, pred);
let hir_node = fcx.tcx.hir().find(id);
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(self.tcx()));
+ assert!(!ty.needs_infer() && !ty.has_placeholders() && !ty.has_free_regions());
self.typeck_results.node_types_mut().insert(hir_id, ty);
}
self.tcx
}
fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
- if ty.has_type_flags(ty::TypeFlags::HAS_POTENTIAL_FREE_REGIONS) {
+ if ty.has_type_flags(ty::TypeFlags::HAS_FREE_REGIONS) {
ty.super_fold_with(self)
} else {
ty
pub fn provide(providers: &mut Providers) {
*providers = Providers {
opt_const_param_of: type_of::opt_const_param_of,
- default_anon_const_substs: type_of::default_anon_const_substs,
type_of: type_of::type_of,
item_bounds: item_bounds::item_bounds,
explicit_item_bounds: item_bounds::explicit_item_bounds,
tcx,
&mut predicates,
trait_ref,
- &mut cgp::parameters_for_impl(tcx, self_ty, trait_ref),
+ &mut cgp::parameters_for_impl(self_ty, trait_ref),
);
}
use rustc_hir::intravisit::Visitor;
use rustc_hir::{HirId, Node};
use rustc_middle::hir::map::Map;
-use rustc_middle::ty::subst::{InternalSubsts, SubstsRef};
+use rustc_middle::ty::subst::InternalSubsts;
use rustc_middle::ty::util::IntTypeExt;
use rustc_middle::ty::{self, DefIdTree, Ty, TyCtxt, TypeFoldable, TypeFolder};
use rustc_span::symbol::Ident;
arg_path
}
-pub(super) fn default_anon_const_substs(tcx: TyCtxt<'_>, def_id: DefId) -> SubstsRef<'_> {
- let generics = tcx.generics_of(def_id);
- if let Some(parent) = generics.parent {
- // This is the reason we bother with having optional anon const substs.
- //
- // In the future the substs of an anon const will depend on its parents predicates
- // at which point eagerly looking at them will cause a query cycle.
- //
- // So for now this is only an assurance that this approach won't cause cycle errors in
- // the future.
- let _cycle_check = tcx.predicates_of(parent);
- }
-
- 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() {
- let allowed_flags = ty::TypeFlags::MAY_NEED_DEFAULT_CONST_SUBSTS
- | ty::TypeFlags::STILL_FURTHER_SPECIALIZABLE
- | ty::TypeFlags::HAS_ERROR;
- assert!(!arg.has_type_flags(!allowed_flags));
- }
- substs
-}
-
pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: DefId) -> Ty<'_> {
let def_id = def_id.expect_local();
use rustc_hir::*;
/// Returns the set of parameters constrained by the impl header.
pub fn parameters_for_impl<'tcx>(
- tcx: TyCtxt<'tcx>,
impl_self_ty: Ty<'tcx>,
impl_trait_ref: Option<ty::TraitRef<'tcx>>,
) -> FxHashSet<Parameter> {
let vec = match impl_trait_ref {
- Some(tr) => parameters_for(tcx, &tr, false),
- None => parameters_for(tcx, &impl_self_ty, false),
+ Some(tr) => parameters_for(&tr, false),
+ None => parameters_for(&impl_self_ty, false),
};
vec.into_iter().collect()
}
/// of parameters whose values are needed in order to constrain `ty` - these
/// differ, with the latter being a superset, in the presence of projections.
pub fn parameters_for<'tcx>(
- tcx: TyCtxt<'tcx>,
t: &impl TypeFoldable<'tcx>,
include_nonconstraining: bool,
) -> Vec<Parameter> {
- let mut collector = ParameterCollector { tcx, parameters: vec![], include_nonconstraining };
+ let mut collector = ParameterCollector { parameters: vec![], include_nonconstraining };
t.visit_with(&mut collector);
collector.parameters
}
-struct ParameterCollector<'tcx> {
- tcx: TyCtxt<'tcx>,
+struct ParameterCollector {
parameters: Vec<Parameter>,
include_nonconstraining: bool,
}
-impl<'tcx> TypeVisitor<'tcx> for ParameterCollector<'tcx> {
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.tcx)
- }
-
+impl<'tcx> TypeVisitor<'tcx> for ParameterCollector {
fn visit_ty(&mut self, t: Ty<'tcx>) -> ControlFlow<Self::BreakTy> {
match *t.kind() {
ty::Projection(..) | ty::Opaque(..) if !self.include_nonconstraining => {
// `<<T as Bar>::Baz as Iterator>::Output = <U as Iterator>::Output`
// Then the projection only applies if `T` is known, but it still
// does not determine `U`.
- let inputs = parameters_for(tcx, &projection.projection_ty, true);
+ let inputs = parameters_for(&projection.projection_ty, true);
let relies_only_on_inputs = inputs.iter().all(|p| input_parameters.contains(p));
if !relies_only_on_inputs {
continue;
}
- input_parameters.extend(parameters_for(tcx, &projection.ty, false));
+ input_parameters.extend(parameters_for(&projection.ty, false));
} else {
continue;
}
let impl_predicates = tcx.predicates_of(impl_def_id);
let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
- let mut input_parameters = cgp::parameters_for_impl(tcx, impl_self_ty, impl_trait_ref);
+ let mut input_parameters = cgp::parameters_for_impl(impl_self_ty, impl_trait_ref);
cgp::identify_constrained_generic_params(
tcx,
impl_predicates,
match item.kind {
ty::AssocKind::Type => {
if item.defaultness.has_value() {
- cgp::parameters_for(tcx, &tcx.type_of(def_id), true)
+ cgp::parameters_for(&tcx.type_of(def_id), true)
} else {
Vec::new()
}
continue;
}
- unconstrained_parameters.extend(cgp::parameters_for(tcx, &projection_ty, true));
+ unconstrained_parameters.extend(cgp::parameters_for(&projection_ty, true));
- for param in cgp::parameters_for(tcx, &projected_ty, false) {
+ for param in cgp::parameters_for(&projected_ty, false) {
if !unconstrained_parameters.contains(¶m) {
constrained_params.insert(param.0);
}
}
- unconstrained_parameters.extend(cgp::parameters_for(tcx, &projected_ty, true));
+ unconstrained_parameters.extend(cgp::parameters_for(&projected_ty, true));
}
}
parent_substs: &Vec<GenericArg<'tcx>>,
span: Span,
) {
- let mut base_params = cgp::parameters_for(tcx, parent_substs, true);
+ let mut base_params = cgp::parameters_for(parent_substs, true);
base_params.sort_by_key(|param| param.0);
if let (_, [duplicate, ..]) = base_params.partition_dedup() {
let param = impl1_substs[duplicate.0 as usize];
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(tcx) => (),
+ _ if predicate.is_global() => (),
// We allow specializing on explicitly marked traits with no associated
// items.
ty::PredicateKind::Trait(ty::TraitPredicate {
required_predicates: &mut RequiredPredicates<'tcx>,
explicit_map: &mut ExplicitPredicatesMap<'tcx>,
) {
- // We must not look into the default substs of consts
- // as computing those depends on the results of `predicates_of`.
- //
- // Luckily the only types contained in default substs are type
- // parameters which don't matter here.
- //
- // FIXME(adt_const_params): Once complex const parameter types
- // are allowed, this might be incorrect. I think that we will still be
- // fine, as all outlives relations of the const param types should also
- // be part of the adt containing it, but we should still both update the
- // documentation and add some tests for this.
- for arg in field_ty.walk_ignoring_default_const_substs() {
+ for arg in field_ty.walk() {
let ty = match arg.unpack() {
GenericArgKind::Type(ty) => ty,
// 'b`.
if let Some(self_ty) = ignored_self_ty {
if let GenericArgKind::Type(ty) = outlives_predicate.0.unpack() {
- if ty.walk(tcx).any(|arg| arg == self_ty.into()) {
+ if ty.walk().any(|arg| arg == self_ty.into()) {
debug!("skipping self ty = {:?}", &ty);
continue;
}
match &val.val {
ty::ConstKind::Unevaluated(uv) => {
- let substs = uv.substs(self.tcx());
- self.add_constraints_from_invariant_substs(current, substs, variance);
+ self.add_constraints_from_invariant_substs(current, uv.substs, variance);
}
_ => {}
}
crate fn print_const(cx: &DocContext<'_>, n: &ty::Const<'_>) -> String {
match n.val {
- ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs_: _, promoted }) => {
+ ty::ConstKind::Unevaluated(ty::Unevaluated { def, substs: _, promoted }) => {
let mut s = if let Some(def) = def.as_local() {
let hir_id = cx.tcx.hir().local_def_id_to_hir_id(def.did);
print_const_expr(cx.tcx, cx.tcx.hir().body_owned_by(hir_id))
- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:35
- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
+ // + span: $DIR/const-promotion-extern-static.rs:9:31: 9:44
-+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[HASH]::BAR), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:6 ~ const_promotion_extern_static[HASH]::BAR), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:9:31: 9:44
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:9:34: 9:35
- _3 = [move _4]; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:46
- _2 = &_3; // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
+ // + span: $DIR/const-promotion-extern-static.rs:13:31: 13:55
-+ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[HASH]::FOO), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &[&i32; 1], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:7 ~ const_promotion_extern_static[HASH]::FOO), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &(*_6); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
_1 = move _2 as &[&i32] (Pointer(Unsize)); // scope 0 at $DIR/const-promotion-extern-static.rs:13:31: 13:55
- StorageDead(_4); // scope 0 at $DIR/const-promotion-extern-static.rs:13:45: 13:46
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
- // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
- // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[i32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ bad_op_unsafe_oob_for_slices[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_3 = _9; // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_2 = &raw const (*_3); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
_1 = move _2 as *const [i32] (Pointer(Unsize)); // scope 0 at $DIR/bad_op_unsafe_oob_for_slices.rs:5:25: 5:35
// + val: Unevaluated(FOO, [], None)
// mir::Constant
// + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[HASH]::main::FOO), const_param_did: None }, substs_: Some([]), promoted: None }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ const_prop_fails_gracefully[HASH]::main::FOO), const_param_did: None }, substs: [], promoted: None }) }
_2 = &raw const (*_3); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
_1 = move _2 as usize (Misc); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:13: 7:39
StorageDead(_2); // scope 0 at $DIR/const_prop_fails_gracefully.rs:7:38: 7:39
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/ref_deref.rs:5:6: 5:10
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_2 = _4; // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
- _1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
+ _1 = const 4_i32; // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
+ // + val: Unevaluated(main, [], Some(promoted[0]))
+ // mir::Constant
+ // + span: $DIR/ref_deref.rs:5:6: 5:10
-+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &(*_4); // scope 0 at $DIR/ref_deref.rs:5:6: 5:10
_1 = (*_2); // scope 0 at $DIR/ref_deref.rs:5:5: 5:10
- StorageDead(_3); // scope 0 at $DIR/ref_deref.rs:5:10: 5:11
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/ref_deref_project.rs:5:6: 5:17
- // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
StorageDead(_2); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
+ // + val: Unevaluated(main, [], Some(promoted[0]))
+ // mir::Constant
+ // + span: $DIR/ref_deref_project.rs:5:6: 5:17
-+ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
++ // + literal: Const { ty: &(i32, i32), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ ref_deref_project[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
+ _2 = &((*_4).1: i32); // scope 0 at $DIR/ref_deref_project.rs:5:6: 5:17
_1 = (*_2); // scope 0 at $DIR/ref_deref_project.rs:5:5: 5:17
- StorageDead(_3); // scope 0 at $DIR/ref_deref_project.rs:5:17: 5:18
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/slice_len.rs:5:6: 5:19
- // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
_3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
StorageLive(_10); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/slice_len.rs:5:6: 5:19
- // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &[u32; 3], val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ slice_len[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_4 = _9; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
_3 = _4; // scope 0 at $DIR/slice_len.rs:5:6: 5:19
StorageLive(_10); // scope 0 at $DIR/slice_len.rs:5:6: 5:19
// + val: Unevaluated(bar, [], Some(promoted[1]))
// mir::Constant
// + span: $DIR/inline-retag.rs:12:7: 12:9
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[HASH]::bar), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[1]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[HASH]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[1]) }) }
Retag(_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
_4 = &(*_10); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
Retag(_4); // scope 1 at $DIR/inline-retag.rs:12:7: 12:9
// + val: Unevaluated(bar, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/inline-retag.rs:12:11: 12:14
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[HASH]::bar), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:4 ~ inline_retag[HASH]::bar), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
_7 = &(*_9); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
Retag(_7); // scope 1 at $DIR/inline-retag.rs:12:11: 12:14
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_8 = _20; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.0: &i32) = move _7; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_6.1: &i32) = move _8; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:3 ~ issue_73223[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_11 = _28; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.0: &i32) = move _10; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
(_9.1: &i32) = move _11; // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(discriminant, [T], Some(promoted[2]))
// mir::Constant
// + span: $DIR/lower_intrinsics.rs:75:42: 75:44
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[HASH]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[2]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[HASH]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[2]) }) }
_7 = &(*_19); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
_6 = &(*_7); // scope 0 at $DIR/lower_intrinsics.rs:75:42: 75:44
- _5 = discriminant_value::<i32>(move _6) -> bb2; // scope 0 at $DIR/lower_intrinsics.rs:75:5: 75:45
// + val: Unevaluated(discriminant, [T], Some(promoted[1]))
// mir::Constant
// + span: $DIR/lower_intrinsics.rs:76:42: 76:45
- // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[HASH]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[1]) }) }
+ // + literal: Const { ty: &(), val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[HASH]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[1]) }) }
_11 = &(*_18); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
_10 = &(*_11); // scope 0 at $DIR/lower_intrinsics.rs:76:42: 76:45
- _9 = discriminant_value::<()>(move _10) -> bb3; // scope 0 at $DIR/lower_intrinsics.rs:76:5: 76:46
// + val: Unevaluated(discriminant, [T], Some(promoted[0]))
// mir::Constant
// + span: $DIR/lower_intrinsics.rs:77:42: 77:47
- // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[HASH]::discriminant), const_param_did: None }, substs_: Some([T]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &E, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:29 ~ lower_intrinsics[HASH]::discriminant), const_param_did: None }, substs: [T], promoted: Some(promoted[0]) }) }
_15 = &(*_17); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
_14 = &(*_15); // scope 0 at $DIR/lower_intrinsics.rs:77:42: 77:47
- _13 = discriminant_value::<E>(move _14) -> bb4; // scope 0 at $DIR/lower_intrinsics.rs:77:5: 77:48
// + val: Unevaluated(full_tested_match, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/match_false_edges.rs:16:14: 16:15
- // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[HASH]::full_tested_match), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &std::option::Option<i32>, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:5 ~ match_false_edges[HASH]::full_tested_match), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
_6 = &(((*_11) as Some).0: i32); // scope 0 at $DIR/match_false_edges.rs:16:14: 16:15
_4 = &shallow _2; // scope 0 at $DIR/match_false_edges.rs:15:19: 15:27
StorageLive(_7); // scope 0 at $DIR/match_false_edges.rs:16:20: 16:27
// + val: Unevaluated(array_casts, [], Some(promoted[0]))
// mir::Constant
// + span: $SRC_DIR/core/src/macros/mod.rs:LL:COL
- // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[HASH]::array_casts), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &usize, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:15 ~ retag[HASH]::array_casts), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
_18 = &(*_35); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
Retag(_18); // scope 5 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
// + val: Unevaluated(main, [], Some(promoted[0]))
// mir::Constant
// + span: $DIR/retag.rs:47:21: 47:23
- // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[HASH]::main), const_param_did: None }, substs_: Some([]), promoted: Some(promoted[0]) }) }
+ // + literal: Const { ty: &i32, val: Unevaluated(Unevaluated { def: WithOptConstParam { did: DefId(0:13 ~ retag[HASH]::main), const_param_did: None }, substs: [], promoted: Some(promoted[0]) }) }
Retag(_28); // scope 7 at $DIR/retag.rs:47:21: 47:23
_23 = &(*_28); // scope 7 at $DIR/retag.rs:47:21: 47:23
Retag(_23); // scope 7 at $DIR/retag.rs:47:21: 47:23
// skip if there is a `self` parameter binding to a type
// that contains `Self` (i.e.: `self: Box<Self>`), see #4804
if let Some(trait_self_ty) = self.trait_self_ty {
- if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(self.cx.tcx, cmt.place.ty(), trait_self_ty)
- {
+ if map.name(cmt.hir_id) == kw::SelfLower && contains_ty(cmt.place.ty(), trait_self_ty) {
return;
}
}
if let Some(init) = local.init;
then {
let init_ty = cx.typeck_results().expr_ty(init);
- let contains_sync_guard = init_ty.walk(cx.tcx).any(|inner| match inner.unpack() {
+ let contains_sync_guard = init_ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => {
SYNC_GUARD_PATHS.iter().any(|path| match_type(cx, inner_ty, path))
},
if same_item_push_visitor.should_lint();
if let Some((vec, pushed_item)) = same_item_push_visitor.vec_push;
let vec_ty = cx.typeck_results().expr_ty(vec);
- let ty = vec_ty.walk(cx.tcx).nth(1).unwrap().expect_ty();
+ let ty = vec_ty.walk().nth(1).unwrap().expect_ty();
if cx
.tcx
.lang_items()
// walk the return type and check for Self (this does not check associated types)
if let Some(self_adt) = self_ty.ty_adt_def() {
- if contains_adt_constructor(cx.tcx, ret_ty, self_adt) {
+ if contains_adt_constructor(ret_ty, self_adt) {
return;
}
- } else if contains_ty(cx.tcx, ret_ty, self_ty) {
+ } else if contains_ty(ret_ty, self_ty) {
return;
}
if let ty::PredicateKind::Projection(projection_predicate) = predicate.kind().skip_binder() {
// walk the associated type and check for Self
if let Some(self_adt) = self_ty.ty_adt_def() {
- if contains_adt_constructor(cx.tcx, projection_predicate.ty, self_adt) {
+ if contains_adt_constructor(projection_predicate.ty, self_adt) {
return;
}
- } else if contains_ty(cx.tcx, projection_predicate.ty, self_ty) {
+ } else if contains_ty(projection_predicate.ty, self_ty) {
return;
}
}
if let TraitItemKind::Fn(_, _) = item.kind;
let ret_ty = return_ty(cx, item.hir_id());
let self_ty = TraitRef::identity(cx.tcx, item.def_id.to_def_id()).self_ty().skip_binder();
- if !contains_ty(cx.tcx, ret_ty, self_ty);
+ if !contains_ty(ret_ty, self_ty);
then {
span_lint(
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(cx.tcx))
+ .filter(|p| !p.is_global())
.filter_map(|obligation| {
// Note that we do not want to deal with qualified predicates here.
match obligation.predicate.kind().no_bound_vars() {
let result = cx.tcx.const_eval_resolve(
cx.param_env,
- ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
+ ty::Unevaluated::new(
+ ty::WithOptConstParam::unknown(def_id),
+ substs,
+ ),
None,
);
is_value_unfrozen_raw(cx, result, ty)
non_send_fields.push(NonSendField {
def: field_def,
ty: field_ty,
- generic_params: collect_generic_params(cx, field_ty),
+ generic_params: collect_generic_params(field_ty),
})
}
}
/// Given a type, collect all of its generic parameters.
/// Example: `MyStruct<P, Box<Q, R>>` => `vec![P, Q, R]`
-fn collect_generic_params<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Vec<Ty<'tcx>> {
- ty.walk(cx.tcx)
+fn collect_generic_params(ty: Ty<'_>) -> Vec<Ty<'_>> {
+ ty.walk()
.filter_map(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => Some(inner_ty),
_ => None,
/// Checks if the type contains any pointer-like types in substs (including nested ones)
fn contains_pointer_like<'tcx>(cx: &LateContext<'tcx>, target_ty: Ty<'tcx>) -> bool {
- for ty_node in target_ty.walk(cx.tcx) {
+ for ty_node in target_ty.walk() {
if let GenericArgKind::Type(inner_ty) = ty_node.unpack() {
match inner_ty.kind() {
ty::RawPtr(_) => {
visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor as _},
Mutability,
};
-use rustc_middle::ty::{self, fold::TypeVisitor, Ty, TyCtxt};
+use rustc_middle::ty::{self, fold::TypeVisitor, Ty};
use rustc_mir_dataflow::{Analysis, AnalysisDomain, CallReturnPlaces, GenKill, GenKillAnalysis, ResultsCursor};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::source_map::{BytePos, Span};
self.possible_borrower.add(borrowed.local, lhs);
},
other => {
- if ContainsRegion(self.cx.tcx)
+ if ContainsRegion
.visit_ty(place.ty(&self.body.local_decls, self.cx.tcx).ty)
.is_continue()
{
.flat_map(HybridBitSet::iter)
.collect();
- if ContainsRegion(self.cx.tcx)
+ if ContainsRegion
.visit_ty(self.body.local_decls[*dest].ty)
.is_break()
{
}
}
-struct ContainsRegion<'tcx>(TyCtxt<'tcx>);
+struct ContainsRegion;
-impl<'tcx> TypeVisitor<'tcx> for ContainsRegion<'tcx> {
+impl TypeVisitor<'_> for ContainsRegion {
type BreakTy = ();
- fn tcx_for_anon_const_substs(&self) -> Option<TyCtxt<'tcx>> {
- Some(self.0)
- }
- fn visit_region(&mut self, _: ty::Region<'tcx>) -> ControlFlow<Self::BreakTy> {
+ fn visit_region(&mut self, _: ty::Region<'_>) -> ControlFlow<Self::BreakTy> {
ControlFlow::BREAK
}
}
.fn_sig(def_id)
.output()
.skip_binder()
- .walk(self.cx.tcx)
+ .walk()
.any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)));
}
// Ensure method is constructor-like
if let Some(self_adt) = self_ty.ty_adt_def() {
- if !contains_adt_constructor(cx.tcx, ret_ty, self_adt) {
+ if !contains_adt_constructor(ret_ty, self_adt) {
return;
}
- } else if !contains_ty(cx.tcx, ret_ty, self_ty) {
+ } else if !contains_ty(ret_ty, self_ty) {
return;
}
let ty = cx.typeck_results().expr_ty(expr);
matches!(ty.kind(), ty::Ref(..))
|| ty
- .walk(cx.tcx)
+ .walk()
.any(|arg| matches!(arg.unpack(), GenericArgKind::Lifetime(_)))
}
//
// See also https://github.com/rust-lang/rust-clippy/issues/2894.
for (impl_hir_ty, trait_sem_ty) in impl_inputs_outputs.zip(trait_method_sig.inputs_and_output) {
- if trait_sem_ty.walk(cx.tcx).any(|inner| inner == self_ty.into()) {
+ if trait_sem_ty.walk().any(|inner| inner == self_ty.into()) {
let mut visitor = SkipTyCollector::default();
visitor.visit_ty(impl_hir_ty);
types_to_skip.extend(visitor.types_to_skip);
.tcx
.const_eval_resolve(
self.param_env,
- ty::Unevaluated::new(ty::WithOptConstParam::unknown(def_id), substs),
+ ty::Unevaluated::new(
+ ty::WithOptConstParam::unknown(def_id),
+ substs,
+ ),
None,
)
.ok()
.predicates_of(did)
.predicates
.iter()
- .filter_map(|(p, _)| if p.is_global(cx.tcx) { Some(*p) } else { None });
+ .filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
traits::impossible_predicates(
cx.tcx,
traits::elaborate_predicates(cx.tcx, predicates)
if is_primitive {
// if we have wrappers like Array, Slice or Tuple, print these
// and get the type enclosed in the slice ref
- match expr_type.peel_refs().walk(cx.tcx).nth(1).unwrap().expect_ty().kind() {
+ match expr_type.peel_refs().walk().nth(1).unwrap().expect_ty().kind() {
rustc_ty::Slice(..) => return Some("slice".into()),
rustc_ty::Array(..) => return Some("array".into()),
rustc_ty::Tuple(..) => return Some("tuple".into()),
// is_recursively_primitive_type() should have taken care
// of the rest and we can rely on the type that is found
let refs_peeled = expr_type.peel_refs();
- return Some(refs_peeled.walk(cx.tcx).last().unwrap().to_string());
+ return Some(refs_peeled.walk().last().unwrap().to_string());
},
}
}
}
fn check_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, span: Span) -> McfResult {
- for arg in ty.walk(tcx) {
+ for arg in ty.walk() {
let ty = match arg.unpack() {
GenericArgKind::Type(ty) => ty,
}
/// Walks into `ty` and returns `true` if any inner type is the same as `other_ty`
-pub fn contains_ty<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, other_ty: Ty<'tcx>) -> bool {
- ty.walk(tcx).any(|inner| match inner.unpack() {
+pub fn contains_ty(ty: Ty<'_>, other_ty: Ty<'_>) -> bool {
+ ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => ty::TyS::same_type(other_ty, inner_ty),
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
})
/// Walks into `ty` and returns `true` if any inner type is an instance of the given adt
/// constructor.
-pub fn contains_adt_constructor<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, adt: &'tcx AdtDef) -> bool {
- ty.walk(tcx).any(|inner| match inner.unpack() {
+pub fn contains_adt_constructor(ty: Ty<'_>, adt: &AdtDef) -> bool {
+ ty.walk().any(|inner| match inner.unpack() {
GenericArgKind::Type(inner_ty) => inner_ty.ty_adt_def() == Some(adt),
GenericArgKind::Lifetime(_) | GenericArgKind::Const(_) => false,
})
.iter()
.all(|field| is_normalizable_helper(cx, param_env, field.ty(cx.tcx, substs), cache))
}),
- _ => ty.walk(cx.tcx).all(|generic_arg| match generic_arg.unpack() {
+ _ => ty.walk().all(|generic_arg| match generic_arg.unpack() {
GenericArgKind::Type(inner_ty) if inner_ty != ty => {
is_normalizable_helper(cx, param_env, inner_ty, cache)
},