1
Fork 0

take predicates by value instead of by reference

This commit is contained in:
Bastian Kauschke 2020-05-23 11:09:32 +02:00
parent 7f940ef5d9
commit 647ae50ce6
15 changed files with 58 additions and 67 deletions

View file

@ -1011,7 +1011,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
&self, &self,
cause: &ObligationCause<'tcx>, cause: &ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
predicate: &ty::PolySubtypePredicate<'tcx>, predicate: ty::PolySubtypePredicate<'tcx>,
) -> Option<InferResult<'tcx, ()>> { ) -> Option<InferResult<'tcx, ()>> {
// Subtle: it's ok to skip the binder here and resolve because // Subtle: it's ok to skip the binder here and resolve because
// `shallow_resolve` just ignores anything that is not a type // `shallow_resolve` just ignores anything that is not a type
@ -1034,7 +1034,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
Some(self.commit_if_ok(|snapshot| { Some(self.commit_if_ok(|snapshot| {
let (ty::SubtypePredicate { a_is_expected, a, b }, placeholder_map) = let (ty::SubtypePredicate { a_is_expected, a, b }, placeholder_map) =
self.replace_bound_vars_with_placeholders(predicate); self.replace_bound_vars_with_placeholders(&predicate);
let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?; let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
@ -1047,11 +1047,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
pub fn region_outlives_predicate( pub fn region_outlives_predicate(
&self, &self,
cause: &traits::ObligationCause<'tcx>, cause: &traits::ObligationCause<'tcx>,
predicate: &ty::PolyRegionOutlivesPredicate<'tcx>, predicate: ty::PolyRegionOutlivesPredicate<'tcx>,
) -> UnitResult<'tcx> { ) -> UnitResult<'tcx> {
self.commit_if_ok(|snapshot| { self.commit_if_ok(|snapshot| {
let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) = let (ty::OutlivesPredicate(r_a, r_b), placeholder_map) =
self.replace_bound_vars_with_placeholders(predicate); self.replace_bound_vars_with_placeholders(&predicate);
let origin = SubregionOrigin::from_obligation_cause(cause, || { let origin = SubregionOrigin::from_obligation_cause(cause, || {
RelateRegionParamBound(cause.span) RelateRegionParamBound(cause.span)
}); });

View file

@ -223,7 +223,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// like `T` and `T::Item`. It may not work as well for things // like `T` and `T::Item`. It may not work as well for things
// like `<T as Foo<'a>>::Item`. // like `<T as Foo<'a>>::Item`.
let c_b = self.param_env.caller_bounds; let c_b = self.param_env.caller_bounds;
let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter()); let param_bounds =
self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter().copied());
// Next, collect regions we scraped from the well-formedness // Next, collect regions we scraped from the well-formedness
// constraints in the fn signature. To do that, we walk the list // constraints in the fn signature. To do that, we walk the list
@ -334,10 +335,10 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
fn collect_outlives_from_predicate_list( fn collect_outlives_from_predicate_list(
&self, &self,
compare_ty: impl Fn(Ty<'tcx>) -> bool, compare_ty: impl Fn(Ty<'tcx>) -> bool,
predicates: impl Iterator<Item = impl AsRef<ty::Predicate<'tcx>>>, predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> { ) -> impl Iterator<Item = ty::OutlivesPredicate<Ty<'tcx>, ty::Region<'tcx>>> {
predicates predicates
.filter_map(|p| p.as_ref().to_opt_type_outlives()) .filter_map(|p| p.to_opt_type_outlives())
.filter_map(|p| p.no_bound_vars()) .filter_map(|p| p.no_bound_vars())
.filter(move |p| compare_ty(p.0)) .filter(move |p| compare_ty(p.0))
} }

View file

@ -8,7 +8,7 @@ use rustc_span::Span;
pub fn anonymize_predicate<'tcx>( pub fn anonymize_predicate<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
pred: &ty::Predicate<'tcx>, pred: ty::Predicate<'tcx>,
) -> ty::Predicate<'tcx> { ) -> ty::Predicate<'tcx> {
match pred.kind() { match pred.kind() {
&ty::PredicateKind::Trait(ref data, constness) => { &ty::PredicateKind::Trait(ref data, constness) => {
@ -66,7 +66,7 @@ impl PredicateSet<'tcx> {
Self { tcx, set: Default::default() } Self { tcx, set: Default::default() }
} }
fn insert(&mut self, pred: &ty::Predicate<'tcx>) -> bool { fn insert(&mut self, pred: ty::Predicate<'tcx>) -> bool {
// We have to be careful here because we want // We have to be careful here because we want
// //
// for<'a> Foo<&'a int> // for<'a> Foo<&'a int>
@ -81,10 +81,10 @@ impl PredicateSet<'tcx> {
} }
} }
impl<T: AsRef<ty::Predicate<'tcx>>> Extend<T> for PredicateSet<'tcx> { impl Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) { fn extend<I: IntoIterator<Item = ty::Predicate<'tcx>>>(&mut self, iter: I) {
for pred in iter { for pred in iter {
self.insert(pred.as_ref()); self.insert(pred);
} }
} }
} }
@ -132,7 +132,7 @@ pub fn elaborate_obligations<'tcx>(
mut obligations: Vec<PredicateObligation<'tcx>>, mut obligations: Vec<PredicateObligation<'tcx>>,
) -> Elaborator<'tcx> { ) -> Elaborator<'tcx> {
let mut visited = PredicateSet::new(tcx); let mut visited = PredicateSet::new(tcx);
obligations.retain(|obligation| visited.insert(&obligation.predicate)); obligations.retain(|obligation| visited.insert(obligation.predicate));
Elaborator { stack: obligations, visited } Elaborator { stack: obligations, visited }
} }
@ -172,7 +172,7 @@ impl Elaborator<'tcx> {
// cases. One common case is when people define // cases. One common case is when people define
// `trait Sized: Sized { }` rather than `trait Sized { }`. // `trait Sized: Sized { }` rather than `trait Sized { }`.
let visited = &mut self.visited; let visited = &mut self.visited;
let obligations = obligations.filter(|o| visited.insert(&o.predicate)); let obligations = obligations.filter(|o| visited.insert(o.predicate));
self.stack.extend(obligations); self.stack.extend(obligations);
} }
@ -260,7 +260,7 @@ impl Elaborator<'tcx> {
} }
}) })
.map(|predicate_kind| predicate_kind.to_predicate(tcx)) .map(|predicate_kind| predicate_kind.to_predicate(tcx))
.filter(|predicate| visited.insert(predicate)) .filter(|&predicate| visited.insert(predicate))
.map(|predicate| predicate_obligation(predicate, None)), .map(|predicate| predicate_obligation(predicate, None)),
); );
} }

View file

@ -1094,12 +1094,6 @@ pub struct CratePredicatesMap<'tcx> {
pub predicates: FxHashMap<DefId, &'tcx [(ty::Predicate<'tcx>, Span)]>, pub predicates: FxHashMap<DefId, &'tcx [(ty::Predicate<'tcx>, Span)]>,
} }
impl<'tcx> AsRef<Predicate<'tcx>> for Predicate<'tcx> {
fn as_ref(&self) -> &Predicate<'tcx> {
self
}
}
impl<'tcx> Predicate<'tcx> { impl<'tcx> Predicate<'tcx> {
/// Performs a substitution suitable for going from a /// Performs a substitution suitable for going from a
/// poly-trait-ref to supertraits that must hold if that /// poly-trait-ref to supertraits that must hold if that
@ -1214,17 +1208,17 @@ pub struct TraitPredicate<'tcx> {
pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>; pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>;
impl<'tcx> TraitPredicate<'tcx> { impl<'tcx> TraitPredicate<'tcx> {
pub fn def_id(&self) -> DefId { pub fn def_id(self) -> DefId {
self.trait_ref.def_id self.trait_ref.def_id
} }
pub fn self_ty(&self) -> Ty<'tcx> { pub fn self_ty(self) -> Ty<'tcx> {
self.trait_ref.self_ty() self.trait_ref.self_ty()
} }
} }
impl<'tcx> PolyTraitPredicate<'tcx> { impl<'tcx> PolyTraitPredicate<'tcx> {
pub fn def_id(&self) -> DefId { pub fn def_id(self) -> DefId {
// Ok to skip binder since trait `DefId` does not care about regions. // Ok to skip binder since trait `DefId` does not care about regions.
self.skip_binder().def_id() self.skip_binder().def_id()
} }

View file

@ -768,12 +768,12 @@ impl AutoTraitFinder<'tcx> {
} }
} }
} }
ty::PredicateKind::RegionOutlives(ref binder) => { &ty::PredicateKind::RegionOutlives(binder) => {
if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() { if select.infcx().region_outlives_predicate(&dummy_cause, binder).is_err() {
return false; return false;
} }
} }
ty::PredicateKind::TypeOutlives(ref binder) => { &ty::PredicateKind::TypeOutlives(binder) => {
match ( match (
binder.no_bound_vars(), binder.no_bound_vars(),
binder.map_bound_ref(|pred| pred.0).no_bound_vars(), binder.map_bound_ref(|pred| pred.0).no_bound_vars(),

View file

@ -146,9 +146,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
continue; continue;
} }
if self.error_implies(&error2.predicate, &error.predicate) if self.error_implies(error2.predicate, error.predicate)
&& !(error2.index >= error.index && !(error2.index >= error.index
&& self.error_implies(&error.predicate, &error2.predicate)) && self.error_implies(error.predicate, error2.predicate))
{ {
info!("skipping {:?} (implied by {:?})", error, error2); info!("skipping {:?} (implied by {:?})", error, error2);
is_suppressed[index] = true; is_suppressed[index] = true;
@ -500,7 +500,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
ty::PredicateKind::RegionOutlives(ref predicate) => { ty::PredicateKind::RegionOutlives(ref predicate) => {
let predicate = self.resolve_vars_if_possible(predicate); let predicate = self.resolve_vars_if_possible(predicate);
let err = self let err = self
.region_outlives_predicate(&obligation.cause, &predicate) .region_outlives_predicate(&obligation.cause, predicate)
.err() .err()
.unwrap(); .unwrap();
struct_span_err!( struct_span_err!(
@ -955,7 +955,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
trait InferCtxtPrivExt<'tcx> { trait InferCtxtPrivExt<'tcx> {
// returns if `cond` not occurring implies that `error` does not occur - i.e., that // returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs. // `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool; fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool;
fn report_fulfillment_error( fn report_fulfillment_error(
&self, &self,
@ -1042,7 +1042,7 @@ trait InferCtxtPrivExt<'tcx> {
impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> { impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
// returns if `cond` not occurring implies that `error` does not occur - i.e., that // returns if `cond` not occurring implies that `error` does not occur - i.e., that
// `error` occurring implies that `cond` occurs. // `error` occurring implies that `cond` occurs.
fn error_implies(&self, cond: &ty::Predicate<'tcx>, error: &ty::Predicate<'tcx>) -> bool { fn error_implies(&self, cond: ty::Predicate<'tcx>, error: ty::Predicate<'tcx>) -> bool {
if cond == error { if cond == error {
return true; return true;
} }
@ -1055,7 +1055,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
} }
}; };
for obligation in super::elaborate_predicates(self.tcx, std::iter::once(*cond)) { for obligation in super::elaborate_predicates(self.tcx, std::iter::once(cond)) {
if let ty::PredicateKind::Trait(implication, _) = obligation.predicate.kind() { if let ty::PredicateKind::Trait(implication, _) = obligation.predicate.kind() {
let error = error.to_poly_trait_ref(); let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref(); let implication = implication.to_poly_trait_ref();

View file

@ -378,7 +378,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
} }
} }
ty::PredicateKind::RegionOutlives(ref binder) => { &ty::PredicateKind::RegionOutlives(binder) => {
match infcx.region_outlives_predicate(&obligation.cause, binder) { match infcx.region_outlives_predicate(&obligation.cause, binder) {
Ok(()) => ProcessResult::Changed(vec![]), Ok(()) => ProcessResult::Changed(vec![]),
Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)), Err(_) => ProcessResult::Error(CodeSelectionError(Unimplemented)),
@ -481,7 +481,7 @@ impl<'a, 'b, 'tcx> ObligationProcessor for FulfillProcessor<'a, 'b, 'tcx> {
} }
} }
ty::PredicateKind::Subtype(subtype) => { &ty::PredicateKind::Subtype(subtype) => {
match self.selcx.infcx().subtype_predicate( match self.selcx.infcx().subtype_predicate(
&obligation.cause, &obligation.cause,
obligation.param_env, obligation.param_env,

View file

@ -1541,14 +1541,14 @@ fn assoc_ty_def(
crate trait ProjectionCacheKeyExt<'tcx>: Sized { crate trait ProjectionCacheKeyExt<'tcx>: Sized {
fn from_poly_projection_predicate( fn from_poly_projection_predicate(
selcx: &mut SelectionContext<'cx, 'tcx>, selcx: &mut SelectionContext<'cx, 'tcx>,
predicate: &ty::PolyProjectionPredicate<'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>,
) -> Option<Self>; ) -> Option<Self>;
} }
impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> { impl<'tcx> ProjectionCacheKeyExt<'tcx> for ProjectionCacheKey<'tcx> {
fn from_poly_projection_predicate( fn from_poly_projection_predicate(
selcx: &mut SelectionContext<'cx, 'tcx>, selcx: &mut SelectionContext<'cx, 'tcx>,
predicate: &ty::PolyProjectionPredicate<'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>,
) -> Option<Self> { ) -> Option<Self> {
let infcx = selcx.infcx(); let infcx = selcx.infcx();
// We don't do cross-snapshot caching of obligations with escaping regions, // We don't do cross-snapshot caching of obligations with escaping regions,

View file

@ -415,13 +415,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
match obligation.predicate.kind() { match obligation.predicate.kind() {
ty::PredicateKind::Trait(t, _) => { &ty::PredicateKind::Trait(t, _) => {
debug_assert!(!t.has_escaping_bound_vars()); debug_assert!(!t.has_escaping_bound_vars());
let obligation = obligation.with(*t); let obligation = obligation.with(t);
self.evaluate_trait_predicate_recursively(previous_stack, obligation) self.evaluate_trait_predicate_recursively(previous_stack, obligation)
} }
ty::PredicateKind::Subtype(p) => { &ty::PredicateKind::Subtype(p) => {
// Does this code ever run? // Does this code ever run?
match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) { match self.infcx.subtype_predicate(&obligation.cause, obligation.param_env, p) {
Some(Ok(InferOk { mut obligations, .. })) => { Some(Ok(InferOk { mut obligations, .. })) => {
@ -463,8 +463,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
} }
} }
ty::PredicateKind::Projection(data) => { &ty::PredicateKind::Projection(data) => {
let project_obligation = obligation.with(*data); let project_obligation = obligation.with(data);
match project::poly_project_and_unify_type(self, &project_obligation) { match project::poly_project_and_unify_type(self, &project_obligation) {
Ok(Some(mut subobligations)) => { Ok(Some(mut subobligations)) => {
self.add_depth(subobligations.iter_mut(), obligation.recursion_depth); self.add_depth(subobligations.iter_mut(), obligation.recursion_depth);
@ -962,7 +962,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars()); debug_assert!(!stack.obligation.predicate.has_escaping_bound_vars());
if let Some(c) = if let Some(c) =
self.check_candidate_cache(stack.obligation.param_env, &cache_fresh_trait_pred) self.check_candidate_cache(stack.obligation.param_env, cache_fresh_trait_pred)
{ {
debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c); debug!("CACHE HIT: SELECT({:?})={:?}", cache_fresh_trait_pred, c);
return c; return c;
@ -1247,7 +1247,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
fn check_candidate_cache( fn check_candidate_cache(
&mut self, &mut self,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
cache_fresh_trait_pred: &ty::PolyTraitPredicate<'tcx>, cache_fresh_trait_pred: ty::PolyTraitPredicate<'tcx>,
) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> { ) -> Option<SelectionResult<'tcx, SelectionCandidate<'tcx>>> {
let tcx = self.tcx(); let tcx = self.tcx();
let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref; let trait_ref = &cache_fresh_trait_pred.skip_binder().trait_ref;

View file

@ -108,9 +108,9 @@ impl<'tcx> TraitAliasExpander<'tcx> {
} }
// Don't recurse if this trait alias is already on the stack for the DFS search. // Don't recurse if this trait alias is already on the stack for the DFS search.
let anon_pred = anonymize_predicate(tcx, &pred); let anon_pred = anonymize_predicate(tcx, pred);
if item.path.iter().rev().skip(1).any(|(tr, _)| { if item.path.iter().rev().skip(1).any(|(tr, _)| {
anonymize_predicate(tcx, &tr.without_const().to_predicate(tcx)) == anon_pred anonymize_predicate(tcx, tr.without_const().to_predicate(tcx)) == anon_pred
}) { }) {
return false; return false;
} }

View file

@ -66,7 +66,7 @@ pub fn predicate_obligations<'a, 'tcx>(
infcx: &InferCtxt<'a, 'tcx>, infcx: &InferCtxt<'a, 'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
body_id: hir::HirId, body_id: hir::HirId,
predicate: &ty::Predicate<'tcx>, predicate: ty::Predicate<'tcx>,
span: Span, span: Span,
) -> Vec<traits::PredicateObligation<'tcx>> { ) -> Vec<traits::PredicateObligation<'tcx>> {
let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None }; let mut wf = WfPredicates { infcx, param_env, body_id, span, out: vec![], item: None };

View file

@ -179,7 +179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
ty::Dynamic(ref object_type, ..) => { ty::Dynamic(ref object_type, ..) => {
let sig = object_type.projection_bounds().find_map(|pb| { let sig = object_type.projection_bounds().find_map(|pb| {
let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self); let pb = pb.with_self_ty(self.tcx, self.tcx.types.trait_object_dummy_self);
self.deduce_sig_from_projection(None, &pb) self.deduce_sig_from_projection(None, pb)
}); });
let kind = object_type let kind = object_type
.principal_def_id() .principal_def_id()
@ -206,8 +206,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
obligation.predicate obligation.predicate
); );
if let ty::PredicateKind::Projection(ref proj_predicate) = if let &ty::PredicateKind::Projection(proj_predicate) = obligation.predicate.kind()
obligation.predicate.kind()
{ {
// Given a Projection predicate, we can potentially infer // Given a Projection predicate, we can potentially infer
// the complete signature. // the complete signature.
@ -238,7 +237,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn deduce_sig_from_projection( fn deduce_sig_from_projection(
&self, &self,
cause_span: Option<Span>, cause_span: Option<Span>,
projection: &ty::PolyProjectionPredicate<'tcx>, projection: ty::PolyProjectionPredicate<'tcx>,
) -> Option<ExpectedSig<'tcx>> { ) -> Option<ExpectedSig<'tcx>> {
let tcx = self.tcx; let tcx = self.tcx;
@ -644,7 +643,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// where R is the return type we are expecting. This type `T` // where R is the return type we are expecting. This type `T`
// will be our output. // will be our output.
let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| { let output_ty = self.obligations_for_self_ty(ret_vid).find_map(|(_, obligation)| {
if let ty::PredicateKind::Projection(ref proj_predicate) = obligation.predicate.kind() { if let &ty::PredicateKind::Projection(proj_predicate) = obligation.predicate.kind() {
self.deduce_future_output_from_projection(obligation.cause.span, proj_predicate) self.deduce_future_output_from_projection(obligation.cause.span, proj_predicate)
} else { } else {
None None
@ -665,7 +664,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
fn deduce_future_output_from_projection( fn deduce_future_output_from_projection(
&self, &self,
cause_span: Span, cause_span: Span,
predicate: &ty::PolyProjectionPredicate<'tcx>, predicate: ty::PolyProjectionPredicate<'tcx>,
) -> Option<Ty<'tcx>> { ) -> Option<Ty<'tcx>> {
debug!("deduce_future_output_from_projection(predicate={:?})", predicate); debug!("deduce_future_output_from_projection(predicate={:?})", predicate);

View file

@ -205,7 +205,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// just to look for all the predicates directly. // just to look for all the predicates directly.
assert_eq!(dtor_predicates.parent, None); assert_eq!(dtor_predicates.parent, None);
for (predicate, predicate_sp) in dtor_predicates.predicates { for &(predicate, predicate_sp) in dtor_predicates.predicates {
// (We do not need to worry about deep analysis of type // (We do not need to worry about deep analysis of type
// expressions etc because the Drop impls are already forced // expressions etc because the Drop impls are already forced
// to take on a structure that is roughly an alpha-renaming of // to take on a structure that is roughly an alpha-renaming of
@ -228,7 +228,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
// This implementation solves (Issue #59497) and (Issue #58311). // This implementation solves (Issue #59497) and (Issue #58311).
// It is unclear to me at the moment whether the approach based on `relate` // It is unclear to me at the moment whether the approach based on `relate`
// could be extended easily also to the other `Predicate`. // could be extended easily also to the other `Predicate`.
let predicate_matches_closure = |p: &'_ Predicate<'tcx>| { let predicate_matches_closure = |p: Predicate<'tcx>| {
let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env); let mut relator: SimpleEqRelation<'tcx> = SimpleEqRelation::new(tcx, self_param_env);
match (predicate.kind(), p.kind()) { match (predicate.kind(), p.kind()) {
(ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => { (ty::PredicateKind::Trait(a, _), ty::PredicateKind::Trait(b, _)) => {
@ -241,12 +241,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
} }
}; };
if !assumptions_in_impl_context.iter().any(predicate_matches_closure) { if !assumptions_in_impl_context.iter().copied().any(predicate_matches_closure) {
let item_span = tcx.hir().span(self_type_hir_id); let item_span = tcx.hir().span(self_type_hir_id);
let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id()); let self_descr = tcx.def_kind(self_type_did).descr(self_type_did.to_def_id());
struct_span_err!( struct_span_err!(
tcx.sess, tcx.sess,
*predicate_sp, predicate_sp,
E0367, E0367,
"`Drop` impl requires `{}` but the {} it is implemented for does not", "`Drop` impl requires `{}` but the {} it is implemented for does not",
predicate, predicate,

View file

@ -819,8 +819,8 @@ fn check_where_clauses<'tcx, 'fcx>(
debug!("check_where_clauses: predicates={:?}", predicates.predicates); debug!("check_where_clauses: predicates={:?}", predicates.predicates);
assert_eq!(predicates.predicates.len(), predicates.spans.len()); assert_eq!(predicates.predicates.len(), predicates.spans.len());
let wf_obligations = let wf_obligations =
predicates.predicates.iter().zip(predicates.spans.iter()).flat_map(|(p, sp)| { predicates.predicates.iter().zip(predicates.spans.iter()).flat_map(|(&p, &sp)| {
traits::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, *sp) traits::wf::predicate_obligations(fcx, fcx.param_env, fcx.body_id, p, sp)
}); });
for obligation in wf_obligations.chain(default_obligations) { for obligation in wf_obligations.chain(default_obligations) {

View file

@ -329,16 +329,13 @@ fn check_predicates<'tcx>(
// which is sound because we forbid impls like the following // which is sound because we forbid impls like the following
// //
// impl<D: Debug> AlwaysApplicable for D { } // impl<D: Debug> AlwaysApplicable for D { }
let always_applicable_traits = impl1_predicates let always_applicable_traits =
.predicates impl1_predicates.predicates.iter().copied().filter(|&predicate| {
.iter()
.filter(|predicate| {
matches!( matches!(
trait_predicate_kind(tcx, predicate), trait_predicate_kind(tcx, predicate),
Some(TraitSpecializationKind::AlwaysApplicable) Some(TraitSpecializationKind::AlwaysApplicable)
) )
}) });
.copied();
// Include the well-formed predicates of the type parameters of the impl. // Include the well-formed predicates of the type parameters of the impl.
for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() { for ty in tcx.impl_trait_ref(impl1_def_id).unwrap().substs.types() {
@ -361,12 +358,12 @@ fn check_predicates<'tcx>(
for predicate in impl1_predicates.predicates { for predicate in impl1_predicates.predicates {
if !impl2_predicates.predicates.contains(&predicate) { if !impl2_predicates.predicates.contains(&predicate) {
check_specialization_on(tcx, &predicate, span) check_specialization_on(tcx, predicate, span)
} }
} }
} }
fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'tcx>, span: Span) { fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: ty::Predicate<'tcx>, span: Span) {
debug!("can_specialize_on(predicate = {:?})", predicate); debug!("can_specialize_on(predicate = {:?})", predicate);
match predicate.kind() { match predicate.kind() {
// Global predicates are either always true or always false, so we // Global predicates are either always true or always false, so we
@ -399,7 +396,7 @@ fn check_specialization_on<'tcx>(tcx: TyCtxt<'tcx>, predicate: &ty::Predicate<'t
fn trait_predicate_kind<'tcx>( fn trait_predicate_kind<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
predicate: &ty::Predicate<'tcx>, predicate: ty::Predicate<'tcx>,
) -> Option<TraitSpecializationKind> { ) -> Option<TraitSpecializationKind> {
match predicate.kind() { match predicate.kind() {
ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => { ty::PredicateKind::Trait(pred, hir::Constness::NotConst) => {