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

@ -26,7 +26,7 @@ use rustc_hir::lang_items::LangItem;
use rustc_hir::{GenericArg, GenericArgs};
use rustc_middle::ty::subst::{self, GenericArgKind, InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{self, Const, DefIdTree, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, Const, DefIdTree, EarlyBinder, Ty, TyCtxt, TypeFoldable};
use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECTS};
use rustc_span::edition::Edition;
use rustc_span::lev_distance::find_best_match_for_name;
@ -523,7 +523,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
self.astconv
.normalize_ty(
self.span,
tcx.at(self.span).type_of(param.def_id).subst(tcx, substs),
EarlyBinder(tcx.at(self.span).type_of(param.def_id))
.subst(tcx, substs),
)
.into()
}
@ -543,7 +544,9 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
GenericParamDefKind::Const { has_default } => {
let ty = tcx.at(self.span).type_of(param.def_id);
if !infer_args && has_default {
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
EarlyBinder(tcx.const_param_default(param.def_id))
.subst(tcx, substs.unwrap())
.into()
} else {
if infer_args {
self.astconv.ct_infer(ty, Some(param), self.span).into()
@ -1292,7 +1295,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
item_segment: &hir::PathSegment<'_>,
) -> Ty<'tcx> {
let substs = self.ast_path_substs_for_ty(span, did, item_segment);
self.normalize_ty(span, self.tcx().at(span).type_of(did).subst(self.tcx(), substs))
self.normalize_ty(
span,
EarlyBinder(self.tcx().at(span).type_of(did)).subst(self.tcx(), substs),
)
}
fn conv_object_ty_poly_trait_ref(
@ -2441,7 +2447,8 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
true,
None,
);
self.normalize_ty(span, tcx.at(span).type_of(def_id).subst(tcx, substs))
EarlyBinder(self.normalize_ty(span, tcx.at(span).type_of(def_id)))
.subst(tcx, substs)
}
hir::TyKind::Array(ref ty, ref length) => {
let length = match length {
@ -2684,7 +2691,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
trait_ref.def_id,
)?;
let fn_sig = tcx.fn_sig(assoc.def_id).subst(
let fn_sig = tcx.bound_fn_sig(assoc.def_id).subst(
tcx,
trait_ref.substs.extend_to(tcx, assoc.def_id, |param, _| tcx.mk_param_from_def(param)),
);

View file

@ -339,7 +339,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> Ty<'tcx> {
let (fn_sig, def_id) = match *callee_ty.kind() {
ty::FnDef(def_id, subst) => {
let fn_sig = self.tcx.fn_sig(def_id).subst(self.tcx, subst);
let fn_sig = self.tcx.bound_fn_sig(def_id).subst(self.tcx, subst);
// Unit testing: function items annotated with
// `#[rustc_evaluate_where_clauses]` trigger special output

View file

@ -171,7 +171,7 @@ pub(super) fn check_fn<'a, 'tcx>(
let va_list_did = tcx.require_lang_item(LangItem::VaList, Some(span));
let region = fcx.next_region_var(RegionVariableOrigin::MiscVariable(span));
Some(tcx.type_of(va_list_did).subst(tcx, &[region.into()]))
Some(tcx.bound_type_of(va_list_did).subst(tcx, &[region.into()]))
} else {
None
};
@ -655,7 +655,7 @@ fn check_opaque_meets_bounds<'tcx>(
span: Span,
origin: &hir::OpaqueTyOrigin,
) {
let hidden_type = tcx.type_of(def_id).subst(tcx, substs);
let hidden_type = tcx.bound_type_of(def_id.to_def_id()).subst(tcx, substs);
let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
let defining_use_anchor = match *origin {

View file

@ -175,19 +175,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) -> (Option<ExpectedSig<'tcx>>, Option<ty::ClosureKind>) {
match *expected_ty.kind() {
ty::Opaque(def_id, substs) => {
let bounds = self.tcx.explicit_item_bounds(def_id);
let sig = bounds.iter().find_map(|(pred, span)| match pred.kind().skip_binder() {
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
Some(*span),
pred.kind().rebind(proj_predicate.subst(self.tcx, substs)),
),
_ => None,
});
let bounds = self.tcx.bound_explicit_item_bounds(def_id);
let sig = bounds
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(pred, span)| match pred.0.kind().skip_binder() {
ty::PredicateKind::Projection(proj_predicate) => self
.deduce_sig_from_projection(
Some(span.0),
pred.0.kind().rebind(
pred.map_bound(|_| proj_predicate).subst(self.tcx, substs),
),
),
_ => None,
});
let kind = bounds
.iter()
.filter_map(|(pred, _)| match pred.kind().skip_binder() {
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.filter_map(|(pred, _)| match pred.0.kind().skip_binder() {
ty::PredicateKind::Trait(tp) => {
self.tcx.fn_trait_kind_from_lang_item(tp.def_id())
}
@ -668,7 +674,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
),
};
let item_bounds = self.tcx.explicit_item_bounds(def_id);
let item_bounds = self.tcx.bound_explicit_item_bounds(def_id);
// Search for a pending obligation like
//
@ -676,17 +682,21 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
//
// where R is the return type we are expecting. This type `T`
// will be our output.
let output_ty = item_bounds.iter().find_map(|&(predicate, span)| {
let bound_predicate = predicate.subst(self.tcx, substs).kind();
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder() {
self.deduce_future_output_from_projection(
span,
bound_predicate.rebind(proj_predicate),
)
} else {
None
}
});
let output_ty = item_bounds
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.find_map(|(predicate, span)| {
let bound_predicate = predicate.subst(self.tcx, substs).kind();
if let ty::PredicateKind::Projection(proj_predicate) = bound_predicate.skip_binder()
{
self.deduce_future_output_from_projection(
span.0,
bound_predicate.rebind(proj_predicate),
)
} else {
None
}
});
debug!("deduce_future_output_from_obligations: output_ty={:?}", output_ty);
output_ty

View file

@ -265,9 +265,8 @@ fn compare_predicate_entailment<'tcx>(
let impl_fty = tcx.mk_fn_ptr(ty::Binder::dummy(impl_sig));
debug!("compare_impl_method: impl_fty={:?}", impl_fty);
// First liberate late bound regions and subst placeholders
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, tcx.fn_sig(trait_m.def_id));
let trait_sig = trait_sig.subst(tcx, trait_to_placeholder_substs);
let trait_sig = tcx.bound_fn_sig(trait_m.def_id).subst(tcx, trait_to_placeholder_substs);
let trait_sig = tcx.liberate_late_bound_regions(impl_m.def_id, trait_sig);
let trait_sig =
inh.normalize_associated_types_in(impl_m_span, impl_m_hir_id, param_env, trait_sig);
// Add the resulting inputs and output as well-formed.
@ -1066,7 +1065,7 @@ crate fn compare_const_impl<'tcx>(
// Compute placeholder form of impl and trait const tys.
let impl_ty = tcx.type_of(impl_c.def_id);
let trait_ty = tcx.type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
let trait_ty = tcx.bound_type_of(trait_c.def_id).subst(tcx, trait_to_impl_substs);
let mut cause = ObligationCause::new(
impl_c_span,
impl_c_hir_id,
@ -1452,14 +1451,15 @@ pub fn check_type_bounds<'tcx>(
};
let obligations = tcx
.explicit_item_bounds(trait_ty.def_id)
.iter()
.map(|&(bound, span)| {
.bound_explicit_item_bounds(trait_ty.def_id)
.transpose_iter()
.map(|e| e.map_bound(|e| *e).transpose_tuple2())
.map(|(bound, span)| {
debug!(?bound);
let concrete_ty_bound = bound.subst(tcx, rebased_substs);
debug!("check_type_bounds: concrete_ty_bound = {:?}", concrete_ty_bound);
traits::Obligation::new(mk_cause(span), param_env, concrete_ty_bound)
traits::Obligation::new(mk_cause(span.0), param_env, concrete_ty_bound)
})
.collect();
debug!("check_type_bounds: item_bounds={:?}", obligations);

View file

@ -8,7 +8,7 @@ use rustc_infer::traits::TraitEngineExt as _;
use rustc_middle::ty::error::TypeError;
use rustc_middle::ty::relate::{Relate, RelateResult, TypeRelation};
use rustc_middle::ty::subst::{Subst, SubstsRef};
use rustc_middle::ty::{self, Predicate, Ty, TyCtxt};
use rustc_middle::ty::{self, EarlyBinder, Predicate, Ty, TyCtxt};
use rustc_span::Span;
use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
use rustc_trait_selection::traits::query::dropck_outlives::AtExt;
@ -84,7 +84,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
let drop_impl_span = tcx.def_span(drop_impl_did);
let fresh_impl_substs =
infcx.fresh_substs_for_item(drop_impl_span, drop_impl_did.to_def_id());
let fresh_impl_self_ty = drop_impl_ty.subst(tcx, fresh_impl_substs);
let fresh_impl_self_ty = EarlyBinder(drop_impl_ty).subst(tcx, fresh_impl_substs);
let cause = &ObligationCause::misc(drop_impl_span, drop_impl_hir_id);
match infcx.at(cause, impl_param_env).eq(named_type, fresh_impl_self_ty) {

View file

@ -23,8 +23,8 @@ use rustc_middle::ty::subst::{
self, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSelfTy, UserSubsts,
};
use rustc_middle::ty::{
self, AdtKind, CanonicalUserType, DefIdTree, GenericParamDefKind, ToPolyTraitRef, ToPredicate,
Ty, UserType,
self, AdtKind, CanonicalUserType, DefIdTree, EarlyBinder, GenericParamDefKind, ToPolyTraitRef,
ToPredicate, Ty, UserType,
};
use rustc_session::lint;
use rustc_span::hygiene::DesugaringKind;
@ -347,7 +347,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
T: TypeFoldable<'tcx>,
{
debug!("instantiate_type_scheme(value={:?}, substs={:?})", value, substs);
let value = value.subst(self.tcx, substs);
let value = EarlyBinder(value).subst(self.tcx, substs);
let result = self.normalize_associated_types_in(span, value);
debug!("instantiate_type_scheme = {:?}", result);
result
@ -838,9 +838,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
let def_kind = self.tcx.def_kind(def_id);
let item_ty = if let DefKind::Variant = def_kind {
self.tcx.type_of(self.tcx.parent(def_id))
self.tcx.bound_type_of(self.tcx.parent(def_id))
} else {
self.tcx.type_of(def_id)
self.tcx.bound_type_of(def_id)
};
let substs = self.infcx.fresh_substs_for_item(span, def_id);
let ty = item_ty.subst(self.tcx, substs);
@ -1044,8 +1044,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
) {
let (sig, did, substs) = match (&expected.kind(), &found.kind()) {
(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);
if sig1 != sig2 {
return;
}
@ -1056,7 +1056,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
(sig1, *did1, substs1)
}
(ty::FnDef(did, substs), ty::FnPtr(sig2)) => {
let sig1 = self.tcx.fn_sig(*did).subst(self.tcx, substs);
let sig1 = self.tcx.bound_fn_sig(*did).subst(self.tcx, substs);
if sig1 != *sig2 {
return;
}
@ -1401,7 +1401,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// If we have a default, then we it doesn't matter that we're not
// inferring the type arguments: we provide the default where any
// is missing.
let default = tcx.type_of(param.def_id);
let default = tcx.bound_type_of(param.def_id);
self.fcx
.normalize_ty(self.span, default.subst(tcx, substs.unwrap()))
.into()
@ -1415,7 +1415,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
GenericParamDefKind::Const { has_default } => {
if !infer_args && has_default {
tcx.const_param_default(param.def_id).subst(tcx, substs.unwrap()).into()
EarlyBinder(tcx.const_param_default(param.def_id))
.subst(tcx, substs.unwrap())
.into()
} else {
self.fcx.var_for_def(self.span, param)
}

View file

@ -129,7 +129,7 @@ pub fn check_intrinsic_type(tcx: TyCtxt<'_>, it: &hir::ForeignItem<'_>) {
ty::INNERMOST,
ty::BoundRegion { var: ty::BoundVar::from_u32(1), kind: ty::BrEnv },
));
let va_list_ty = tcx.type_of(did).subst(tcx, &[region.into()]);
let va_list_ty = tcx.bound_type_of(did).subst(tcx, &[region.into()]);
(tcx.mk_ref(env_region, ty::TypeAndMut { ty: va_list_ty, mutbl }), va_list_ty)
})
};

View file

@ -460,7 +460,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
debug!("method_predicates after subst = {:?}", method_predicates);
let sig = self.tcx.fn_sig(def_id);
let sig = self.tcx.bound_fn_sig(def_id);
let sig = sig.subst(self.tcx, all_substs);
debug!("type scheme substituted, sig={:?}", sig);

View file

@ -460,7 +460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// N.B., instantiate late-bound regions first so that
// `instantiate_type_scheme` can normalize associated types that
// may reference those regions.
let fn_sig = tcx.fn_sig(def_id);
let fn_sig = tcx.bound_fn_sig(def_id);
let fn_sig = fn_sig.subst(self.tcx, substs);
let fn_sig = self.replace_bound_vars_with_fresh_vars(span, infer::FnCall, fn_sig).0;

View file

@ -21,7 +21,7 @@ use rustc_middle::middle::stability;
use rustc_middle::ty::fast_reject::{simplify_type, TreatParams};
use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef};
use rustc_middle::ty::GenericParamDefKind;
use rustc_middle::ty::{self, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, ToPredicate, Ty, TyCtxt, TypeFoldable};
use rustc_session::lint;
use rustc_span::def_id::LocalDefId;
use rustc_span::lev_distance::{
@ -711,7 +711,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
}
let (impl_ty, impl_substs) = self.impl_ty_and_substs(impl_def_id);
let impl_ty = impl_ty.subst(self.tcx, impl_substs);
let impl_ty = EarlyBinder(impl_ty).subst(self.tcx, impl_substs);
debug!("impl_ty: {:?}", impl_ty);
@ -901,7 +901,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
) -> bool {
match method.kind {
ty::AssocKind::Fn => {
let fty = self.tcx.fn_sig(method.def_id);
let fty = self.tcx.bound_fn_sig(method.def_id);
self.probe(|_| {
let substs = self.fresh_substs_for_item(self.span, method.def_id);
let fty = fty.subst(self.tcx, substs);
@ -1771,7 +1771,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
#[instrument(level = "debug", skip(self))]
fn xform_method_sig(&self, method: DefId, substs: SubstsRef<'tcx>) -> ty::FnSig<'tcx> {
let fn_sig = self.tcx.fn_sig(method);
let fn_sig = self.tcx.bound_fn_sig(method);
debug!(?fn_sig);
assert!(!substs.has_escaping_bound_vars());

View file

@ -21,7 +21,8 @@ use rustc_middle::hir::nested_filter;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable, TypeVisitor,
self, AdtKind, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
TypeVisitor,
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
@ -1388,7 +1389,7 @@ fn check_where_clauses<'tcx, 'fcx>(
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
let substituted_pred = pred.subst(tcx, substs);
let substituted_pred = EarlyBinder(pred).subst(tcx, substs);
// Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params.
if substituted_pred.has_param_types_or_consts()

View file

@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def::DefKind;
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};
use rustc_span::Span;
use super::explicit::ExplicitPredicatesMap;
@ -137,7 +137,7 @@ fn insert_required_predicates_to_be_wf<'tcx>(
// `unsubstituted_predicate` is `U: 'b` in the
// example above. So apply the substitution to
// get `T: 'a` (or `predicate`):
let predicate = unsubstituted_predicate.subst(tcx, substs);
let predicate = EarlyBinder(*unsubstituted_predicate).subst(tcx, substs);
insert_outlives_predicate(
tcx,
predicate.0,
@ -287,7 +287,7 @@ pub fn check_explicit_predicates<'tcx>(
continue;
}
let predicate = outlives_predicate.subst(tcx, substs);
let predicate = EarlyBinder(*outlives_predicate).subst(tcx, substs);
debug!("predicate = {:?}", &predicate);
insert_outlives_predicate(tcx, predicate.0, predicate.1, span, required_predicates);
}