From 98dab3335f8355f8a313d09e0dfe0b8ef9412b35 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 8 Nov 2018 17:14:13 +1100 Subject: [PATCH] Wrap some query results in `Lrc`. So that the frequent clones in `try_get` are cheaper. Fixes #54274. --- src/librustc/infer/outlives/verify.rs | 4 +- src/librustc/traits/object_safety.rs | 5 +- src/librustc/traits/specialize/mod.rs | 2 +- src/librustc/ty/mod.rs | 6 +-- src/librustc/ty/query/mod.rs | 11 ++-- src/librustc_metadata/cstore_impl.rs | 6 +-- src/librustc_traits/lowering/mod.rs | 12 +++-- src/librustc_typeck/astconv.rs | 7 +-- src/librustc_typeck/check/mod.rs | 6 +-- src/librustc_typeck/check/wfcheck.rs | 4 +- src/librustc_typeck/collect.rs | 67 ++++++++++++------------ src/librustc_typeck/outlives/explicit.rs | 6 +-- src/librustdoc/clean/mod.rs | 2 +- src/librustdoc/clean/simplify.rs | 4 +- 14 files changed, 73 insertions(+), 69 deletions(-) diff --git a/src/librustc/infer/outlives/verify.rs b/src/librustc/infer/outlives/verify.rs index a7a79dd2e65..5fee04341b6 100644 --- a/src/librustc/infer/outlives/verify.rs +++ b/src/librustc/infer/outlives/verify.rs @@ -299,8 +299,8 @@ fn region_bounds_declared_on_associated_item( 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 - .into_iter() - .map(|(p, _)| p) + .iter() + .map(|(p, _)| *p) .collect(); let identity_substs = Substs::identity_for_item(tcx, assoc_item_def_id); let identity_proj = tcx.mk_projection(assoc_item_def_id, identity_substs); diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs index 1d76ccdca31..715ce0d7e80 100644 --- a/src/librustc/traits/object_safety.rs +++ b/src/librustc/traits/object_safety.rs @@ -182,7 +182,7 @@ fn predicates_reference_self( }; predicates .predicates - .into_iter() + .iter() .map(|(predicate, _)| predicate.subst_supertrait(self, &trait_ref)) .any(|predicate| { match predicate { @@ -302,9 +302,10 @@ fn virtual_call_violation_for_method(self, return Some(MethodViolationCode::Generic); } - if self.predicates_of(method.def_id).predicates.into_iter() + if self.predicates_of(method.def_id).predicates.iter() // A trait object can't claim to live more than the concrete type, // so outlives predicates will always hold. + .cloned() .filter(|(p, _)| p.to_opt_type_outlives().is_none()) .collect::>() // Do a shallow visit so that `contains_illegal_self_type_reference` diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs index d7b5dd049e3..d3dc1655b0d 100644 --- a/src/librustc/traits/specialize/mod.rs +++ b/src/librustc/traits/specialize/mod.rs @@ -407,7 +407,7 @@ fn to_pretty_impl_header(tcx: TyCtxt<'_, '_, '_>, impl_def_id: DefId) -> Option< // The predicates will contain default bounds like `T: Sized`. We need to // remove these bounds, and add `T: ?Sized` to any untouched type parameters. - let predicates = tcx.predicates_of(impl_def_id).predicates; + let predicates = &tcx.predicates_of(impl_def_id).predicates; let mut pretty_predicates = Vec::with_capacity( predicates.len() + types_without_default_bounds.len()); diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 83feadd50d7..4472f23b2c4 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -2126,7 +2126,7 @@ pub fn non_enum_variant(&self) -> &VariantDef { } #[inline] - pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> GenericPredicates<'gcx> { + pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Lrc> { tcx.predicates_of(self.did) } @@ -2369,8 +2369,8 @@ fn sized_constraint_for_ty(&self, def_id: sized_trait, substs: tcx.mk_substs_trait(ty, &[]) }).to_predicate(); - let predicates = tcx.predicates_of(self.did).predicates; - if predicates.into_iter().any(|(p, _)| p == sized_predicate) { + let predicates = &tcx.predicates_of(self.did).predicates; + if predicates.iter().any(|(p, _)| *p == sized_predicate) { vec![] } else { vec![ty] diff --git a/src/librustc/ty/query/mod.rs b/src/librustc/ty/query/mod.rs index c834166e67d..0052628e12a 100644 --- a/src/librustc/ty/query/mod.rs +++ b/src/librustc/ty/query/mod.rs @@ -127,17 +127,18 @@ /// predicate gets in the way of some checks, which are intended /// to operate over only the actual where-clauses written by the /// user.) - [] fn predicates_of: PredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn predicates_of: PredicatesOfItem(DefId) -> Lrc>, /// Maps from the def-id of an item (trait/struct/enum/fn) to the /// predicates (where clauses) directly defined on it. This is /// equal to the `explicit_predicates_of` predicates plus the /// `inferred_outlives_of` predicates. - [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn predicates_defined_on: PredicatesDefinedOnItem(DefId) + -> Lrc>, /// Returns the predicates written explicit by the user. [] fn explicit_predicates_of: ExplicitPredicatesOfItem(DefId) - -> ty::GenericPredicates<'tcx>, + -> Lrc>, /// Returns the inferred outlives predicates (e.g., for `struct /// Foo<'a, T> { x: &'a T }`, this would return `T: 'a`). @@ -149,12 +150,12 @@ /// evaluate them even during type conversion, often before the /// full predicates are available (note that supertraits have /// additional acyclicity requirements). - [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> ty::GenericPredicates<'tcx>, + [] fn super_predicates_of: SuperPredicatesOfItem(DefId) -> Lrc>, /// To avoid cycles within the predicates of a single item we compute /// per-type-parameter predicates for resolving `T::AssocTy`. [] fn type_param_predicates: type_param_predicates((DefId, DefId)) - -> ty::GenericPredicates<'tcx>, + -> Lrc>, [] fn trait_def: TraitDefOfItem(DefId) -> &'tcx ty::TraitDef, [] fn adt_def: AdtDefOfItem(DefId) -> &'tcx ty::AdtDef, diff --git a/src/librustc_metadata/cstore_impl.rs b/src/librustc_metadata/cstore_impl.rs index e6e1367b592..e1d9ca5339e 100644 --- a/src/librustc_metadata/cstore_impl.rs +++ b/src/librustc_metadata/cstore_impl.rs @@ -103,9 +103,9 @@ fn into_args(self) -> (DefId, DefId) { (self.0.as_def_id(), self.1) } generics_of => { tcx.alloc_generics(cdata.get_generics(def_id.index, tcx.sess)) } - predicates_of => { cdata.get_predicates(def_id.index, tcx) } - predicates_defined_on => { cdata.get_predicates_defined_on(def_id.index, tcx) } - super_predicates_of => { cdata.get_super_predicates(def_id.index, tcx) } + predicates_of => { Lrc::new(cdata.get_predicates(def_id.index, tcx)) } + predicates_defined_on => { Lrc::new(cdata.get_predicates_defined_on(def_id.index, tcx)) } + super_predicates_of => { Lrc::new(cdata.get_super_predicates(def_id.index, tcx)) } trait_def => { tcx.alloc_trait_def(cdata.get_trait_def(def_id.index, tcx.sess)) } diff --git a/src/librustc_traits/lowering/mod.rs b/src/librustc_traits/lowering/mod.rs index 471c0e7abbc..dc47b15a68f 100644 --- a/src/librustc_traits/lowering/mod.rs +++ b/src/librustc_traits/lowering/mod.rs @@ -217,8 +217,9 @@ fn program_clauses_for_trait<'a, 'tcx>( let implemented_from_env = Clause::ForAll(ty::Binder::bind(implemented_from_env)); - let where_clauses = &tcx.predicates_defined_on(def_id).predicates - .into_iter() + let predicates = &tcx.predicates_defined_on(def_id).predicates; + let where_clauses = &predicates + .iter() .map(|(wc, _)| wc.lower()) .map(|wc| wc.subst(tcx, bound_vars)) .collect::>(); @@ -314,8 +315,9 @@ fn program_clauses_for_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId let trait_pred = ty::TraitPredicate { trait_ref }.lower(); // `WC` - let where_clauses = tcx.predicates_of(def_id).predicates - .into_iter() + let predicates = &tcx.predicates_of(def_id).predicates; + let where_clauses = predicates + .iter() .map(|(wc, _)| wc.lower()) .map(|wc| wc.subst(tcx, bound_vars)); @@ -352,7 +354,7 @@ pub fn program_clauses_for_type_def<'a, 'tcx>( // `WC` let where_clauses = tcx.predicates_of(def_id).predicates - .into_iter() + .iter() .map(|(wc, _)| wc.lower()) .map(|wc| wc.subst(tcx, bound_vars)) .collect::>(); diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 572e79407a1..d388d756438 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -24,6 +24,7 @@ use rustc::ty::{self, Ty, TyCtxt, ToPredicate, TypeFoldable}; use rustc::ty::{GenericParamDef, GenericParamDefKind}; use rustc::ty::wf::object_region_bounds; +use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use std::collections::BTreeSet; use std::slice; @@ -45,7 +46,7 @@ pub trait AstConv<'gcx, 'tcx> { /// Returns the set of bounds in scope for the type parameter with /// the given id. fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) - -> ty::GenericPredicates<'tcx>; + -> Lrc>; /// What lifetime should we use when a lifetime is omitted (and not elided)? fn re_infer(&self, span: Span, _def: Option<&ty::GenericParamDef>) @@ -1119,8 +1120,8 @@ fn find_bound_for_assoc_item(&self, { let tcx = self.tcx(); - let bounds = self.get_type_parameter_bounds(span, ty_param_def_id) - .predicates.into_iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()); + let predicates = &self.get_type_parameter_bounds(span, ty_param_def_id).predicates; + let bounds = predicates.iter().filter_map(|(p, _)| p.to_opt_poly_trait_ref()); // Check that there is exactly one way to find an associated type with the // correct name. diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 41e0c6c0a19..c936e0833c0 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -1869,7 +1869,7 @@ impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> { fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx } fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) - -> ty::GenericPredicates<'tcx> + -> Lrc> { let tcx = self.tcx; let node_id = tcx.hir.as_local_node_id(def_id).unwrap(); @@ -1877,7 +1877,7 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) let item_def_id = tcx.hir.local_def_id(item_id); let generics = tcx.generics_of(item_def_id); let index = generics.param_def_id_to_index[&def_id]; - ty::GenericPredicates { + Lrc::new(ty::GenericPredicates { parent: None, predicates: self.param_env.caller_bounds.iter().filter_map(|&predicate| { match predicate { @@ -1890,7 +1890,7 @@ fn get_type_parameter_bounds(&self, _: Span, def_id: DefId) _ => None } }).collect() - } + }) } fn re_infer(&self, span: Span, def: Option<&ty::GenericParamDef>) diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs index 8574443190d..b5addbd18d2 100644 --- a/src/librustc_typeck/check/wfcheck.rs +++ b/src/librustc_typeck/check/wfcheck.rs @@ -910,8 +910,8 @@ fn check_false_global_bounds<'a, 'gcx, 'tcx>( let def_id = fcx.tcx.hir.local_def_id(id); let predicates = fcx.tcx.predicates_of(def_id).predicates - .into_iter() - .map(|(p, _)| p) + .iter() + .map(|(p, _)| *p) .collect(); // Check elaborated bounds let implied_obligations = traits::elaborate_predicates(fcx.tcx, predicates); diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index d2dc226aca2..6ef09d96fd1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -39,6 +39,7 @@ use rustc::ty::{ReprOptions, ToPredicate}; use rustc::util::captures::Captures; use rustc::util::nodemap::FxHashMap; +use rustc_data_structures::sync::Lrc; use rustc_target::spec::abi; use syntax::ast; @@ -178,7 +179,8 @@ fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx } - fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) -> ty::GenericPredicates<'tcx> { + fn get_type_parameter_bounds(&self, span: Span, def_id: DefId) + -> Lrc> { self.tcx .at(span) .type_param_predicates((self.item_def_id, def_id)) @@ -243,7 +245,7 @@ fn record_ty(&self, _hir_id: hir::HirId, _ty: Ty<'tcx>, _span: Span) { fn type_param_predicates<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, (item_def_id, def_id): (DefId, DefId), -) -> ty::GenericPredicates<'tcx> { +) -> Lrc> { use rustc::hir::*; // In the AST, bounds can derive from two places. Either @@ -264,11 +266,11 @@ fn type_param_predicates<'a, 'tcx>( tcx.generics_of(item_def_id).parent }; - let mut result = parent.map_or( - ty::GenericPredicates { + let mut result = parent.map_or_else( + || Lrc::new(ty::GenericPredicates { parent: None, predicates: vec![], - }, + }), |parent| { let icx = ItemCtxt::new(tcx, parent); icx.get_type_parameter_bounds(DUMMY_SP, def_id) @@ -298,7 +300,7 @@ fn type_param_predicates<'a, 'tcx>( // Implied `Self: Trait` and supertrait bounds. if param_id == item_node_id { let identity_trait_ref = ty::TraitRef::identity(tcx, item_def_id); - result + Lrc::make_mut(&mut result) .predicates .push((identity_trait_ref.to_predicate(), item.span)); } @@ -317,7 +319,7 @@ fn type_param_predicates<'a, 'tcx>( }; let icx = ItemCtxt::new(tcx, item_def_id); - result + Lrc::make_mut(&mut result) .predicates .extend(icx.type_parameter_bounds_in_generics(ast_generics, param_id, ty, OnlySelfBounds(true))); @@ -685,7 +687,7 @@ fn adt_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::Ad fn super_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_def_id: DefId, -) -> ty::GenericPredicates<'tcx> { +) -> Lrc> { debug!("super_predicates(trait_def_id={:?})", trait_def_id); let trait_node_id = tcx.hir.as_local_node_id(trait_def_id).unwrap(); @@ -729,10 +731,10 @@ fn super_predicates_of<'a, 'tcx>( } } - ty::GenericPredicates { + Lrc::new(ty::GenericPredicates { parent: None, predicates: superbounds, - } + }) } fn trait_def<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> &'tcx ty::TraitDef { @@ -1605,27 +1607,23 @@ fn early_bound_lifetimes_from_generics<'a, 'tcx>( fn predicates_defined_on<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> ty::GenericPredicates<'tcx> { - let explicit = tcx.explicit_predicates_of(def_id); - let span = tcx.def_span(def_id); - let predicates = explicit.predicates.into_iter().chain( - tcx.inferred_outlives_of(def_id).iter().map(|&p| (p, span)) - ).collect(); - - ty::GenericPredicates { - parent: explicit.parent, - predicates: predicates, +) -> Lrc> { + let mut result = tcx.explicit_predicates_of(def_id); + let inferred_outlives = tcx.inferred_outlives_of(def_id); + if !inferred_outlives.is_empty() { + let span = tcx.def_span(def_id); + Lrc::make_mut(&mut result) + .predicates + .extend(inferred_outlives.iter().map(|&p| (p, span))); } + result } fn predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> ty::GenericPredicates<'tcx> { - let ty::GenericPredicates { - parent, - mut predicates, - } = tcx.predicates_defined_on(def_id); +) -> Lrc> { + let mut result = tcx.predicates_defined_on(def_id); if tcx.is_trait(def_id) { // For traits, add `Self: Trait` predicate. This is @@ -1641,16 +1639,17 @@ fn predicates_of<'a, 'tcx>( // used, and adding the predicate into this list ensures // that this is done. let span = tcx.def_span(def_id); - predicates.push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); + Lrc::make_mut(&mut result) + .predicates + .push((ty::TraitRef::identity(tcx, def_id).to_predicate(), span)); } - - ty::GenericPredicates { parent, predicates } + result } fn explicit_predicates_of<'a, 'tcx>( tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId, -) -> ty::GenericPredicates<'tcx> { +) -> Lrc> { use rustc::hir::*; use rustc_data_structures::fx::FxHashSet; @@ -1761,10 +1760,10 @@ fn extend, Span)>>(&mut self, iter: if impl_trait_fn.is_some() { // impl Trait - return ty::GenericPredicates { + return Lrc::new(ty::GenericPredicates { parent: None, predicates: bounds.predicates(tcx, opaque_ty), - }; + }); } else { // named existential types predicates.extend(bounds.predicates(tcx, opaque_ty)); @@ -1794,7 +1793,7 @@ fn extend, Span)>>(&mut self, iter: // on a trait we need to add in the supertrait bounds and bounds found on // associated types. if let Some((_trait_ref, _)) = is_trait { - predicates.extend(tcx.super_predicates_of(def_id).predicates); + predicates.extend(tcx.super_predicates_of(def_id).predicates.iter().cloned()); } // In default impls, we can assume that the self type implements @@ -1971,10 +1970,10 @@ fn extend, Span)>>(&mut self, iter: ); } - ty::GenericPredicates { + Lrc::new(ty::GenericPredicates { parent: generics.parent, predicates, - } + }) } pub enum SizedByDefault { diff --git a/src/librustc_typeck/outlives/explicit.rs b/src/librustc_typeck/outlives/explicit.rs index 75f8b78b9ec..9b374cf932f 100644 --- a/src/librustc_typeck/outlives/explicit.rs +++ b/src/librustc_typeck/outlives/explicit.rs @@ -33,14 +33,14 @@ pub fn explicit_predicates_of( ) -> &RequiredPredicates<'tcx> { self.map.entry(def_id).or_insert_with(|| { let predicates = if def_id.is_local() { - tcx.explicit_predicates_of(def_id).predicates + tcx.explicit_predicates_of(def_id) } else { - tcx.predicates_of(def_id).predicates + tcx.predicates_of(def_id) }; let mut required_predicates = RequiredPredicates::default(); // process predicates and convert to `RequiredPredicates` entry, see below - for (pred, _) in predicates.into_iter() { + for (pred, _) in predicates.predicates.iter() { match pred { ty::Predicate::TypeOutlives(predicate) => { let OutlivesPredicate(ref ty, ref reg) = predicate.skip_binder(); diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 77782c19b72..924c86ba56f 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1563,7 +1563,7 @@ fn is_impl_trait(param: &hir::GenericParam) -> bool { } impl<'a, 'tcx> Clean for (&'a ty::Generics, - &'a ty::GenericPredicates<'tcx>) { + &'a Lrc>) { fn clean(&self, cx: &DocContext) -> Generics { use self::WherePredicate as WP; diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index eda522af922..635608d140d 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -156,8 +156,8 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: DefId, if child == trait_ { return true } - let predicates = cx.tcx.super_predicates_of(child).predicates; - predicates.iter().filter_map(|(pred, _)| { + let predicates = cx.tcx.super_predicates_of(child); + predicates.predicates.iter().filter_map(|(pred, _)| { if let ty::Predicate::Trait(ref pred) = *pred { if pred.skip_binder().trait_ref.self_ty().is_self() { Some(pred.def_id()) -- GitLab