a small wf and clause cleanup
This commit is contained in:
parent
c1f86f0bc8
commit
a4f6770d83
@ -16,6 +16,7 @@ use rustc_infer::traits::util;
|
|||||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||||
use rustc_middle::ty::fold::BottomUpFolder;
|
use rustc_middle::ty::fold::BottomUpFolder;
|
||||||
use rustc_middle::ty::util::ExplicitSelf;
|
use rustc_middle::ty::util::ExplicitSelf;
|
||||||
|
use rustc_middle::ty::ToPredicate;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{
|
||||||
self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
self, GenericArgs, Ty, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt,
|
||||||
};
|
};
|
||||||
@ -2279,16 +2280,16 @@ pub(super) fn check_type_bounds<'tcx>(
|
|||||||
//
|
//
|
||||||
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
|
// impl<T> X for T where T: X { type Y = <T as X>::Y; }
|
||||||
}
|
}
|
||||||
_ => predicates.push(ty::Clause::from_projection_clause(
|
_ => predicates.push(
|
||||||
tcx,
|
|
||||||
ty::Binder::bind_with_vars(
|
ty::Binder::bind_with_vars(
|
||||||
ty::ProjectionPredicate {
|
ty::ProjectionPredicate {
|
||||||
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
|
projection_ty: tcx.mk_alias_ty(trait_ty.def_id, rebased_args),
|
||||||
term: normalize_impl_ty.into(),
|
term: normalize_impl_ty.into(),
|
||||||
},
|
},
|
||||||
bound_vars,
|
bound_vars,
|
||||||
),
|
)
|
||||||
)),
|
.to_predicate(tcx),
|
||||||
|
),
|
||||||
};
|
};
|
||||||
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
|
ty::ParamEnv::new(tcx.mk_clauses(&predicates), Reveal::UserFacing)
|
||||||
};
|
};
|
||||||
|
@ -1105,11 +1105,11 @@ fn check_associated_type_bounds(wfcx: &WfCheckingCtxt<'_, '_>, item: ty::AssocIt
|
|||||||
let wf_obligations =
|
let wf_obligations =
|
||||||
bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
|
bounds.instantiate_identity_iter_copied().flat_map(|(bound, bound_span)| {
|
||||||
let normalized_bound = wfcx.normalize(span, None, bound);
|
let normalized_bound = wfcx.normalize(span, None, bound);
|
||||||
traits::wf::predicate_obligations(
|
traits::wf::clause_obligations(
|
||||||
wfcx.infcx,
|
wfcx.infcx,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
wfcx.body_def_id,
|
wfcx.body_def_id,
|
||||||
normalized_bound.as_predicate(),
|
normalized_bound,
|
||||||
bound_span,
|
bound_span,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
@ -1209,7 +1209,7 @@ fn check_impl<'tcx>(
|
|||||||
wfcx.infcx,
|
wfcx.infcx,
|
||||||
wfcx.param_env,
|
wfcx.param_env,
|
||||||
wfcx.body_def_id,
|
wfcx.body_def_id,
|
||||||
&trait_pred,
|
trait_pred,
|
||||||
ast_trait_ref.path.span,
|
ast_trait_ref.path.span,
|
||||||
item,
|
item,
|
||||||
);
|
);
|
||||||
@ -1418,13 +1418,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|
|||||||
debug!(?predicates.predicates);
|
debug!(?predicates.predicates);
|
||||||
assert_eq!(predicates.predicates.len(), predicates.spans.len());
|
assert_eq!(predicates.predicates.len(), predicates.spans.len());
|
||||||
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
|
let wf_obligations = predicates.into_iter().flat_map(|(p, sp)| {
|
||||||
traits::wf::predicate_obligations(
|
traits::wf::clause_obligations(infcx, wfcx.param_env, wfcx.body_def_id, p, sp)
|
||||||
infcx,
|
|
||||||
wfcx.param_env,
|
|
||||||
wfcx.body_def_id,
|
|
||||||
p.as_predicate(),
|
|
||||||
sp,
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
|
let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
|
||||||
wfcx.register_obligations(obligations);
|
wfcx.register_obligations(obligations);
|
||||||
|
@ -578,11 +578,6 @@ impl rustc_errors::IntoDiagnosticArg for Clause<'_> {
|
|||||||
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
|
pub struct Clause<'tcx>(Interned<'tcx, WithCachedTypeInfo<ty::Binder<'tcx, PredicateKind<'tcx>>>>);
|
||||||
|
|
||||||
impl<'tcx> Clause<'tcx> {
|
impl<'tcx> Clause<'tcx> {
|
||||||
pub fn from_projection_clause(tcx: TyCtxt<'tcx>, pred: PolyProjectionPredicate<'tcx>) -> Self {
|
|
||||||
let pred: Predicate<'tcx> = pred.to_predicate(tcx);
|
|
||||||
pred.expect_clause()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn as_predicate(self) -> Predicate<'tcx> {
|
pub fn as_predicate(self) -> Predicate<'tcx> {
|
||||||
Predicate(self.0)
|
Predicate(self.0)
|
||||||
}
|
}
|
||||||
@ -1296,12 +1291,25 @@ impl<'tcx> ToPredicate<'tcx, PolyTraitPredicate<'tcx>> for Binder<'tcx, TraitRef
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
|
||||||
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
|
PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
|
impl<'tcx> ToPredicate<'tcx> for PolyTraitPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
||||||
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
|
self.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).to_predicate(tcx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for TraitPredicate<'tcx> {
|
||||||
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||||
|
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||||
|
p.expect_clause()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
|
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyTraitPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||||
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||||
@ -1340,9 +1348,10 @@ impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for ProjectionPredicate<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> ToPredicate<'tcx> for TraitPredicate<'tcx> {
|
impl<'tcx> ToPredicate<'tcx, Clause<'tcx>> for PolyProjectionPredicate<'tcx> {
|
||||||
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Predicate<'tcx> {
|
fn to_predicate(self, tcx: TyCtxt<'tcx>) -> Clause<'tcx> {
|
||||||
PredicateKind::Clause(ClauseKind::Trait(self)).to_predicate(tcx)
|
let p: Predicate<'tcx> = self.to_predicate(tcx);
|
||||||
|
p.expect_clause()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -725,7 +725,7 @@ impl<'tcx> PolyExistentialPredicate<'tcx> {
|
|||||||
self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx)
|
self.rebind(tr).with_self_ty(tcx, self_ty).to_predicate(tcx)
|
||||||
}
|
}
|
||||||
ExistentialPredicate::Projection(p) => {
|
ExistentialPredicate::Projection(p) => {
|
||||||
ty::Clause::from_projection_clause(tcx, self.rebind(p.with_self_ty(tcx, self_ty)))
|
self.rebind(p.with_self_ty(tcx, self_ty)).to_predicate(tcx)
|
||||||
}
|
}
|
||||||
ExistentialPredicate::AutoTrait(did) => {
|
ExistentialPredicate::AutoTrait(did) => {
|
||||||
let generics = tcx.generics_of(did);
|
let generics = tcx.generics_of(did);
|
||||||
|
@ -346,14 +346,13 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
|
|||||||
ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
|
ty::TraitRef::from_lang_item(tcx, LangItem::Sized, DUMMY_SP, [output])
|
||||||
});
|
});
|
||||||
|
|
||||||
let pred = ty::Clause::from_projection_clause(
|
let pred = tupled_inputs_and_output
|
||||||
tcx,
|
.map_bound(|(inputs, output)| ty::ProjectionPredicate {
|
||||||
tupled_inputs_and_output.map_bound(|(inputs, output)| ty::ProjectionPredicate {
|
|
||||||
projection_ty: tcx
|
projection_ty: tcx
|
||||||
.mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
|
.mk_alias_ty(goal.predicate.def_id(), [goal.predicate.self_ty(), inputs]),
|
||||||
term: output.into(),
|
term: output.into(),
|
||||||
}),
|
})
|
||||||
);
|
.to_predicate(tcx);
|
||||||
|
|
||||||
// A built-in `Fn` impl only holds if the output is sized.
|
// A built-in `Fn` impl only holds if the output is sized.
|
||||||
// (FIXME: technically we only need to check this if the type is a fn ptr...)
|
// (FIXME: technically we only need to check this if the type is a fn ptr...)
|
||||||
|
@ -1644,7 +1644,7 @@ fn assemble_candidates_from_object_ty<'cx, 'tcx>(
|
|||||||
let env_predicates = data
|
let env_predicates = data
|
||||||
.projection_bounds()
|
.projection_bounds()
|
||||||
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
|
.filter(|bound| bound.item_def_id() == obligation.predicate.def_id)
|
||||||
.map(|p| ty::Clause::from_projection_clause(tcx, p.with_self_ty(tcx, object_ty)));
|
.map(|p| p.with_self_ty(tcx, object_ty).to_predicate(tcx));
|
||||||
|
|
||||||
assemble_candidates_from_predicates(
|
assemble_candidates_from_predicates(
|
||||||
selcx,
|
selcx,
|
||||||
|
@ -105,13 +105,13 @@ pub fn unnormalized_obligations<'tcx>(
|
|||||||
|
|
||||||
/// Returns the obligations that make this trait reference
|
/// Returns the obligations that make this trait reference
|
||||||
/// well-formed. For example, if there is a trait `Set` defined like
|
/// well-formed. For example, if there is a trait `Set` defined like
|
||||||
/// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
|
/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
|
||||||
/// if `Bar: Eq`.
|
/// if `Bar: Eq`.
|
||||||
pub fn trait_obligations<'tcx>(
|
pub fn trait_obligations<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: LocalDefId,
|
body_id: LocalDefId,
|
||||||
trait_pred: &ty::TraitPredicate<'tcx>,
|
trait_pred: ty::TraitPredicate<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
item: &'tcx hir::Item<'tcx>,
|
item: &'tcx hir::Item<'tcx>,
|
||||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
@ -129,12 +129,17 @@ pub fn trait_obligations<'tcx>(
|
|||||||
wf.normalize(infcx)
|
wf.normalize(infcx)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Returns the requirements for `clause` to be well-formed.
|
||||||
|
///
|
||||||
|
/// For example, if there is a trait `Set` defined like
|
||||||
|
/// `trait Set<K: Eq>`, then the trait bound `Foo: Set<Bar>` is WF
|
||||||
|
/// if `Bar: Eq`.
|
||||||
#[instrument(skip(infcx), ret)]
|
#[instrument(skip(infcx), ret)]
|
||||||
pub fn predicate_obligations<'tcx>(
|
pub fn clause_obligations<'tcx>(
|
||||||
infcx: &InferCtxt<'tcx>,
|
infcx: &InferCtxt<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
body_id: LocalDefId,
|
body_id: LocalDefId,
|
||||||
predicate: ty::Predicate<'tcx>,
|
clause: ty::Clause<'tcx>,
|
||||||
span: Span,
|
span: Span,
|
||||||
) -> Vec<traits::PredicateObligation<'tcx>> {
|
) -> Vec<traits::PredicateObligation<'tcx>> {
|
||||||
let mut wf = WfPredicates {
|
let mut wf = WfPredicates {
|
||||||
@ -148,45 +153,32 @@ pub fn predicate_obligations<'tcx>(
|
|||||||
};
|
};
|
||||||
|
|
||||||
// It's ok to skip the binder here because wf code is prepared for it
|
// It's ok to skip the binder here because wf code is prepared for it
|
||||||
match predicate.kind().skip_binder() {
|
match clause.kind().skip_binder() {
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
|
ty::ClauseKind::Trait(t) => {
|
||||||
wf.compute_trait_pred(&t, Elaborate::None);
|
wf.compute_trait_pred(t, Elaborate::None);
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(..)) => {}
|
ty::ClauseKind::RegionOutlives(..) => {}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(
|
ty::ClauseKind::TypeOutlives(ty::OutlivesPredicate(ty, _reg)) => {
|
||||||
ty,
|
|
||||||
_reg,
|
|
||||||
))) => {
|
|
||||||
wf.compute(ty.into());
|
wf.compute(ty.into());
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::Projection(t)) => {
|
ty::ClauseKind::Projection(t) => {
|
||||||
wf.compute_projection(t.projection_ty);
|
wf.compute_projection(t.projection_ty);
|
||||||
wf.compute(match t.term.unpack() {
|
wf.compute(match t.term.unpack() {
|
||||||
ty::TermKind::Ty(ty) => ty.into(),
|
ty::TermKind::Ty(ty) => ty.into(),
|
||||||
ty::TermKind::Const(c) => c.into(),
|
ty::TermKind::Const(c) => c.into(),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, ty)) => {
|
ty::ClauseKind::ConstArgHasType(ct, ty) => {
|
||||||
wf.compute(ct.into());
|
wf.compute(ct.into());
|
||||||
wf.compute(ty.into());
|
wf.compute(ty.into());
|
||||||
}
|
}
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
|
ty::ClauseKind::WellFormed(arg) => {
|
||||||
wf.compute(arg);
|
wf.compute(arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(ct)) => {
|
ty::ClauseKind::ConstEvaluatable(ct) => {
|
||||||
wf.compute(ct.into());
|
wf.compute(ct.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
ty::PredicateKind::ObjectSafe(_)
|
|
||||||
| ty::PredicateKind::ClosureKind(..)
|
|
||||||
| ty::PredicateKind::Subtype(..)
|
|
||||||
| ty::PredicateKind::Coerce(..)
|
|
||||||
| ty::PredicateKind::ConstEquate(..)
|
|
||||||
| ty::PredicateKind::Ambiguous
|
|
||||||
| ty::PredicateKind::AliasRelate(..) => {
|
|
||||||
bug!("We should only wf check where clauses, unexpected predicate: {predicate:?}")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wf.normalize(infcx)
|
wf.normalize(infcx)
|
||||||
@ -233,7 +225,7 @@ enum Elaborate {
|
|||||||
|
|
||||||
fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: &ty::TraitRef<'tcx>,
|
trait_ref: ty::TraitRef<'tcx>,
|
||||||
item: Option<&hir::Item<'tcx>>,
|
item: Option<&hir::Item<'tcx>>,
|
||||||
cause: &mut traits::ObligationCause<'tcx>,
|
cause: &mut traits::ObligationCause<'tcx>,
|
||||||
pred: ty::Predicate<'tcx>,
|
pred: ty::Predicate<'tcx>,
|
||||||
@ -336,9 +328,9 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
|
/// Pushes the obligations required for `trait_ref` to be WF into `self.out`.
|
||||||
fn compute_trait_pred(&mut self, trait_pred: &ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
|
fn compute_trait_pred(&mut self, trait_pred: ty::TraitPredicate<'tcx>, elaborate: Elaborate) {
|
||||||
let tcx = self.tcx();
|
let tcx = self.tcx();
|
||||||
let trait_ref = &trait_pred.trait_ref;
|
let trait_ref = trait_pred.trait_ref;
|
||||||
|
|
||||||
// Negative trait predicates don't require supertraits to hold, just
|
// Negative trait predicates don't require supertraits to hold, just
|
||||||
// that their args are WF.
|
// that their args are WF.
|
||||||
@ -411,7 +403,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
|||||||
|
|
||||||
// Compute the obligations that are required for `trait_ref` to be WF,
|
// Compute the obligations that are required for `trait_ref` to be WF,
|
||||||
// given that it is a *negative* trait predicate.
|
// given that it is a *negative* trait predicate.
|
||||||
fn compute_negative_trait_pred(&mut self, trait_ref: &ty::TraitRef<'tcx>) {
|
fn compute_negative_trait_pred(&mut self, trait_ref: ty::TraitRef<'tcx>) {
|
||||||
for arg in trait_ref.args {
|
for arg in trait_ref.args {
|
||||||
self.compute(arg);
|
self.compute(arg);
|
||||||
}
|
}
|
||||||
|
@ -3,9 +3,8 @@ use rustc_hir as hir;
|
|||||||
use rustc_hir::def::DefKind;
|
use rustc_hir::def::DefKind;
|
||||||
use rustc_index::bit_set::BitSet;
|
use rustc_index::bit_set::BitSet;
|
||||||
use rustc_middle::query::Providers;
|
use rustc_middle::query::Providers;
|
||||||
use rustc_middle::ty::{
|
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt, TypeVisitor};
|
||||||
self, EarlyBinder, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor,
|
use rustc_middle::ty::{ToPredicate, TypeSuperVisitable, TypeVisitable};
|
||||||
};
|
|
||||||
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
use rustc_span::def_id::{DefId, LocalDefId, CRATE_DEF_ID};
|
||||||
use rustc_span::DUMMY_SP;
|
use rustc_span::DUMMY_SP;
|
||||||
use rustc_trait_selection::traits;
|
use rustc_trait_selection::traits;
|
||||||
@ -214,10 +213,10 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
|
|||||||
// strategy, then just reinterpret the associated type like an opaque :^)
|
// strategy, then just reinterpret the associated type like an opaque :^)
|
||||||
let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args);
|
let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).instantiate(self.tcx, shifted_alias_ty.args);
|
||||||
|
|
||||||
self.predicates.push(ty::Clause::from_projection_clause(self.tcx, ty::Binder::bind_with_vars(
|
self.predicates.push(ty::Binder::bind_with_vars(
|
||||||
ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() },
|
ty::ProjectionPredicate { projection_ty: shifted_alias_ty, term: default_ty.into() },
|
||||||
self.bound_vars,
|
self.bound_vars,
|
||||||
)));
|
).to_predicate(self.tcx));
|
||||||
|
|
||||||
// We walk the *un-shifted* alias ty, because we're tracking the de bruijn
|
// We walk the *un-shifted* alias ty, because we're tracking the de bruijn
|
||||||
// binder depth, and if we were to walk `shifted_alias_ty` instead, we'd
|
// binder depth, and if we were to walk `shifted_alias_ty` instead, we'd
|
||||||
|
Loading…
x
Reference in New Issue
Block a user