Skip to content
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

Remove some Vec allocations to improve performance #71268

Merged
merged 4 commits into from
Apr 27, 2020
Merged
Show file tree
Hide file tree
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
12 changes: 4 additions & 8 deletions src/librustc_infer/infer/outlives/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 as Foo<'a>>::Item`.
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
// constraints in the fn signature. To do that, we walk the list
Expand Down Expand Up @@ -315,15 +315,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
let tcx = self.tcx;
let assoc_item = tcx.associated_item(assoc_item_def_id);
let trait_def_id = assoc_item.container.assert_trait();
let trait_predicates =
tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p).collect();
let trait_predicates = tcx.predicates_of(trait_def_id).predicates.iter().map(|(p, _)| *p);
let identity_substs = InternalSubsts::identity_for_item(tcx, assoc_item_def_id);
let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs);
self.collect_outlives_from_predicate_list(
move |ty| ty == identity_proj,
traits::elaborate_predicates(tcx, trait_predicates)
.map(|o| o.predicate)
.collect::<Vec<_>>(),
traits::elaborate_predicates(tcx, trait_predicates).map(|o| o.predicate),
)
.map(|b| b.1)
}
Expand All @@ -337,10 +334,9 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
fn collect_outlives_from_predicate_list(
&self,
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>>> {
predicates
.into_iter()
.filter_map(|p| p.as_ref().to_opt_type_outlives())
.filter_map(|p| p.no_bound_vars())
.filter(move |p| compare_ty(p.0))
Expand Down
17 changes: 7 additions & 10 deletions src/librustc_infer/traits/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,24 +97,22 @@ pub fn elaborate_trait_ref<'tcx>(
tcx: TyCtxt<'tcx>,
trait_ref: ty::PolyTraitRef<'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>(
tcx: TyCtxt<'tcx>,
trait_refs: impl Iterator<Item = ty::PolyTraitRef<'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)
}

pub fn elaborate_predicates<'tcx>(
tcx: TyCtxt<'tcx>,
mut predicates: Vec<ty::Predicate<'tcx>>,
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> Elaborator<'tcx> {
let mut visited = PredicateSet::new(tcx);
predicates.retain(|pred| visited.insert(pred));
let obligations: Vec<_> =
let obligations =
predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect();
elaborate_obligations(tcx, obligations)
}
Expand Down Expand Up @@ -151,21 +149,20 @@ impl Elaborator<'tcx> {
// Get predicates declared on the trait.
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(
pred.subst_supertrait(tcx, &data.to_poly_trait_ref()),
Some(*span),
)
});
debug!("super_predicates: data={:?} predicates={:?}", data, &obligations);
debug!("super_predicates: data={:?}", data);

// Only keep those bounds that we haven't already seen.
// This is necessary to prevent infinite recursion in some
// cases. One common case is when people define
// `trait Sized: Sized { }` rather than `trait Sized { }`.
let visited = &mut self.visited;
let obligations =
obligations.filter(|obligation| visited.insert(&obligation.predicate));
let obligations = obligations.filter(|o| visited.insert(&o.predicate));

self.stack.extend(obligations);
}
Expand Down
12 changes: 5 additions & 7 deletions src/librustc_middle/ty/trait_def.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,15 +168,13 @@ impl<'tcx> TyCtxt<'tcx> {
}

/// Returns a vector containing all impls
pub fn all_impls(self, def_id: DefId) -> Vec<DefId> {
let impls = self.trait_impls_of(def_id);
pub fn all_impls(self, def_id: DefId) -> impl Iterator<Item = DefId> + 'tcx {
let TraitImpls { blanket_impls, non_blanket_impls } = self.trait_impls_of(def_id);

impls
.blanket_impls
.iter()
.chain(impls.non_blanket_impls.values().flatten())
blanket_impls
.into_iter()
.chain(non_blanket_impls.into_iter().map(|(_, v)| v).flatten())
.cloned()
.collect()
}
}

Expand Down
3 changes: 1 addition & 2 deletions src/librustc_mir/transform/const_prop.rs
Original file line number Diff line number Diff line change
Expand Up @@ -122,8 +122,7 @@ impl<'tcx> MirPass<'tcx> for ConstProp {
.predicates_of(source.def_id())
.predicates
.iter()
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None })
.collect();
.filter_map(|(p, _)| if p.is_global() { Some(*p) } else { None });
if !traits::normalize_and_test_predicates(
tcx,
traits::elaborate_predicates(tcx, predicates).map(|o| o.predicate).collect(),
Expand Down
13 changes: 6 additions & 7 deletions src/librustc_trait_selection/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 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());

for required_region in required_region_bounds {
Expand Down Expand Up @@ -1127,7 +1127,8 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {

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);

// Make sure that we are in fact defining the *entire* type
Expand Down Expand Up @@ -1245,17 +1246,15 @@ pub fn may_define_opaque_type(tcx: TyCtxt<'_>, def_id: DefId, opaque_hir_id: hir
crate fn required_region_bounds(
tcx: TyCtxt<'tcx>,
erased_self_ty: Ty<'tcx>,
predicates: Vec<ty::Predicate<'tcx>>,
predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) -> Vec<ty::Region<'tcx>> {
debug!(
"required_region_bounds(erased_self_ty={:?}, predicates={:?})",
erased_self_ty, predicates
);
debug!("required_region_bounds(erased_self_ty={:?})", erased_self_ty);

assert!(!erased_self_ty.has_escaping_bound_vars());

traits::elaborate_predicates(tcx, predicates)
.filter_map(|obligation| {
debug!("required_region_bounds(obligation={:?})", obligation);
match obligation.predicate {
ty::Predicate::Projection(..)
| ty::Predicate::Trait(..)
Expand Down
13 changes: 7 additions & 6 deletions src/librustc_trait_selection/traits/auto_trait.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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<_> =
user_env.caller_bounds.iter().cloned().collect();

Expand Down Expand Up @@ -358,10 +358,11 @@ impl AutoTraitFinder<'tcx> {
_ => panic!("Unexpected error for '{:?}': {:?}", ty, result),
};

computed_preds.extend(user_computed_preds.iter().cloned());
let normalized_preds =
elaborate_predicates(tcx, computed_preds.iter().cloned().collect())
.map(|o| o.predicate);
let normalized_preds = elaborate_predicates(
tcx,
computed_preds.clone().chain(user_computed_preds.iter().cloned()),
)
.map(|o| o.predicate);
new_env =
ty::ParamEnv::new(tcx.mk_predicates(normalized_preds), param_env.reveal, None);
}
Expand Down Expand Up @@ -739,7 +740,7 @@ impl AutoTraitFinder<'tcx> {
if p.ty().skip_binder().has_infer_types() {
if !self.evaluate_nested_obligations(
ty,
v.clone().iter().cloned(),
v.into_iter(),
computed_preds,
fresh_preds,
predicates,
Expand Down
10 changes: 3 additions & 7 deletions src/librustc_trait_selection/traits/error_reporting/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1007,7 +1007,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 {
let error = error.to_poly_trait_ref();
let implication = implication.to_poly_trait_ref();
Expand Down Expand Up @@ -1208,22 +1208,18 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {

match simp {
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_simp = fast_reject::simplify_type(self.tcx, imp.self_ty(), true);
if let Some(imp_simp) = imp_simp {
if simp != imp_simp {
return None;
}
}

Some(imp)
})
.collect(),
None => {
all_impls.iter().map(|&def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect()
}
None => all_impls.map(|def_id| self.tcx.impl_trait_ref(def_id).unwrap()).collect(),
}
}

Expand Down
6 changes: 3 additions & 3 deletions src/librustc_trait_selection/traits/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,8 +110,8 @@ pub enum TraitQueryMode {
pub fn predicates_for_generics<'tcx>(
cause: ObligationCause<'tcx>,
param_env: ty::ParamEnv<'tcx>,
generic_bounds: &ty::InstantiatedPredicates<'tcx>,
) -> PredicateObligations<'tcx> {
generic_bounds: ty::InstantiatedPredicates<'tcx>,
) -> impl Iterator<Item = PredicateObligation<'tcx>> {
util::predicates_for_generics(cause, 0, param_env, generic_bounds)
}

Expand Down Expand Up @@ -297,7 +297,7 @@ pub fn normalize_param_env_or_error<'tcx>(
);

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)
.collect();

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trait_selection/traits/object_safety.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
let predicates = tcx.predicates_of(def_id);
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, _) => {
trait_pred.def_id() == sized_def_id && trait_pred.skip_binder().self_ty().is_param(0)
}
Expand Down
16 changes: 6 additions & 10 deletions src/librustc_trait_selection/traits/project.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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.
let trait_predicates = tcx.predicates_of(def_id);
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(
selcx,
obligation,
Expand All @@ -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>,
obligation: &ProjectionTyObligation<'tcx>,
obligation_trait_ref: &ty::TraitRef<'tcx>,
candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
ctor: fn(ty::PolyProjectionPredicate<'tcx>) -> ProjectionTyCandidate<'tcx>,
env_predicates: I,
) where
I: IntoIterator<Item = ty::Predicate<'tcx>>,
{
env_predicates: impl Iterator<Item = ty::Predicate<'tcx>>,
) {
debug!("assemble_candidates_from_predicates(obligation={:?})", obligation);
let infcx = selcx.infcx();
for predicate in env_predicates {
Expand Down Expand Up @@ -1153,10 +1151,8 @@ fn confirm_object_candidate<'cx, 'tcx>(
object_ty
),
};
let env_predicates = data
.projection_bounds()
.map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate())
.collect();
let env_predicates =
data.projection_bounds().map(|p| p.with_self_ty(selcx.tcx(), object_ty).to_predicate());
let env_predicate = {
let env_predicates = elaborate_predicates(selcx.tcx(), env_predicates);

Expand Down
3 changes: 2 additions & 1 deletion src/librustc_trait_selection/traits/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1443,7 +1443,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
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| {
self.infcx.probe(|_| {
self.match_projection(
Expand Down
34 changes: 15 additions & 19 deletions src/librustc_trait_selection/traits/specialize/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,26 +189,22 @@ fn fulfill_implication<'a, 'tcx>(

let selcx = &mut SelectionContext::new(&infcx);
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);
debug!(
"fulfill_implication: target_trait_ref={:?}, obligations={:?}",
target_trait_ref, obligations
);

// do the impls unify? If not, no specialization.
match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref) {
Ok(InferOk { obligations: o, .. }) => {
obligations.extend(o);
}
Err(_) => {
debug!(
"fulfill_implication: {:?} does not unify with {:?}",
source_trait_ref, target_trait_ref
);
return Err(());
}
}
let more_obligations =
match infcx.at(&ObligationCause::dummy(), param_env).eq(source_trait_ref, target_trait_ref)
{
Ok(InferOk { obligations, .. }) => obligations,
Err(_) => {
debug!(
"fulfill_implication: {:?} does not unify with {:?}",
source_trait_ref, target_trait_ref
);
return Err(());
}
};

// attempt to prove all of the predicates for impl2 given those for impl1
// (which are packed up in penv)
Expand All @@ -226,7 +222,7 @@ fn fulfill_implication<'a, 'tcx>(
// we already make a mockery out of the region system, so
// why not ignore them a bit earlier?
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);
}
match fulfill_cx.select_all_or_error(infcx) {
Expand Down Expand Up @@ -261,7 +257,7 @@ pub(super) fn specialization_graph_provider(
) -> &specialization_graph::Graph {
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
// iterated over (roughly) in definition order, so we are sorting by
Expand Down
Loading