Auto merge of #96883 - jackh726:early-binder-2, r=oli-obk

Add EarlyBinder

Chalk has no concept of `Param` (e0ade19d13/chalk-ir/src/lib.rs (L579)) or `ReEarlyBound` (e0ade19d13/chalk-ir/src/lib.rs (L1308)). Everything  is just "bound" - the equivalent of rustc's late-bound. It's not completely clear yet whether to move everything to the same time of binder in rustc or add `Param` and `ReEarlyBound` in Chalk.

Either way, tracking when we have or haven't already substituted out these in rustc can be helpful.

As a first step, I'm just adding a `EarlyBinder` newtype that is required to call `subst`. I also add a couple "transparent" `bound_*` wrappers around a couple query that are often immediately substituted.

r? `@nikomatsakis`
This commit is contained in:
bors 2022-05-14 23:53:11 +00:00
commit 2a8a0fc423
67 changed files with 400 additions and 217 deletions

View file

@ -70,7 +70,7 @@ use rustc_middle::ty::{
self,
error::TypeError,
subst::{GenericArgKind, Subst, SubstsRef},
Binder, List, Region, Ty, TyCtxt, TypeFoldable,
Binder, EarlyBinder, List, Region, Ty, TyCtxt, TypeFoldable,
};
use rustc_span::{sym, BytePos, DesugaringKind, Pos, Span};
use rustc_target::spec::abi;
@ -961,12 +961,14 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
for (def_id, actual) in iter::zip(default_params, substs.iter().rev()) {
match actual.unpack() {
GenericArgKind::Const(c) => {
if self.tcx.const_param_default(def_id).subst(self.tcx, substs) != c {
if EarlyBinder(self.tcx.const_param_default(def_id)).subst(self.tcx, substs)
!= c
{
break;
}
}
GenericArgKind::Type(ty) => {
if self.tcx.type_of(def_id).subst(self.tcx, substs) != ty {
if self.tcx.bound_type_of(def_id).subst(self.tcx, substs) != ty {
break;
}
}
@ -1383,8 +1385,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
(ty::FnDef(did1, substs1), ty::FnDef(did2, substs2)) => {
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
let mut values = self.cmp_fn_sig(&sig1, &sig2);
let path1 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did1, substs1));
let path2 = format!(" {{{}}}", self.tcx.def_path_str_with_substs(*did2, substs2));
@ -1395,7 +1397,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
(ty::FnDef(did1, substs1), ty::FnPtr(sig2)) => {
let sig1 = self.tcx.fn_sig(*did1).subst(self.tcx, substs1);
let sig1 = self.tcx.bound_fn_sig(*did1).subst(self.tcx, substs1);
let mut values = self.cmp_fn_sig(&sig1, sig2);
values.0.push_highlighted(format!(
" {{{}}}",
@ -1405,7 +1407,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
}
(ty::FnPtr(sig1), ty::FnDef(did2, substs2)) => {
let sig2 = self.tcx.fn_sig(*did2).subst(self.tcx, substs2);
let sig2 = self.tcx.bound_fn_sig(*did2).subst(self.tcx, substs2);
let mut values = self.cmp_fn_sig(sig1, &sig2);
values.1.push_normal(format!(
" {{{}}}",
@ -1847,9 +1849,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
// Future::Output
let item_def_id = self.tcx.associated_item_def_ids(future_trait)[0];
let bounds = self.tcx.explicit_item_bounds(*def_id);
let bounds = self.tcx.bound_explicit_item_bounds(*def_id);
for (predicate, _) in bounds {
for predicate in bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
let predicate = predicate.subst(self.tcx, substs);
let output = predicate
.kind()

View file

@ -561,9 +561,9 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
obligations = self.at(&cause, param_env).eq(prev, hidden_ty)?.obligations;
}
let item_bounds = tcx.explicit_item_bounds(def_id);
let item_bounds = tcx.bound_explicit_item_bounds(def_id);
for (predicate, _) in item_bounds {
for predicate in item_bounds.transpose_iter().map(|e| e.map_bound(|(p, _)| *p)) {
debug!(?predicate);
let predicate = predicate.subst(tcx, substs);

View file

@ -4,7 +4,7 @@ use rustc_data_structures::captures::Captures;
use rustc_data_structures::sso::SsoHashSet;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, GenericArgKind, Subst};
use rustc_middle::ty::{self, Ty, TyCtxt};
use rustc_middle::ty::{self, EarlyBinder, Ty, TyCtxt};
/// The `TypeOutlives` struct has the job of "lowering" a `T: 'a`
/// obligation into a series of `'a: 'b` constraints and "verifys", as
@ -290,7 +290,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
debug!("projection_bounds(projection_ty={:?})", projection_ty);
let tcx = self.tcx;
self.region_bounds_declared_on_associated_item(projection_ty.item_def_id)
.map(move |r| r.subst(tcx, projection_ty.substs))
.map(move |r| EarlyBinder(r).subst(tcx, projection_ty.substs))
}
/// Given the `DefId` of an associated item, returns any region