Skip to content

More EarlyBinder cleanups #100095

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Aug 4, 2022
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 16 additions & 16 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
@@ -16,9 +16,7 @@ use rustc_middle::mir::{
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
};
use rustc_middle::ty::{
self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty,
};
use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind;
@@ -461,35 +459,37 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.tcx;

// Find out if the predicates show that the type is a Fn or FnMut
let find_fn_kind_from_did = |predicates: &[(ty::Predicate<'tcx>, Span)], substs| {
predicates.iter().find_map(|(pred, _)| {
let pred = if let Some(substs) = substs {
EarlyBinder(*pred).subst(tcx, substs).kind().skip_binder()
} else {
pred.kind().skip_binder()
};
if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
let find_fn_kind_from_did =
|predicates: ty::EarlyBinder<&[(ty::Predicate<'tcx>, Span)]>, substs| {
predicates.0.iter().find_map(|(pred, _)| {
let pred = if let Some(substs) = substs {
predicates.rebind(*pred).subst(tcx, substs).kind().skip_binder()
} else {
pred.kind().skip_binder()
};
if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
return Some(hir::Mutability::Not);
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
return Some(hir::Mutability::Mut);
}
}
None
})
};
None
})
};

// If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably)
// borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
// These types seem reasonably opaque enough that they could be substituted with their
// borrowed variants in a function body when we see a move error.
let borrow_level = match ty.kind() {
ty::Param(_) => find_fn_kind_from_did(
tcx.explicit_predicates_of(self.mir_def_id().to_def_id()).predicates,
tcx.bound_explicit_predicates_of(self.mir_def_id().to_def_id())
.map_bound(|p| p.predicates),
None,
),
ty::Opaque(did, substs) => {
find_fn_kind_from_did(tcx.explicit_item_bounds(*did), Some(*substs))
find_fn_kind_from_did(tcx.bound_explicit_item_bounds(*did), Some(*substs))
}
ty::Closure(_, substs) => match substs.as_closure().kind() {
ty::ClosureKind::Fn => Some(hir::Mutability::Not),
4 changes: 2 additions & 2 deletions compiler/rustc_const_eval/src/const_eval/eval_queries.rs
Original file line number Diff line number Diff line change
@@ -13,7 +13,7 @@ use rustc_middle::mir::pretty::display_allocation;
use rustc_middle::traits::Reveal;
use rustc_middle::ty::layout::LayoutOf;
use rustc_middle::ty::print::with_no_trimmed_paths;
use rustc_middle::ty::{self, subst::Subst, EarlyBinder, TyCtxt};
use rustc_middle::ty::{self, subst::Subst, TyCtxt};
use rustc_span::source_map::Span;
use rustc_target::abi::{self, Abi};
use std::borrow::Cow;
@@ -45,7 +45,7 @@ fn eval_body_using_ecx<'mir, 'tcx>(
"Unexpected DefKind: {:?}",
ecx.tcx.def_kind(cid.instance.def_id())
);
let layout = ecx.layout_of(EarlyBinder(body.return_ty()).subst(tcx, cid.instance.substs))?;
let layout = ecx.layout_of(body.bound_return_ty().subst(tcx, cid.instance.substs))?;
assert!(!layout.is_unsized());
let ret = ecx.allocate(layout, MemoryKind::Stack)?;

6 changes: 6 additions & 0 deletions compiler/rustc_middle/src/mir/mod.rs
Original file line number Diff line number Diff line change
@@ -431,6 +431,12 @@ impl<'tcx> Body<'tcx> {
self.local_decls[RETURN_PLACE].ty
}

/// Returns the return type; it always return first element from `local_decls` array.
#[inline]
pub fn bound_return_ty(&self) -> ty::EarlyBinder<Ty<'tcx>> {
ty::EarlyBinder(self.local_decls[RETURN_PLACE].ty)
}

/// Gets the location of the terminator for the given block.
#[inline]
pub fn terminator_loc(&self, bb: BasicBlock) -> Location {
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/adt.rs
Original file line number Diff line number Diff line change
@@ -563,7 +563,7 @@ impl<'tcx> AdtDef<'tcx> {
///
/// Due to normalization being eager, this applies even if
/// the associated type is behind a pointer (e.g., issue #31299).
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> &'tcx [Ty<'tcx>] {
tcx.adt_sized_constraint(self.did()).0
pub fn sized_constraint(self, tcx: TyCtxt<'tcx>) -> ty::EarlyBinder<&'tcx [Ty<'tcx>]> {
ty::EarlyBinder(tcx.adt_sized_constraint(self.did()).0)
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_middle/src/ty/sty.rs
Original file line number Diff line number Diff line change
@@ -2191,7 +2191,7 @@ impl<'tcx> Ty<'tcx> {

ty::Tuple(tys) => tys.iter().all(|ty| ty.is_trivially_sized(tcx)),

ty::Adt(def, _substs) => def.sized_constraint(tcx).is_empty(),
ty::Adt(def, _substs) => def.sized_constraint(tcx).0.is_empty(),

ty::Projection(_) | ty::Param(_) | ty::Opaque(..) => false,

18 changes: 18 additions & 0 deletions compiler/rustc_middle/src/ty/util.rs
Original file line number Diff line number Diff line change
@@ -680,6 +680,24 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
ty::EarlyBinder(self.const_param_default(def_id))
}

pub fn bound_predicates_of(
self,
def_id: DefId,
) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> {
ty::EarlyBinder(self.predicates_of(def_id))
}

pub fn bound_explicit_predicates_of(
self,
def_id: DefId,
) -> ty::EarlyBinder<ty::generics::GenericPredicates<'tcx>> {
ty::EarlyBinder(self.explicit_predicates_of(def_id))
}

pub fn bound_impl_subject(self, def_id: DefId) -> ty::EarlyBinder<ty::ImplSubject<'tcx>> {
ty::EarlyBinder(self.impl_subject(def_id))
}
}

struct OpaqueTypeExpander<'tcx> {
6 changes: 2 additions & 4 deletions compiler/rustc_mir_transform/src/const_prop.rs
Original file line number Diff line number Diff line change
@@ -18,9 +18,7 @@ use rustc_middle::mir::{
};
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{
self, ConstKind, EarlyBinder, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable,
};
use rustc_middle::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeVisitable};
use rustc_span::{def_id::DefId, Span};
use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
use rustc_target::spec::abi::Abi as CallAbi;
@@ -387,7 +385,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
);

let ret_layout = ecx
.layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
.layout_of(body.bound_return_ty().subst(tcx, substs))
.ok()
// Don't bother allocating memory for large values.
// I don't know how return types can seem to be unsized but this happens in the
5 changes: 2 additions & 3 deletions compiler/rustc_mir_transform/src/const_prop_lint.rs
Original file line number Diff line number Diff line change
@@ -23,8 +23,7 @@ use rustc_middle::mir::{
use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout};
use rustc_middle::ty::subst::{InternalSubsts, Subst};
use rustc_middle::ty::{
self, ConstInt, ConstKind, EarlyBinder, Instance, ParamEnv, ScalarInt, Ty, TyCtxt,
TypeVisitable,
self, ConstInt, ConstKind, Instance, ParamEnv, ScalarInt, Ty, TyCtxt, TypeVisitable,
};
use rustc_session::lint;
use rustc_span::Span;
@@ -196,7 +195,7 @@ impl<'mir, 'tcx> ConstPropagator<'mir, 'tcx> {
);

let ret_layout = ecx
.layout_of(EarlyBinder(body.return_ty()).subst(tcx, substs))
.layout_of(body.bound_return_ty().subst(tcx, substs))
.ok()
// Don't bother allocating memory for large values.
// I don't know how return types can seem to be unsized but this happens in the
12 changes: 6 additions & 6 deletions compiler/rustc_trait_selection/src/traits/project.rs
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@ use rustc_middle::traits::select::OverflowError;
use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::visit::{MaxUniverse, TypeVisitable};
use rustc_middle::ty::{self, EarlyBinder, Term, ToPredicate, Ty, TyCtxt};
use rustc_middle::ty::{self, Term, ToPredicate, Ty, TyCtxt};
use rustc_span::symbol::sym;

use std::collections::BTreeMap;
@@ -2005,16 +2005,16 @@ fn confirm_impl_candidate<'cx, 'tcx>(
let substs = obligation.predicate.substs.rebase_onto(tcx, trait_def_id, substs);
let substs =
translate_substs(selcx.infcx(), param_env, impl_def_id, substs, assoc_ty.defining_node);
let ty = tcx.type_of(assoc_ty.item.def_id);
let ty = tcx.bound_type_of(assoc_ty.item.def_id);
let is_const = matches!(tcx.def_kind(assoc_ty.item.def_id), DefKind::AssocConst);
let term: ty::Term<'tcx> = if is_const {
let term: ty::EarlyBinder<ty::Term<'tcx>> = if is_const {
let identity_substs =
crate::traits::InternalSubsts::identity_for_item(tcx, assoc_ty.item.def_id);
let did = ty::WithOptConstParam::unknown(assoc_ty.item.def_id);
let kind = ty::ConstKind::Unevaluated(ty::Unevaluated::new(did, identity_substs));
tcx.mk_const(ty::ConstS { ty, kind }).into()
ty.map_bound(|ty| tcx.mk_const(ty::ConstS { ty, kind }).into())
} else {
ty.into()
ty.map_bound(|ty| ty.into())
};
if substs.len() != tcx.generics_of(assoc_ty.item.def_id).count() {
let err = tcx.ty_error_with_message(
@@ -2024,7 +2024,7 @@ fn confirm_impl_candidate<'cx, 'tcx>(
Progress { term: err.into(), obligations: nested }
} else {
assoc_ty_own_obligations(selcx, obligation, &mut nested);
Progress { term: EarlyBinder(term).subst(tcx, substs), obligations: nested }
Progress { term: term.subst(tcx, substs), obligations: nested }
}
}

16 changes: 10 additions & 6 deletions compiler/rustc_trait_selection/src/traits/select/mod.rs
Original file line number Diff line number Diff line change
@@ -1883,7 +1883,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
let sized_crit = def.sized_constraint(self.tcx());
// (*) binder moved here
Where(obligation.predicate.rebind({
sized_crit.iter().map(|ty| EarlyBinder(*ty).subst(self.tcx(), substs)).collect()
sized_crit
.0
.iter()
.map(|ty| sized_crit.rebind(*ty).subst(self.tcx(), substs))
.collect()
}))
}

@@ -2356,11 +2360,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// obligation will normalize to `<$0 as Iterator>::Item = $1` and
// `$1: Copy`, so we must ensure the obligations are emitted in
// that order.
let predicates = tcx.predicates_of(def_id);
let predicates = tcx.bound_predicates_of(def_id);
debug!(?predicates);
assert_eq!(predicates.parent, None);
let mut obligations = Vec::with_capacity(predicates.predicates.len());
for (predicate, span) in predicates.predicates {
assert_eq!(predicates.0.parent, None);
let mut obligations = Vec::with_capacity(predicates.0.predicates.len());
for (predicate, span) in predicates.0.predicates {
let span = *span;
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
@@ -2374,7 +2378,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env,
cause.clone(),
recursion_depth,
EarlyBinder(*predicate).subst(tcx, substs),
predicates.rebind(*predicate).subst(tcx, substs),
&mut obligations,
);
obligations.push(Obligation { cause, recursion_depth, param_env, predicate });
6 changes: 3 additions & 3 deletions compiler/rustc_trait_selection/src/traits/util.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,7 @@ use smallvec::SmallVec;
use rustc_data_structures::fx::FxHashSet;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::{GenericArg, Subst, SubstsRef};
use rustc_middle::ty::{self, EarlyBinder, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};
use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable};

use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
pub use rustc_infer::traits::{self, util::*};
@@ -200,8 +200,8 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
impl_def_id: DefId,
impl_substs: SubstsRef<'tcx>,
) -> (ImplSubject<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
let subject = selcx.tcx().impl_subject(impl_def_id);
let subject = EarlyBinder(subject).subst(selcx.tcx(), impl_substs);
let subject = selcx.tcx().bound_impl_subject(impl_def_id);
let subject = subject.subst(selcx.tcx(), impl_substs);
let Normalized { value: subject, obligations: normalization_obligations1 } =
super::normalize(selcx, param_env, ObligationCause::dummy(), subject);

31 changes: 16 additions & 15 deletions compiler/rustc_traits/src/chalk/db.rs
Original file line number Diff line number Diff line change
@@ -51,11 +51,11 @@ impl<'tcx> RustIrDatabase<'tcx> {
where
ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option<T>>,
{
self.interner
.tcx
.explicit_item_bounds(def_id)
let bounds = self.interner.tcx.bound_explicit_item_bounds(def_id);
bounds
.0
.iter()
.map(|(bound, _)| EarlyBinder(*bound).subst(self.interner.tcx, &bound_vars))
.map(|(bound, _)| bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars))
.filter_map(|bound| LowerInto::<Option<_>>::lower_into(bound, self.interner))
.collect()
}
@@ -268,21 +268,20 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t

let where_clauses = self.where_clauses_for(def_id, bound_vars);

let sig = self.interner.tcx.fn_sig(def_id);
let sig = self.interner.tcx.bound_fn_sig(def_id);
let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars(
self.interner,
self.interner.tcx,
EarlyBinder(sig.inputs_and_output()).subst(self.interner.tcx, bound_vars),
sig.map_bound(|s| s.inputs_and_output()).subst(self.interner.tcx, bound_vars),
);

let argument_types = inputs_and_output[..inputs_and_output.len() - 1]
.iter()
.map(|t| {
EarlyBinder(*t).subst(self.interner.tcx, &bound_vars).lower_into(self.interner)
})
.map(|t| sig.rebind(*t).subst(self.interner.tcx, &bound_vars).lower_into(self.interner))
.collect();

let return_type = EarlyBinder(inputs_and_output[inputs_and_output.len() - 1])
let return_type = sig
.rebind(inputs_and_output[inputs_and_output.len() - 1])
.subst(self.interner.tcx, &bound_vars)
.lower_into(self.interner);

@@ -295,7 +294,7 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t
};
Arc::new(chalk_solve::rust_ir::FnDefDatum {
id: fn_def_id,
sig: sig.lower_into(self.interner),
sig: sig.0.lower_into(self.interner),
binders: chalk_ir::Binders::new(binders, bound),
})
}
@@ -503,12 +502,14 @@ impl<'tcx> chalk_solve::RustIrDatabase<RustInterner<'tcx>> for RustIrDatabase<'t

let identity_substs = InternalSubsts::identity_for_item(self.interner.tcx, opaque_ty_id.0);

let explicit_item_bounds = self.interner.tcx.bound_explicit_item_bounds(opaque_ty_id.0);
let bounds =
self.interner
.tcx
.explicit_item_bounds(opaque_ty_id.0)
explicit_item_bounds
.0
.iter()
.map(|(bound, _)| EarlyBinder(*bound).subst(self.interner.tcx, &bound_vars))
.map(|(bound, _)| {
explicit_item_bounds.rebind(*bound).subst(self.interner.tcx, &bound_vars)
})
.map(|bound| {
bound.fold_with(&mut ReplaceOpaqueTyFolder {
tcx: self.interner.tcx,
7 changes: 3 additions & 4 deletions compiler/rustc_ty_utils/src/ty.rs
Original file line number Diff line number Diff line change
@@ -2,9 +2,7 @@ use rustc_data_structures::fx::FxIndexSet;
use rustc_hir as hir;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::subst::Subst;
use rustc_middle::ty::{
self, Binder, EarlyBinder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt,
};
use rustc_middle::ty::{self, Binder, Predicate, PredicateKind, ToPredicate, Ty, TyCtxt};
use rustc_trait_selection::traits;

fn sized_constraint_for_ty<'tcx>(
@@ -33,8 +31,9 @@ fn sized_constraint_for_ty<'tcx>(
let adt_tys = adt.sized_constraint(tcx);
debug!("sized_constraint_for_ty({:?}) intermediate = {:?}", ty, adt_tys);
adt_tys
.0
.iter()
.map(|ty| EarlyBinder(*ty).subst(tcx, substs))
.map(|ty| adt_tys.rebind(*ty).subst(tcx, substs))
.flat_map(|ty| sized_constraint_for_ty(tcx, adtdef, ty))
.collect()
}
13 changes: 7 additions & 6 deletions compiler/rustc_typeck/src/check/wfcheck.rs
Original file line number Diff line number Diff line change
@@ -15,8 +15,8 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{
self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt,
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor,
self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
TypeSuperVisitable, TypeVisitable, TypeVisitor,
};
use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -1295,7 +1295,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
let infcx = wfcx.infcx;
let tcx = wfcx.tcx();

let predicates = tcx.predicates_of(def_id);
let predicates = tcx.bound_predicates_of(def_id.to_def_id());
let generics = tcx.generics_of(def_id);

let is_our_default = |def: &ty::GenericParamDef| match def.kind {
@@ -1392,6 +1392,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id

// Now we build the substituted predicates.
let default_obligations = predicates
.0
.predicates
.iter()
.flat_map(|&(pred, sp)| {
@@ -1422,15 +1423,15 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
}
let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break();
let substituted_pred = EarlyBinder(pred).subst(tcx, substs);
let substituted_pred = predicates.rebind(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()
|| param_count.params.len() > 1
|| has_region
{
None
} else if predicates.predicates.iter().any(|&(p, _)| p == substituted_pred) {
} else if predicates.0.predicates.iter().any(|&(p, _)| p == substituted_pred) {
// Avoid duplication of predicates that contain no parameters, for example.
None
} else {
@@ -1456,7 +1457,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
traits::Obligation::new(cause, wfcx.param_env, pred)
});

let predicates = predicates.instantiate_identity(tcx);
let predicates = predicates.0.instantiate_identity(tcx);

let predicates = wfcx.normalize(span, None, predicates);