Auto merge of #71268 - estebank:devectorize, r=eddyb
Remove some `Vec` allocations to improve performance This claws back most of the performance lost in https://github.com/rust-lang/rust/pull/69745. r? @eddyb
This commit is contained in:
commit
46ec74e60f
20 changed files with 134 additions and 171 deletions
|
@ -223,7 +223,7 @@ 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);
|
let param_bounds = self.collect_outlives_from_predicate_list(&compare_ty, c_b.into_iter());
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -315,15 +315,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
|
||||||
let tcx = self.tcx;
|
let tcx = self.tcx;
|
||||||
let assoc_item = tcx.associated_item(assoc_item_def_id);
|
let assoc_item = tcx.associated_item(assoc_item_def_id);
|
||||||
let trait_def_id = assoc_item.container.assert_trait();
|
let trait_def_id = assoc_item.container.assert_trait();
|
||||||
let trait_predicates =
|
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
|
||||||
tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p).collect();
|
|
||||||
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
|
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
|
||||||
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
|
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
|
||||||
self.collect_outlives_from_predicate_list(
|
self.collect_outlives_from_predicate_list(
|
||||||
move |ty| ty == identity_proj,
|
move |ty| ty == identity_proj,
|
||||||
traits::elaborate_predicates(tcx, trait_predicates)
|
traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate),
|
||||||
.map(|o| o.predicate)
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
)
|
)
|
||||||
.map(|b| b.1)
|
.map(|b| b.1)
|
||||||
}
|
}
|
||||||
|
@ -337,10 +334,9 @@ 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 IntoIterator<Item = impl AsRef<ty::Predicate<'tcx>>>,
|
predicates: impl Iterator<Item = impl AsRef<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
|
||||||
.into_iter()
|
|
||||||
.filter_map(|p| p.as_ref().to_opt_type_outlives())
|
.filter_map(|p| p.as_ref().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))
|
||||||
|
|
|
@ -97,24 +97,22 @@ pub fn elaborate_trait_ref<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_ref: ty::PolyTraitRef<'tcx>,
|
trait_ref: ty::PolyTraitRef<'tcx>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> Elaborator<'tcx> {
|
||||||
elaborate_predicates(tcx, vec![trait_ref.without_const().to_predicate()])
|
elaborate_predicates(tcx, std::iter::once(trait_ref.without_const().to_predicate()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elaborate_trait_refs<'tcx>(
|
pub fn elaborate_trait_refs<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'tcx>>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> Elaborator<'tcx> {
|
||||||
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate()).collect();
|
let predicates = trait_refs.map(|trait_ref| trait_ref.without_const().to_predicate());
|
||||||
elaborate_predicates(tcx, predicates)
|
elaborate_predicates(tcx, predicates)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn elaborate_predicates<'tcx>(
|
pub fn elaborate_predicates<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
mut predicates: Vec<ty::Predicate<'tcx>>,
|
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
||||||
) -> Elaborator<'tcx> {
|
) -> Elaborator<'tcx> {
|
||||||
let mut visited = PredicateSet::new(tcx);
|
let obligations =
|
||||||
predicates.retain(|pred| visited.insert(pred));
|
|
||||||
let obligations: Vec<_> =
|
|
||||||
predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect();
|
predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect();
|
||||||
elaborate_obligations(tcx, obligations)
|
elaborate_obligations(tcx, obligations)
|
||||||
}
|
}
|
||||||
|
@ -151,21 +149,20 @@ impl Elaborator<'tcx> {
|
||||||
// Get predicates declared on the trait.
|
// Get predicates declared on the trait.
|
||||||
let predicates = tcx.super_predicates_of(data.def_id());
|
let predicates = tcx.super_predicates_of(data.def_id());
|
||||||
|
|
||||||
let obligations = predicates.predicates.iter().map(|(pred, span)| {
|
let obligations = predicates.predicates.into_iter().map(|(pred, span)| {
|
||||||
predicate_obligation(
|
predicate_obligation(
|
||||||
pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
|
pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
|
||||||
Some(*span),
|
Some(*span),
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
debug!("super_predicates: data={:?} predicates={:?}", data, &obligations);
|
debug!("super_predicates: data={:?}", data);
|
||||||
|
|
||||||
// Only keep those bounds that we haven't already seen.
|
// Only keep those bounds that we haven't already seen.
|
||||||
// This is necessary to prevent infinite recursion in some
|
// This is necessary to prevent infinite recursion in some
|
||||||
// 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 =
|
let obligations = obligations.filter(|o| visited.insert(&o.predicate));
|
||||||
obligations.filter(|obligation| visited.insert(&obligation.predicate));
|
|
||||||
|
|
||||||
self.stack.extend(obligations);
|
self.stack.extend(obligations);
|
||||||
}
|
}
|
||||||
|
|
|
@ -168,15 +168,13 @@ impl<'tcx> TyCtxt<'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a vector containing all impls
|
/// Returns a vector containing all impls
|
||||||
pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
|
pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
|
||||||
let impls = self.trait_impls_of(def_id);
|
let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id);
|
||||||
|
|
||||||
impls
|
blanket_impls
|
||||||
.blanket_impls
|
.into_iter()
|
||||||
.iter()
|
.chain(non_blanket_impls.into_iter().map(|(_, v)| v).flatten())
|
||||||
.chain(impls.non_blanket_impls.values().flatten())
|
|
||||||
.cloned()
|
.cloned()
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,8 +116,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
|
||||||
.predicates_of(source.def_id())
|
.predicates_of(source.def_id())
|
||||||
.predicates
|
.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None })
|
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
|
||||||
.collect();
|
|
||||||
if !traits::normalize_and_test_predicates(
|
if !traits::normalize_and_test_predicates(
|
||||||
tcx,
|
tcx,
|
||||||
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
|
||||||
|
|
|
@ -418,7 +418,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
|
let opaque_type = tcx.mk_opaque(def_id, opaque_defn.substs);
|
||||||
|
|
||||||
let required_region_bounds =
|
let required_region_bounds =
|
||||||
required_region_bounds(tcx, opaque_type, bounds.predicates);
|
required_region_bounds(tcx, opaque_type, bounds.predicates.into_iter());
|
||||||
debug_assert!(!required_region_bounds.is_empty());
|
debug_assert!(!required_region_bounds.is_empty());
|
||||||
|
|
||||||
for required_region in required_region_bounds {
|
for required_region in required_region_bounds {
|
||||||
|
@ -1137,7 +1137,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
|
||||||
|
|
||||||
debug!("instantiate_opaque_types: bounds={:?}", bounds);
|
debug!("instantiate_opaque_types: bounds={:?}", bounds);
|
||||||
|
|
||||||
let required_region_bounds = required_region_bounds(tcx, ty, bounds.predicates.clone());
|
let required_region_bounds =
|
||||||
|
required_region_bounds(tcx, ty, bounds.predicates.iter().cloned());
|
||||||
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
|
debug!("instantiate_opaque_types: required_region_bounds={:?}", required_region_bounds);
|
||||||
|
|
||||||
// Make sure that we are in fact defining the *entire* type
|
// Make sure that we are in fact defining the *entire* type
|
||||||
|
@ -1259,17 +1260,15 @@ pub fn may_define_opaque_type(
|
||||||
crate fn required_region_bounds(
|
crate fn required_region_bounds(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
erased_self_ty: Ty<'tcx>,
|
erased_self_ty: Ty<'tcx>,
|
||||||
predicates: Vec<ty::Predicate<'tcx>>,
|
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
||||||
) -> Vec<ty::Region<'tcx>> {
|
) -> Vec<ty::Region<'tcx>> {
|
||||||
debug!(
|
debug!("required_region_bounds(erased_self_ty={:?})", erased_self_ty);
|
||||||
"required_region_bounds(erased_self_ty={:?}, predicates={:?})",
|
|
||||||
erased_self_ty, predicates
|
|
||||||
);
|
|
||||||
|
|
||||||
assert!(!erased_self_ty.has_escaping_bound_vars());
|
assert!(!erased_self_ty.has_escaping_bound_vars());
|
||||||
|
|
||||||
traits::elaborate_predicates(tcx, predicates)
|
traits::elaborate_predicates(tcx, predicates)
|
||||||
.filter_map(|obligation| {
|
.filter_map(|obligation| {
|
||||||
|
debug!("required_region_bounds(obligation={:?})", obligation);
|
||||||
match obligation.predicate {
|
match obligation.predicate {
|
||||||
ty::Predicate::Projection(..)
|
ty::Predicate::Projection(..)
|
||||||
| ty::Predicate::Trait(..)
|
| ty::Predicate::Trait(..)
|
||||||
|
|
|
@ -281,7 +281,7 @@ impl AutoTraitFinder<'tcx> {
|
||||||
},
|
},
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let mut computed_preds: FxHashSet<_> = param_env.caller_bounds.iter().cloned().collect();
|
let computed_preds = param_env.caller_bounds.iter().cloned();
|
||||||
let mut user_computed_preds: FxHashSet<_> =
|
let mut user_computed_preds: FxHashSet<_> =
|
||||||
user_env.caller_bounds.iter().cloned().collect();
|
user_env.caller_bounds.iter().cloned().collect();
|
||||||
|
|
||||||
|
@ -358,10 +358,11 @@ impl AutoTraitFinder<'tcx> {
|
||||||
_ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
|
_ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
|
||||||
};
|
};
|
||||||
|
|
||||||
computed_preds.extend(user_computed_preds.iter().cloned());
|
let normalized_preds = elaborate_predicates(
|
||||||
let normalized_preds =
|
tcx,
|
||||||
elaborate_predicates(tcx, computed_preds.iter().cloned().collect())
|
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
|
||||||
.map(|o| o.predicate);
|
)
|
||||||
|
.map(|o| o.predicate);
|
||||||
new_env =
|
new_env =
|
||||||
ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
|
ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
|
||||||
}
|
}
|
||||||
|
@ -739,7 +740,7 @@ impl AutoTraitFinder<'tcx> {
|
||||||
if p.ty().skip_binder().has_infer_types() {
|
if p.ty().skip_binder().has_infer_types() {
|
||||||
if !self.evaluate_nested_obligations(
|
if !self.evaluate_nested_obligations(
|
||||||
ty,
|
ty,
|
||||||
v.clone().iter().cloned(),
|
v.into_iter(),
|
||||||
computed_preds,
|
computed_preds,
|
||||||
fresh_preds,
|
fresh_preds,
|
||||||
predicates,
|
predicates,
|
||||||
|
|
|
@ -1017,7 +1017,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
for obligation in super::elaborate_predicates(self.tcx, vec![*cond]) {
|
for obligation in super::elaborate_predicates(self.tcx, std::iter::once(*cond)) {
|
||||||
if let ty::Predicate::Trait(implication, _) = obligation.predicate {
|
if let ty::Predicate::Trait(implication, _) = obligation.predicate {
|
||||||
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();
|
||||||
|
@ -1218,8 +1218,7 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
|
|
||||||
match simp {
|
match simp {
|
||||||
Some(simp) => all_impls
|
Some(simp) => all_impls
|
||||||
.iter()
|
.filter_map(|def_id| {
|
||||||
.filter_map(|&def_id| {
|
|
||||||
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
|
let imp = self.tcx.impl_trait_ref(def_id).unwrap();
|
||||||
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
|
let imp_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
|
||||||
if let Some(imp_simp) = imp_simp {
|
if let Some(imp_simp) = imp_simp {
|
||||||
|
@ -1227,13 +1226,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(imp)
|
Some(imp)
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
None => {
|
None => all_impls.map(|def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect(),
|
||||||
all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -110,8 +110,8 @@ pub enum TraitQueryMode {
|
||||||
pub fn predicates_for_generics<'tcx>(
|
pub fn predicates_for_generics<'tcx>(
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
generic_bounds: &ty::InstantiatedPredicates<'tcx>,
|
generic_bounds: ty::InstantiatedPredicates<'tcx>,
|
||||||
) -> PredicateObligations<'tcx> {
|
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
|
||||||
util::predicates_for_generics(cause, 0, param_env, generic_bounds)
|
util::predicates_for_generics(cause, 0, param_env, generic_bounds)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ pub fn normalize_param_env_or_error<'tcx>(
|
||||||
);
|
);
|
||||||
|
|
||||||
let mut predicates: Vec<_> =
|
let mut predicates: Vec<_> =
|
||||||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec())
|
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.into_iter().cloned())
|
||||||
.map(|obligation| obligation.predicate)
|
.map(|obligation| obligation.predicate)
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
|
|
|
@ -302,7 +302,7 @@ fn generics_require_sized_self(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
|
||||||
// Search for a predicate like `Self : Sized` amongst the trait bounds.
|
// Search for a predicate like `Self : Sized` amongst the trait bounds.
|
||||||
let predicates = tcx.predicates_of(def_id);
|
let predicates = tcx.predicates_of(def_id);
|
||||||
let predicates = predicates.instantiate_identity(tcx).predicates;
|
let predicates = predicates.instantiate_identity(tcx).predicates;
|
||||||
elaborate_predicates(tcx, predicates).any(|obligation| match obligation.predicate {
|
elaborate_predicates(tcx, predicates.into_iter()).any(|obligation| match obligation.predicate {
|
||||||
ty::Predicate::Trait(ref trait_pred, _) => {
|
ty::Predicate::Trait(ref trait_pred, _) => {
|
||||||
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
|
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
|
||||||
}
|
}
|
||||||
|
|
|
@ -900,7 +900,7 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||||
// If so, extract what we know from the trait and try to come up with a good answer.
|
// If so, extract what we know from the trait and try to come up with a good answer.
|
||||||
let trait_predicates = tcx.predicates_of(def_id);
|
let trait_predicates = tcx.predicates_of(def_id);
|
||||||
let bounds = trait_predicates.instantiate(tcx, substs);
|
let bounds = trait_predicates.instantiate(tcx, substs);
|
||||||
let bounds = elaborate_predicates(tcx, bounds.predicates).map(|o| o.predicate);
|
let bounds = elaborate_predicates(tcx, bounds.predicates.into_iter()).map(|o| o.predicate);
|
||||||
assemble_candidates_from_predicates(
|
assemble_candidates_from_predicates(
|
||||||
selcx,
|
selcx,
|
||||||
obligation,
|
obligation,
|
||||||
|
@ -911,16 +911,14 @@ fn assemble_candidates_from_trait_def<'cx, 'tcx>(
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assemble_candidates_from_predicates<'cx, 'tcx, I>(
|
fn assemble_candidates_from_predicates<'cx, 'tcx>(
|
||||||
selcx: &mut SelectionContext<'cx, 'tcx>,
|
selcx: &mut SelectionContext<'cx, 'tcx>,
|
||||||
obligation: &ProjectionTyObligation<'tcx>,
|
obligation: &ProjectionTyObligation<'tcx>,
|
||||||
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
obligation_trait_ref: &ty::TraitRef<'tcx>,
|
||||||
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
|
||||||
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
|
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
|
||||||
env_predicates: I,
|
env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
|
||||||
) where
|
) {
|
||||||
I: IntoIterator<Item = ty::Predicate<'tcx>>,
|
|
||||||
{
|
|
||||||
debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
|
debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
|
||||||
let infcx = selcx.infcx();
|
let infcx = selcx.infcx();
|
||||||
for predicate in env_predicates {
|
for predicate in env_predicates {
|
||||||
|
@ -1153,10 +1151,8 @@ fn confirm_object_candidate<'cx, 'tcx>(
|
||||||
object_ty
|
object_ty
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let env_predicates = data
|
let env_predicates =
|
||||||
.projection_bounds()
|
data.projection_bounds().map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate());
|
||||||
.map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
|
|
||||||
.collect();
|
|
||||||
let env_predicate = {
|
let env_predicate = {
|
||||||
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
|
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);
|
||||||
|
|
||||||
|
|
|
@ -1443,7 +1443,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
|
||||||
bounds
|
bounds
|
||||||
);
|
);
|
||||||
|
|
||||||
let elaborated_predicates = util::elaborate_predicates(self.tcx(), bounds.predicates);
|
let elaborated_predicates =
|
||||||
|
util::elaborate_predicates(self.tcx(), bounds.predicates.into_iter());
|
||||||
let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
|
let matching_bound = elaborated_predicates.filter_to_traits().find(|bound| {
|
||||||
self.infcx.probe(|_| {
|
self.infcx.probe(|_| {
|
||||||
self.match_projection(
|
self.match_projection(
|
||||||
|
|
|
@ -189,26 +189,22 @@ fn fulfill_implication<'a, 'tcx>(
|
||||||
|
|
||||||
let selcx = &mut SelectionContext::new(&infcx);
|
let selcx = &mut SelectionContext::new(&infcx);
|
||||||
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
|
let target_substs = infcx.fresh_substs_for_item(DUMMY_SP, target_impl);
|
||||||
let (target_trait_ref, mut obligations) =
|
let (target_trait_ref, obligations) =
|
||||||
impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
|
impl_trait_ref_and_oblig(selcx, param_env, target_impl, target_substs);
|
||||||
debug!(
|
|
||||||
"fulfill_implication: target_trait_ref={:?}, obligations={:?}",
|
|
||||||
target_trait_ref, obligations
|
|
||||||
);
|
|
||||||
|
|
||||||
// do the impls unify? If not, no specialization.
|
// do the impls unify? If not, no specialization.
|
||||||
match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) {
|
let more_obligations =
|
||||||
Ok(InferOk { obligations: o, .. }) => {
|
match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref)
|
||||||
obligations.extend(o);
|
{
|
||||||
}
|
Ok(InferOk { obligations, .. }) => obligations,
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
debug!(
|
debug!(
|
||||||
"fulfill_implication: {:?} does not unify with {:?}",
|
"fulfill_implication: {:?} does not unify with {:?}",
|
||||||
source_trait_ref, target_trait_ref
|
source_trait_ref, target_trait_ref
|
||||||
);
|
);
|
||||||
return Err(());
|
return Err(());
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// attempt to prove all of the predicates for impl2 given those for impl1
|
// attempt to prove all of the predicates for impl2 given those for impl1
|
||||||
// (which are packed up in penv)
|
// (which are packed up in penv)
|
||||||
|
@ -226,7 +222,7 @@ fn fulfill_implication<'a, 'tcx>(
|
||||||
// we already make a mockery out of the region system, so
|
// we already make a mockery out of the region system, so
|
||||||
// why not ignore them a bit earlier?
|
// why not ignore them a bit earlier?
|
||||||
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
|
let mut fulfill_cx = FulfillmentContext::new_ignoring_regions();
|
||||||
for oblig in obligations.into_iter() {
|
for oblig in obligations.chain(more_obligations) {
|
||||||
fulfill_cx.register_predicate_obligation(&infcx, oblig);
|
fulfill_cx.register_predicate_obligation(&infcx, oblig);
|
||||||
}
|
}
|
||||||
match fulfill_cx.select_all_or_error(infcx) {
|
match fulfill_cx.select_all_or_error(infcx) {
|
||||||
|
@ -261,7 +257,7 @@ pub(super) fn specialization_graph_provider(
|
||||||
) -> &specialization_graph::Graph {
|
) -> &specialization_graph::Graph {
|
||||||
let mut sg = specialization_graph::Graph::new();
|
let mut sg = specialization_graph::Graph::new();
|
||||||
|
|
||||||
let mut trait_impls = tcx.all_impls(trait_id);
|
let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect();
|
||||||
|
|
||||||
// The coherence checking implementation seems to rely on impls being
|
// The coherence checking implementation seems to rely on impls being
|
||||||
// iterated over (roughly) in definition order, so we are sorting by
|
// iterated over (roughly) in definition order, so we are sorting by
|
||||||
|
|
|
@ -81,12 +81,10 @@ impl<'tcx> TraitAliasExpansionInfo<'tcx> {
|
||||||
|
|
||||||
pub fn expand_trait_aliases<'tcx>(
|
pub fn expand_trait_aliases<'tcx>(
|
||||||
tcx: TyCtxt<'tcx>,
|
tcx: TyCtxt<'tcx>,
|
||||||
trait_refs: impl IntoIterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
|
trait_refs: impl Iterator<Item = (ty::PolyTraitRef<'tcx>, Span)>,
|
||||||
) -> TraitAliasExpander<'tcx> {
|
) -> TraitAliasExpander<'tcx> {
|
||||||
let items: Vec<_> = trait_refs
|
let items: Vec<_> =
|
||||||
.into_iter()
|
trait_refs.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span)).collect();
|
||||||
.map(|(trait_ref, span)| TraitAliasExpansionInfo::new(trait_ref, span))
|
|
||||||
.collect();
|
|
||||||
TraitAliasExpander { tcx, stack: items }
|
TraitAliasExpander { tcx, stack: items }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -199,7 +197,7 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
impl_def_id: DefId,
|
impl_def_id: DefId,
|
||||||
impl_substs: SubstsRef<'tcx>,
|
impl_substs: SubstsRef<'tcx>,
|
||||||
) -> (ty::TraitRef<'tcx>, Vec<PredicateObligation<'tcx>>) {
|
) -> (ty::TraitRef<'tcx>, impl Iterator<Item = PredicateObligation<'tcx>>) {
|
||||||
let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
|
let impl_trait_ref = selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
|
||||||
let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
|
let impl_trait_ref = impl_trait_ref.subst(selcx.tcx(), impl_substs);
|
||||||
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
|
let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
|
||||||
|
@ -210,13 +208,11 @@ pub fn impl_trait_ref_and_oblig<'a, 'tcx>(
|
||||||
let Normalized { value: predicates, obligations: normalization_obligations2 } =
|
let Normalized { value: predicates, obligations: normalization_obligations2 } =
|
||||||
super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
|
super::normalize(selcx, param_env, ObligationCause::dummy(), &predicates);
|
||||||
let impl_obligations =
|
let impl_obligations =
|
||||||
predicates_for_generics(ObligationCause::dummy(), 0, param_env, &predicates);
|
predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates);
|
||||||
|
|
||||||
let impl_obligations: Vec<_> = impl_obligations
|
let impl_obligations = impl_obligations
|
||||||
.into_iter()
|
.chain(normalization_obligations1.into_iter())
|
||||||
.chain(normalization_obligations1)
|
.chain(normalization_obligations2.into_iter());
|
||||||
.chain(normalization_obligations2)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
(impl_trait_ref, impl_obligations)
|
(impl_trait_ref, impl_obligations)
|
||||||
}
|
}
|
||||||
|
@ -226,20 +222,16 @@ pub fn predicates_for_generics<'tcx>(
|
||||||
cause: ObligationCause<'tcx>,
|
cause: ObligationCause<'tcx>,
|
||||||
recursion_depth: usize,
|
recursion_depth: usize,
|
||||||
param_env: ty::ParamEnv<'tcx>,
|
param_env: ty::ParamEnv<'tcx>,
|
||||||
generic_bounds: &ty::InstantiatedPredicates<'tcx>,
|
generic_bounds: ty::InstantiatedPredicates<'tcx>,
|
||||||
) -> Vec<PredicateObligation<'tcx>> {
|
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
|
||||||
debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
|
debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
|
||||||
|
|
||||||
generic_bounds
|
generic_bounds.predicates.into_iter().map(move |predicate| Obligation {
|
||||||
.predicates
|
cause: cause.clone(),
|
||||||
.iter()
|
recursion_depth,
|
||||||
.map(|&predicate| Obligation {
|
param_env,
|
||||||
cause: cause.clone(),
|
predicate,
|
||||||
recursion_depth,
|
})
|
||||||
param_env,
|
|
||||||
predicate,
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn predicate_for_trait_ref<'tcx>(
|
pub fn predicate_for_trait_ref<'tcx>(
|
||||||
|
|
|
@ -140,7 +140,7 @@ fn extend_cause_with_original_assoc_item_obligation<'tcx>(
|
||||||
item: Option<&hir::Item<'tcx>>,
|
item: Option<&hir::Item<'tcx>>,
|
||||||
cause: &mut traits::ObligationCause<'tcx>,
|
cause: &mut traits::ObligationCause<'tcx>,
|
||||||
pred: &ty::Predicate<'_>,
|
pred: &ty::Predicate<'_>,
|
||||||
mut trait_assoc_items: impl Iterator<Item = ty::AssocItem>,
|
mut trait_assoc_items: impl Iterator<Item = &'tcx ty::AssocItem>,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(
|
||||||
"extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
|
"extended_cause_with_original_assoc_item_obligation {:?} {:?} {:?} {:?}",
|
||||||
|
@ -232,34 +232,33 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
|
||||||
|
|
||||||
let item = self.item;
|
let item = self.item;
|
||||||
|
|
||||||
if let Elaborate::All = elaborate {
|
let extend = |obligation: traits::PredicateObligation<'tcx>| {
|
||||||
let implied_obligations = traits::util::elaborate_obligations(tcx, obligations.clone());
|
let mut cause = cause.clone();
|
||||||
let implied_obligations = implied_obligations.map(|obligation| {
|
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
|
||||||
debug!("compute_trait_ref implied_obligation {:?}", obligation);
|
let derived_cause = traits::DerivedObligationCause {
|
||||||
debug!("compute_trait_ref implied_obligation cause {:?}", obligation.cause);
|
parent_trait_ref,
|
||||||
let mut cause = cause.clone();
|
parent_code: Rc::new(obligation.cause.code.clone()),
|
||||||
if let Some(parent_trait_ref) = obligation.predicate.to_opt_poly_trait_ref() {
|
};
|
||||||
let derived_cause = traits::DerivedObligationCause {
|
cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause);
|
||||||
parent_trait_ref,
|
}
|
||||||
parent_code: Rc::new(obligation.cause.code.clone()),
|
extend_cause_with_original_assoc_item_obligation(
|
||||||
};
|
tcx,
|
||||||
cause.code = traits::ObligationCauseCode::DerivedObligation(derived_cause);
|
trait_ref,
|
||||||
}
|
item,
|
||||||
extend_cause_with_original_assoc_item_obligation(
|
&mut cause,
|
||||||
tcx,
|
&obligation.predicate,
|
||||||
trait_ref,
|
tcx.associated_items(trait_ref.def_id).in_definition_order(),
|
||||||
item,
|
);
|
||||||
&mut cause,
|
traits::Obligation::new(cause, param_env, obligation.predicate)
|
||||||
&obligation.predicate,
|
};
|
||||||
tcx.associated_items(trait_ref.def_id).in_definition_order().copied(),
|
|
||||||
);
|
|
||||||
debug!("compute_trait_ref new cause {:?}", cause);
|
|
||||||
traits::Obligation::new(cause, param_env, obligation.predicate)
|
|
||||||
});
|
|
||||||
self.out.extend(implied_obligations);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.out.extend(obligations);
|
if let Elaborate::All = elaborate {
|
||||||
|
let implied_obligations = traits::util::elaborate_obligations(tcx, obligations);
|
||||||
|
let implied_obligations = implied_obligations.map(extend);
|
||||||
|
self.out.extend(implied_obligations);
|
||||||
|
} else {
|
||||||
|
self.out.extend(obligations);
|
||||||
|
}
|
||||||
|
|
||||||
self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
|
self.out.extend(trait_ref.substs.types().filter(|ty| !ty.has_escaping_bound_vars()).map(
|
||||||
|ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
|
|ty| traits::Obligation::new(cause.clone(), param_env, ty::Predicate::WellFormed(ty)),
|
||||||
|
@ -627,16 +626,13 @@ pub fn object_region_bounds<'tcx>(
|
||||||
// a placeholder type.
|
// a placeholder type.
|
||||||
let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
|
let open_ty = tcx.mk_ty_infer(ty::FreshTy(0));
|
||||||
|
|
||||||
let predicates = existential_predicates
|
let predicates = existential_predicates.iter().filter_map(|predicate| {
|
||||||
.iter()
|
if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
|
||||||
.filter_map(|predicate| {
|
None
|
||||||
if let ty::ExistentialPredicate::Projection(_) = *predicate.skip_binder() {
|
} else {
|
||||||
None
|
Some(predicate.with_self_ty(tcx, open_ty))
|
||||||
} else {
|
}
|
||||||
Some(predicate.with_self_ty(tcx, open_ty))
|
});
|
||||||
}
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
required_region_bounds(tcx, open_ty, predicates)
|
required_region_bounds(tcx, open_ty, predicates)
|
||||||
}
|
}
|
||||||
|
|
|
@ -114,7 +114,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
// a custom error in that case.
|
// a custom error in that case.
|
||||||
if illegal_sized_bound.is_none() {
|
if illegal_sized_bound.is_none() {
|
||||||
let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
|
let method_ty = self.tcx.mk_fn_ptr(ty::Binder::bind(method_sig));
|
||||||
self.add_obligations(method_ty, all_substs, &method_predicates);
|
self.add_obligations(method_ty, all_substs, method_predicates);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the final `MethodCallee`.
|
// Create the final `MethodCallee`.
|
||||||
|
@ -394,7 +394,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
&mut self,
|
&mut self,
|
||||||
fty: Ty<'tcx>,
|
fty: Ty<'tcx>,
|
||||||
all_substs: SubstsRef<'tcx>,
|
all_substs: SubstsRef<'tcx>,
|
||||||
method_predicates: &ty::InstantiatedPredicates<'tcx>,
|
method_predicates: ty::InstantiatedPredicates<'tcx>,
|
||||||
) {
|
) {
|
||||||
debug!(
|
debug!(
|
||||||
"add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
|
"add_obligations: fty={:?} all_substs={:?} method_predicates={:?}",
|
||||||
|
@ -571,7 +571,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
|
||||||
None => return None,
|
None => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
traits::elaborate_predicates(self.tcx, predicates.predicates.clone())
|
traits::elaborate_predicates(self.tcx, predicates.predicates.iter().copied())
|
||||||
.filter_map(|obligation| match obligation.predicate {
|
.filter_map(|obligation| match obligation.predicate {
|
||||||
ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
|
ty::Predicate::Trait(trait_pred, _) if trait_pred.def_id() == sized_def_id => {
|
||||||
let span = predicates
|
let span = predicates
|
||||||
|
|
|
@ -390,7 +390,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
assert!(!bounds.has_escaping_bound_vars());
|
assert!(!bounds.has_escaping_bound_vars());
|
||||||
|
|
||||||
let cause = traits::ObligationCause::misc(span, self.body_id);
|
let cause = traits::ObligationCause::misc(span, self.body_id);
|
||||||
obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, &bounds));
|
obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
|
||||||
|
|
||||||
// Also add an obligation for the method type being well-formed.
|
// Also add an obligation for the method type being well-formed.
|
||||||
let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig));
|
let method_ty = tcx.mk_fn_ptr(ty::Binder::bind(fn_sig));
|
||||||
|
|
|
@ -1342,7 +1342,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
// clauses) that must be considered. Make sure that those
|
// clauses) that must be considered. Make sure that those
|
||||||
// match as well (or at least may match, sometimes we
|
// match as well (or at least may match, sometimes we
|
||||||
// don't have enough information to fully evaluate).
|
// don't have enough information to fully evaluate).
|
||||||
let candidate_obligations: Vec<_> = match probe.kind {
|
match probe.kind {
|
||||||
InherentImplCandidate(ref substs, ref ref_obligations) => {
|
InherentImplCandidate(ref substs, ref ref_obligations) => {
|
||||||
// Check whether the impl imposes obligations we have to worry about.
|
// Check whether the impl imposes obligations we have to worry about.
|
||||||
let impl_def_id = probe.item.container.id();
|
let impl_def_id = probe.item.container.id();
|
||||||
|
@ -1353,19 +1353,23 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
|
|
||||||
// Convert the bounds into obligations.
|
// Convert the bounds into obligations.
|
||||||
let impl_obligations =
|
let impl_obligations =
|
||||||
traits::predicates_for_generics(cause, self.param_env, &impl_bounds);
|
traits::predicates_for_generics(cause, self.param_env, impl_bounds);
|
||||||
|
|
||||||
debug!("impl_obligations={:?}", impl_obligations);
|
let candidate_obligations = impl_obligations
|
||||||
impl_obligations
|
|
||||||
.into_iter()
|
|
||||||
.chain(norm_obligations.into_iter())
|
.chain(norm_obligations.into_iter())
|
||||||
.chain(ref_obligations.iter().cloned())
|
.chain(ref_obligations.iter().cloned());
|
||||||
.collect()
|
// Evaluate those obligations to see if they might possibly hold.
|
||||||
|
for o in candidate_obligations {
|
||||||
|
let o = self.resolve_vars_if_possible(&o);
|
||||||
|
if !self.predicate_may_hold(&o) {
|
||||||
|
result = ProbeResult::NoMatch;
|
||||||
|
possibly_unsatisfied_predicates.push((o.predicate, None));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ObjectCandidate | WhereClauseCandidate(..) => {
|
ObjectCandidate | WhereClauseCandidate(..) => {
|
||||||
// These have no additional conditions to check.
|
// These have no additional conditions to check.
|
||||||
vec![]
|
|
||||||
}
|
}
|
||||||
|
|
||||||
TraitCandidate(trait_ref) => {
|
TraitCandidate(trait_ref) => {
|
||||||
|
@ -1412,17 +1416,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
|
||||||
return ProbeResult::NoMatch;
|
return ProbeResult::NoMatch;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vec![]
|
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
debug!(
|
|
||||||
"consider_probe - candidate_obligations={:?} sub_obligations={:?}",
|
|
||||||
candidate_obligations, sub_obligations
|
|
||||||
);
|
|
||||||
|
|
||||||
// Evaluate those obligations to see if they might possibly hold.
|
// Evaluate those obligations to see if they might possibly hold.
|
||||||
for o in candidate_obligations.into_iter().chain(sub_obligations) {
|
for o in sub_obligations {
|
||||||
let o = self.resolve_vars_if_possible(&o);
|
let o = self.resolve_vars_if_possible(&o);
|
||||||
if !self.predicate_may_hold(&o) {
|
if !self.predicate_may_hold(&o) {
|
||||||
result = ProbeResult::NoMatch;
|
result = ProbeResult::NoMatch;
|
||||||
|
|
|
@ -3460,7 +3460,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
pub fn add_obligations_for_parameters(
|
pub fn add_obligations_for_parameters(
|
||||||
&self,
|
&self,
|
||||||
cause: traits::ObligationCause<'tcx>,
|
cause: traits::ObligationCause<'tcx>,
|
||||||
predicates: &ty::InstantiatedPredicates<'tcx>,
|
predicates: ty::InstantiatedPredicates<'tcx>,
|
||||||
) {
|
) {
|
||||||
assert!(!predicates.has_escaping_bound_vars());
|
assert!(!predicates.has_escaping_bound_vars());
|
||||||
|
|
||||||
|
@ -4411,7 +4411,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
let (bounds, _) = self.instantiate_bounds(path_span, did, substs);
|
let (bounds, _) = self.instantiate_bounds(path_span, did, substs);
|
||||||
let cause =
|
let cause =
|
||||||
traits::ObligationCause::new(path_span, self.body_id, traits::ItemObligation(did));
|
traits::ObligationCause::new(path_span, self.body_id, traits::ItemObligation(did));
|
||||||
self.add_obligations_for_parameters(cause, &bounds);
|
self.add_obligations_for_parameters(cause, bounds);
|
||||||
|
|
||||||
Some((variant, ty))
|
Some((variant, ty))
|
||||||
} else {
|
} else {
|
||||||
|
@ -5681,9 +5681,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||||
for (i, mut obligation) in traits::predicates_for_generics(
|
for (i, mut obligation) in traits::predicates_for_generics(
|
||||||
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
|
traits::ObligationCause::new(span, self.body_id, traits::ItemObligation(def_id)),
|
||||||
self.param_env,
|
self.param_env,
|
||||||
&bounds,
|
bounds,
|
||||||
)
|
)
|
||||||
.into_iter()
|
|
||||||
.enumerate()
|
.enumerate()
|
||||||
{
|
{
|
||||||
// This makes the error point at the bound, but we want to point at the argument
|
// This makes the error point at the bound, but we want to point at the argument
|
||||||
|
|
|
@ -1233,7 +1233,7 @@ fn check_false_global_bounds(fcx: &FnCtxt<'_, '_>, span: Span, id: hir::HirId) {
|
||||||
let empty_env = ty::ParamEnv::empty();
|
let empty_env = ty::ParamEnv::empty();
|
||||||
|
|
||||||
let def_id = fcx.tcx.hir().local_def_id(id);
|
let def_id = fcx.tcx.hir().local_def_id(id);
|
||||||
let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p).collect();
|
let predicates = fcx.tcx.predicates_of(def_id).predicates.iter().map(|(p, _)| *p);
|
||||||
// Check elaborated bounds.
|
// Check elaborated bounds.
|
||||||
let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
|
let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates);
|
||||||
|
|
||||||
|
|
|
@ -329,7 +329,7 @@ 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: Vec<_> = impl1_predicates
|
let always_applicable_traits = impl1_predicates
|
||||||
.predicates
|
.predicates
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|predicate| {
|
.filter(|predicate| {
|
||||||
|
@ -338,8 +338,7 @@ fn check_predicates<'tcx>(
|
||||||
Some(TraitSpecializationKind::AlwaysApplicable)
|
Some(TraitSpecializationKind::AlwaysApplicable)
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
.copied()
|
.copied();
|
||||||
.collect();
|
|
||||||
|
|
||||||
// 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() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue