1
Fork 0

Add bound_predicates_of and bound_explicit_predicates_of

This commit is contained in:
Jack Huey 2022-08-02 22:44:08 -04:00
parent 4493a0f472
commit e21624dc80
5 changed files with 58 additions and 42 deletions

View file

@ -16,9 +16,7 @@ use rustc_middle::mir::{
FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef, FakeReadCause, LocalDecl, LocalInfo, LocalKind, Location, Operand, Place, PlaceRef,
ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, VarBindingForm,
}; };
use rustc_middle::ty::{ use rustc_middle::ty::{self, subst::Subst, suggest_constraining_type_params, PredicateKind, Ty};
self, subst::Subst, suggest_constraining_type_params, EarlyBinder, PredicateKind, Ty,
};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex}; use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::LocalDefId; use rustc_span::def_id::LocalDefId;
use rustc_span::hygiene::DesugaringKind; use rustc_span::hygiene::DesugaringKind;
@ -461,23 +459,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
let tcx = self.infcx.tcx; let tcx = self.infcx.tcx;
// Find out if the predicates show that the type is a Fn or FnMut // 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| { let find_fn_kind_from_did =
predicates.iter().find_map(|(pred, _)| { |predicates: ty::EarlyBinder<&[(ty::Predicate<'tcx>, Span)]>, substs| {
let pred = if let Some(substs) = substs { predicates.0.iter().find_map(|(pred, _)| {
EarlyBinder(*pred).subst(tcx, substs).kind().skip_binder() let pred = if let Some(substs) = substs {
} else { predicates.rebind(*pred).subst(tcx, substs).kind().skip_binder()
pred.kind().skip_binder() } else {
}; pred.kind().skip_binder()
if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty { };
if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty {
if Some(pred.def_id()) == tcx.lang_items().fn_trait() { if Some(pred.def_id()) == tcx.lang_items().fn_trait() {
return Some(hir::Mutability::Not); return Some(hir::Mutability::Not);
} else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() { } else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() {
return Some(hir::Mutability::Mut); return Some(hir::Mutability::Mut);
} }
} }
None None
}) })
}; };
// If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably) // 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`. // borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`.
@ -485,11 +484,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
// borrowed variants in a function body when we see a move error. // borrowed variants in a function body when we see a move error.
let borrow_level = match ty.kind() { let borrow_level = match ty.kind() {
ty::Param(_) => find_fn_kind_from_did( 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, None,
), ),
ty::Opaque(did, substs) => { 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::Closure(_, substs) => match substs.as_closure().kind() {
ty::ClosureKind::Fn => Some(hir::Mutability::Not), ty::ClosureKind::Fn => Some(hir::Mutability::Not),

View file

@ -680,6 +680,20 @@ impl<'tcx> TyCtxt<'tcx> {
pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> { pub fn bound_const_param_default(self, def_id: DefId) -> ty::EarlyBinder<ty::Const<'tcx>> {
ty::EarlyBinder(self.const_param_default(def_id)) 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))
}
} }
struct OpaqueTypeExpander<'tcx> { struct OpaqueTypeExpander<'tcx> {

View file

@ -2356,11 +2356,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
// obligation will normalize to `<$0 as Iterator>::Item = $1` and // obligation will normalize to `<$0 as Iterator>::Item = $1` and
// `$1: Copy`, so we must ensure the obligations are emitted in // `$1: Copy`, so we must ensure the obligations are emitted in
// that order. // that order.
let predicates = tcx.predicates_of(def_id); let predicates = tcx.bound_predicates_of(def_id);
debug!(?predicates); debug!(?predicates);
assert_eq!(predicates.parent, None); assert_eq!(predicates.0.parent, None);
let mut obligations = Vec::with_capacity(predicates.predicates.len()); let mut obligations = Vec::with_capacity(predicates.0.predicates.len());
for (predicate, span) in predicates.predicates { for (predicate, span) in predicates.0.predicates {
let span = *span; let span = *span;
let cause = cause.clone().derived_cause(parent_trait_pred, |derived| { let cause = cause.clone().derived_cause(parent_trait_pred, |derived| {
ImplDerivedObligation(Box::new(ImplDerivedObligationCause { ImplDerivedObligation(Box::new(ImplDerivedObligationCause {
@ -2374,7 +2374,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
param_env, param_env,
cause.clone(), cause.clone(),
recursion_depth, recursion_depth,
EarlyBinder(*predicate).subst(tcx, substs), predicates.rebind(*predicate).subst(tcx, substs),
&mut obligations, &mut obligations,
); );
obligations.push(Obligation { cause, recursion_depth, param_env, predicate }); obligations.push(Obligation { cause, recursion_depth, param_env, predicate });

View file

@ -51,11 +51,11 @@ impl<'tcx> RustIrDatabase<'tcx> {
where where
ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option<T>>, ty::Predicate<'tcx>: LowerInto<'tcx, std::option::Option<T>>,
{ {
self.interner let bounds = self.interner.tcx.bound_explicit_item_bounds(def_id);
.tcx bounds
.explicit_item_bounds(def_id) .0
.iter() .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)) .filter_map(|bound| LowerInto::<Option<_>>::lower_into(bound, self.interner))
.collect() .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 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( let (inputs_and_output, iobinders, _) = crate::chalk::lowering::collect_bound_vars(
self.interner, self.interner,
self.interner.tcx, 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] let argument_types = inputs_and_output[..inputs_and_output.len() - 1]
.iter() .iter()
.map(|t| { .map(|t| sig.rebind(*t).subst(self.interner.tcx, &bound_vars).lower_into(self.interner))
EarlyBinder(*t).subst(self.interner.tcx, &bound_vars).lower_into(self.interner)
})
.collect(); .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) .subst(self.interner.tcx, &bound_vars)
.lower_into(self.interner); .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 { Arc::new(chalk_solve::rust_ir::FnDefDatum {
id: fn_def_id, id: fn_def_id,
sig: sig.lower_into(self.interner), sig: sig.0.lower_into(self.interner),
binders: chalk_ir::Binders::new(binders, bound), 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 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 = let bounds =
self.interner explicit_item_bounds
.tcx .0
.explicit_item_bounds(opaque_ty_id.0)
.iter() .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| { .map(|bound| {
bound.fold_with(&mut ReplaceOpaqueTyFolder { bound.fold_with(&mut ReplaceOpaqueTyFolder {
tcx: self.interner.tcx, tcx: self.interner.tcx,

View file

@ -15,8 +15,8 @@ use rustc_middle::ty::query::Providers;
use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst}; use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
use rustc_middle::ty::trait_def::TraitSpecializationKind; use rustc_middle::ty::trait_def::TraitSpecializationKind;
use rustc_middle::ty::{ use rustc_middle::ty::{
self, AdtKind, DefIdTree, EarlyBinder, GenericParamDefKind, ToPredicate, Ty, TyCtxt, self, AdtKind, DefIdTree, GenericParamDefKind, ToPredicate, Ty, TyCtxt, TypeFoldable,
TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, TypeSuperVisitable, TypeVisitable, TypeVisitor,
}; };
use rustc_session::parse::feature_err; use rustc_session::parse::feature_err;
use rustc_span::symbol::{sym, Ident, Symbol}; 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 infcx = wfcx.infcx;
let tcx = wfcx.tcx(); 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 generics = tcx.generics_of(def_id);
let is_our_default = |def: &ty::GenericParamDef| match def.kind { 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. // Now we build the substituted predicates.
let default_obligations = predicates let default_obligations = predicates
.0
.predicates .predicates
.iter() .iter()
.flat_map(|&(pred, sp)| { .flat_map(|&(pred, sp)| {
@ -1422,7 +1423,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
} }
let mut param_count = CountParams::default(); let mut param_count = CountParams::default();
let has_region = pred.visit_with(&mut param_count).is_break(); 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) // Don't check non-defaulted params, dependent defaults (including lifetimes)
// or preds with multiple params. // or preds with multiple params.
if substituted_pred.has_param_types_or_consts() if substituted_pred.has_param_types_or_consts()
@ -1430,7 +1431,7 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
|| has_region || has_region
{ {
None 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. // Avoid duplication of predicates that contain no parameters, for example.
None None
} else { } 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) 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); let predicates = wfcx.normalize(span, None, predicates);