From aae1215f7faa3aac5ada7e82585b86f1282cd89e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Thu, 2 Jul 2020 20:52:40 -0400 Subject: [PATCH 1/2] Shrink ParamEnv to 16 bytes --- src/librustc_infer/infer/outlives/mod.rs | 2 +- src/librustc_infer/infer/outlives/verify.rs | 2 +- src/librustc_infer/traits/mod.rs | 2 +- src/librustc_middle/ty/layout.rs | 2 +- src/librustc_middle/ty/mod.rs | 121 ++++++++++++++++-- src/librustc_middle/ty/structural_impls.rs | 7 +- src/librustc_mir/const_eval/eval_queries.rs | 10 +- src/librustc_mir/util/elaborate_drops.rs | 2 +- .../traits/auto_trait.rs | 8 +- .../traits/chalk_fulfill.rs | 2 +- .../traits/fulfill.rs | 2 +- src/librustc_trait_selection/traits/mod.rs | 8 +- .../traits/object_safety.rs | 12 +- .../traits/project.rs | 6 +- .../traits/query/normalize.rs | 2 +- .../traits/select/candidate_assembly.rs | 2 +- .../traits/select/mod.rs | 2 +- .../traits/specialize/mod.rs | 5 +- src/librustc_ty/instance.rs | 2 +- src/librustc_typeck/check/compare_method.rs | 4 +- src/librustc_typeck/check/method/probe.rs | 37 +++--- src/librustc_typeck/check/mod.rs | 24 ++-- src/librustdoc/clean/auto_trait.rs | 4 +- .../src/needless_pass_by_value.rs | 2 +- 24 files changed, 187 insertions(+), 83 deletions(-) diff --git a/src/librustc_infer/infer/outlives/mod.rs b/src/librustc_infer/infer/outlives/mod.rs index fd3b38e9d67b0..541a2f18045c4 100644 --- a/src/librustc_infer/infer/outlives/mod.rs +++ b/src/librustc_infer/infer/outlives/mod.rs @@ -11,7 +11,7 @@ pub fn explicit_outlives_bounds<'tcx>( param_env: ty::ParamEnv<'tcx>, ) -> impl Iterator> + 'tcx { debug!("explicit_outlives_bounds()"); - param_env.caller_bounds.into_iter().filter_map(move |predicate| match predicate.kind() { + param_env.caller_bounds().into_iter().filter_map(move |predicate| match predicate.kind() { ty::PredicateKind::Projection(..) | ty::PredicateKind::Trait(..) | ty::PredicateKind::Subtype(..) diff --git a/src/librustc_infer/infer/outlives/verify.rs b/src/librustc_infer/infer/outlives/verify.rs index 383979f864075..8f20b5743df4f 100644 --- a/src/librustc_infer/infer/outlives/verify.rs +++ b/src/librustc_infer/infer/outlives/verify.rs @@ -221,7 +221,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> { // dubious for projections, but it will work for simple cases // like `T` and `T::Item`. It may not work as well for things // like `>::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()); // Next, collect regions we scraped from the well-formedness diff --git a/src/librustc_infer/traits/mod.rs b/src/librustc_infer/traits/mod.rs index 8cd1eb9957bed..7e7c8588ffb40 100644 --- a/src/librustc_infer/traits/mod.rs +++ b/src/librustc_infer/traits/mod.rs @@ -57,7 +57,7 @@ pub type TraitObligation<'tcx> = Obligation<'tcx, ty::PolyTraitPredicate<'tcx>>; // `PredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(PredicateObligation<'_>, 48); +static_assert_size!(PredicateObligation<'_>, 40); pub type Obligations<'tcx, O> = Vec>; pub type PredicateObligations<'tcx> = Vec>; diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs index 39b8566e7a873..010370c6e413a 100644 --- a/src/librustc_middle/ty/layout.rs +++ b/src/librustc_middle/ty/layout.rs @@ -1588,7 +1588,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> { // Ignore layouts that are done with non-empty environments or // non-monomorphic layouts, as the user only wants to see the stuff // resulting from the final codegen session. - if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds.is_empty() { + if layout.ty.has_param_types_or_consts() || !self.param_env.caller_bounds().is_empty() { return; } diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index 03aab2c0f9f2c..fde99f5c2709f 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1,3 +1,5 @@ +// ignore-tidy-filelength + pub use self::fold::{TypeFoldable, TypeVisitor}; pub use self::AssocItemContainer::*; pub use self::BorrowKind::*; @@ -45,6 +47,7 @@ use std::cell::RefCell; use std::cmp::Ordering; use std::fmt; use std::hash::{Hash, Hasher}; +use std::marker::PhantomData; use std::ops::Range; use std::ptr; @@ -1571,17 +1574,34 @@ pub type PlaceholderConst = Placeholder; /// When type checking, we use the `ParamEnv` to track /// details about the set of where-clauses that are in scope at this /// particular point. -#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable, TypeFoldable)] +#[derive(Copy, Clone)] pub struct ParamEnv<'tcx> { + // We pack the caller_bounds List pointer and a Reveal enum into this usize. + // Specifically, the low bit represents Reveal, with 0 meaning `UserFacing` + // and 1 meaning `All`. The rest is the pointer. + // + // This relies on the List> type having at least 2-byte + // alignment. Lists start with a usize and are repr(C) so this should be + // fine; there is a debug_assert in the constructor as well. + // + // Note that the choice of 0 for UserFacing is intentional -- since it is the + // first variant in Reveal this means that joining the pointer is a simple `or`. + packed_data: usize, + /// `Obligation`s that the caller must satisfy. This is basically /// the set of bounds on the in-scope type parameters, translated /// into `Obligation`s, and elaborated and normalized. - pub caller_bounds: &'tcx List>, + /// + /// Note: This is packed into the `packed_data` usize above, use the + /// `caller_bounds()` method to access it. + caller_bounds: PhantomData<&'tcx List>>, /// Typically, this is `Reveal::UserFacing`, but during codegen we - /// want `Reveal::All` -- note that this is always paired with an - /// empty environment. To get that, use `ParamEnv::reveal()`. - pub reveal: traits::Reveal, + /// want `Reveal::All`. + /// + /// Note: This is packed into the caller_bounds usize above, use the reveal() + /// method to access it. + reveal: PhantomData, /// If this `ParamEnv` comes from a call to `tcx.param_env(def_id)`, /// register that `def_id` (useful for transitioning to the chalk trait @@ -1589,6 +1609,57 @@ pub struct ParamEnv<'tcx> { pub def_id: Option, } +impl<'tcx> fmt::Debug for ParamEnv<'tcx> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("ParamEnv") + .field("caller_bounds", &self.caller_bounds()) + .field("reveal", &self.reveal()) + .field("def_id", &self.def_id) + .finish() + } +} + +impl<'tcx> Hash for ParamEnv<'tcx> { + fn hash(&self, state: &mut H) { + self.caller_bounds().hash(state); + self.reveal().hash(state); + self.def_id.hash(state); + } +} + +impl<'tcx> PartialEq for ParamEnv<'tcx> { + fn eq(&self, other: &Self) -> bool { + self.caller_bounds() == other.caller_bounds() + && self.reveal() == other.reveal() + && self.def_id == other.def_id + } +} +impl<'tcx> Eq for ParamEnv<'tcx> {} + +impl<'a, 'tcx> HashStable> for ParamEnv<'tcx> { + fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) { + self.caller_bounds().hash_stable(hcx, hasher); + self.reveal().hash_stable(hcx, hasher); + self.def_id.hash_stable(hcx, hasher); + } +} + +impl<'tcx> TypeFoldable<'tcx> for ParamEnv<'tcx> { + fn super_fold_with>(&self, folder: &mut F) -> Self { + ParamEnv::new( + self.caller_bounds().fold_with(folder), + self.reveal().fold_with(folder), + self.def_id.fold_with(folder), + ) + } + + fn super_visit_with>(&self, visitor: &mut V) -> bool { + self.caller_bounds().visit_with(visitor) + || self.reveal().visit_with(visitor) + || self.def_id.visit_with(visitor) + } +} + impl<'tcx> ParamEnv<'tcx> { /// Construct a trait environment suitable for contexts where /// there are no where-clauses in scope. Hidden types (like `impl @@ -1599,6 +1670,17 @@ impl<'tcx> ParamEnv<'tcx> { Self::new(List::empty(), Reveal::UserFacing, None) } + #[inline] + pub fn caller_bounds(self) -> &'tcx List> { + // mask out bottom bit + unsafe { &*((self.packed_data & (!1)) as *const _) } + } + + #[inline] + pub fn reveal(self) -> traits::Reveal { + if self.packed_data & 1 == 0 { traits::Reveal::UserFacing } else { traits::Reveal::All } + } + /// Construct a trait environment with no where-clauses in scope /// where the values of all `impl Trait` and other hidden types /// are revealed. This is suitable for monomorphized, post-typeck @@ -1618,7 +1700,25 @@ impl<'tcx> ParamEnv<'tcx> { reveal: Reveal, def_id: Option, ) -> Self { - ty::ParamEnv { caller_bounds, reveal, def_id } + let packed_data = caller_bounds as *const _ as usize; + // Check that we can pack the reveal data into the pointer. + debug_assert!(packed_data & 1 == 0); + ty::ParamEnv { + packed_data: packed_data + | match reveal { + Reveal::UserFacing => 0, + Reveal::All => 1, + }, + caller_bounds: PhantomData, + reveal: PhantomData, + def_id, + } + } + + pub fn with_user_facing(mut self) -> Self { + // clear bottom bit + self.packed_data &= !1; + self } /// Returns a new parameter environment with the same clauses, but @@ -1627,13 +1727,14 @@ impl<'tcx> ParamEnv<'tcx> { /// the desired behavior during codegen and certain other special /// contexts; normally though we want to use `Reveal::UserFacing`, /// which is the default. - pub fn with_reveal_all(self) -> Self { - ty::ParamEnv { reveal: Reveal::All, ..self } + pub fn with_reveal_all(mut self) -> Self { + self.packed_data |= 1; + self } /// Returns this same environment but with no caller bounds. pub fn without_caller_bounds(self) -> Self { - ty::ParamEnv { caller_bounds: List::empty(), ..self } + Self::new(List::empty(), self.reveal(), self.def_id) } /// Creates a suitable environment in which to perform trait @@ -1649,7 +1750,7 @@ impl<'tcx> ParamEnv<'tcx> { /// satisfiable. We generally want to behave as if they were true, /// although the surrounding function is never reachable. pub fn and>(self, value: T) -> ParamEnvAnd<'tcx, T> { - match self.reveal { + match self.reveal() { Reveal::UserFacing => ParamEnvAnd { param_env: self, value }, Reveal::All => { diff --git a/src/librustc_middle/ty/structural_impls.rs b/src/librustc_middle/ty/structural_impls.rs index 1d3607fe32ffc..159af277d240b 100644 --- a/src/librustc_middle/ty/structural_impls.rs +++ b/src/librustc_middle/ty/structural_impls.rs @@ -521,11 +521,8 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder { impl<'a, 'tcx> Lift<'tcx> for ty::ParamEnv<'a> { type Lifted = ty::ParamEnv<'tcx>; fn lift_to_tcx(&self, tcx: TyCtxt<'tcx>) -> Option { - tcx.lift(&self.caller_bounds).map(|caller_bounds| ty::ParamEnv { - reveal: self.reveal, - caller_bounds, - def_id: self.def_id, - }) + tcx.lift(&self.caller_bounds()) + .map(|caller_bounds| ty::ParamEnv::new(caller_bounds, self.reveal(), self.def_id)) } } diff --git a/src/librustc_mir/const_eval/eval_queries.rs b/src/librustc_mir/const_eval/eval_queries.rs index d62300b3f5541..d81817377a258 100644 --- a/src/librustc_mir/const_eval/eval_queries.rs +++ b/src/librustc_mir/const_eval/eval_queries.rs @@ -226,9 +226,9 @@ pub fn const_eval_validated_provider<'tcx>( key: ty::ParamEnvAnd<'tcx, GlobalId<'tcx>>, ) -> ::rustc_middle::mir::interpret::ConstEvalResult<'tcx> { // see comment in const_eval_raw_provider for what we're doing here - if key.param_env.reveal == Reveal::All { + if key.param_env.reveal() == Reveal::All { let mut key = key; - key.param_env.reveal = Reveal::UserFacing; + key.param_env = key.param_env.with_user_facing(); match tcx.const_eval_validated(key) { // try again with reveal all as requested Err(ErrorHandled::TooGeneric) => {} @@ -267,9 +267,9 @@ pub fn const_eval_raw_provider<'tcx>( // information being available. // In case we fail in the `UserFacing` variant, we just do the real computation. - if key.param_env.reveal == Reveal::All { + if key.param_env.reveal() == Reveal::All { let mut key = key; - key.param_env.reveal = Reveal::UserFacing; + key.param_env = key.param_env.with_user_facing(); match tcx.const_eval_raw(key) { // try again with reveal all as requested Err(ErrorHandled::TooGeneric) => {} @@ -326,7 +326,7 @@ pub fn const_eval_raw_provider<'tcx>( // this is `Reveal::UserFacing`, then it's expected that we could get a // `TooGeneric` error. When we fall back to `Reveal::All`, then it will either // succeed or we'll report this error then. - if key.param_env.reveal == Reveal::All { + if key.param_env.reveal() == Reveal::All { tcx.sess.delay_span_bug( err.span, &format!("static eval failure did not emit an error: {:#?}", v), diff --git a/src/librustc_mir/util/elaborate_drops.rs b/src/librustc_mir/util/elaborate_drops.rs index 5f55a812a4e0d..20c2f5688eb59 100644 --- a/src/librustc_mir/util/elaborate_drops.rs +++ b/src/librustc_mir/util/elaborate_drops.rs @@ -279,7 +279,7 @@ where let subpath = self.elaborator.field_subpath(variant_path, field); let tcx = self.tcx(); - assert_eq!(self.elaborator.param_env().reveal, Reveal::All); + assert_eq!(self.elaborator.param_env().reveal(), Reveal::All); let field_ty = tcx.normalize_erasing_regions(self.elaborator.param_env(), f.ty(tcx, substs)); (tcx.mk_place_field(base_place, field, field_ty), subpath) diff --git a/src/librustc_trait_selection/traits/auto_trait.rs b/src/librustc_trait_selection/traits/auto_trait.rs index da945a1918524..8c8550d377a6e 100644 --- a/src/librustc_trait_selection/traits/auto_trait.rs +++ b/src/librustc_trait_selection/traits/auto_trait.rs @@ -281,8 +281,8 @@ impl AutoTraitFinder<'tcx> { }, })); - let computed_preds = param_env.caller_bounds.iter(); - let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds.iter().collect(); + let computed_preds = param_env.caller_bounds().iter(); + let mut user_computed_preds: FxHashSet<_> = user_env.caller_bounds().iter().collect(); let mut new_env = param_env; let dummy_cause = ObligationCause::dummy(); @@ -368,12 +368,12 @@ impl AutoTraitFinder<'tcx> { ) .map(|o| o.predicate); 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); } let final_user_env = ty::ParamEnv::new( tcx.mk_predicates(user_computed_preds.into_iter()), - user_env.reveal, + user_env.reveal(), None, ); debug!( diff --git a/src/librustc_trait_selection/traits/chalk_fulfill.rs b/src/librustc_trait_selection/traits/chalk_fulfill.rs index 2ade489275262..a75240042ad76 100644 --- a/src/librustc_trait_selection/traits/chalk_fulfill.rs +++ b/src/librustc_trait_selection/traits/chalk_fulfill.rs @@ -137,7 +137,7 @@ fn in_environment( let environment = match obligation.param_env.def_id { Some(def_id) => environment(infcx.tcx, def_id), - None if obligation.param_env.caller_bounds.is_empty() => ty::List::empty(), + None if obligation.param_env.caller_bounds().is_empty() => ty::List::empty(), // FIXME(chalk): this is hit in ui/where-clauses/where-clause-constraints-are-local-for-trait-impl // and ui/generics/generic-static-methods //_ => bug!("non-empty `ParamEnv` with no def-id"), diff --git a/src/librustc_trait_selection/traits/fulfill.rs b/src/librustc_trait_selection/traits/fulfill.rs index 32ab63458e752..800aef7284f9e 100644 --- a/src/librustc_trait_selection/traits/fulfill.rs +++ b/src/librustc_trait_selection/traits/fulfill.rs @@ -84,7 +84,7 @@ pub struct PendingPredicateObligation<'tcx> { // `PendingPredicateObligation` is used a lot. Make sure it doesn't unintentionally get bigger. #[cfg(target_arch = "x86_64")] -static_assert_size!(PendingPredicateObligation<'_>, 72); +static_assert_size!(PendingPredicateObligation<'_>, 64); impl<'a, 'tcx> FulfillmentContext<'tcx> { /// Creates a new fulfillment context. diff --git a/src/librustc_trait_selection/traits/mod.rs b/src/librustc_trait_selection/traits/mod.rs index 9ab87e6b6ca01..78c50a1176a3d 100644 --- a/src/librustc_trait_selection/traits/mod.rs +++ b/src/librustc_trait_selection/traits/mod.rs @@ -297,7 +297,7 @@ pub fn normalize_param_env_or_error<'tcx>( ); let mut predicates: Vec<_> = - util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.into_iter()) + util::elaborate_predicates(tcx, unnormalized_env.caller_bounds().into_iter()) .map(|obligation| obligation.predicate) .collect(); @@ -305,7 +305,7 @@ pub fn normalize_param_env_or_error<'tcx>( let elaborated_env = ty::ParamEnv::new( tcx.intern_predicates(&predicates), - unnormalized_env.reveal, + unnormalized_env.reveal(), unnormalized_env.def_id, ); @@ -361,7 +361,7 @@ pub fn normalize_param_env_or_error<'tcx>( let outlives_env: Vec<_> = non_outlives_predicates.iter().chain(&outlives_predicates).cloned().collect(); let outlives_env = - ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal, None); + ty::ParamEnv::new(tcx.intern_predicates(&outlives_env), unnormalized_env.reveal(), None); let outlives_predicates = match do_normalize_predicates( tcx, region_context, @@ -383,7 +383,7 @@ pub fn normalize_param_env_or_error<'tcx>( debug!("normalize_param_env_or_error: final predicates={:?}", predicates); ty::ParamEnv::new( tcx.intern_predicates(&predicates), - unnormalized_env.reveal, + unnormalized_env.reveal(), unnormalized_env.def_id, ) } diff --git a/src/librustc_trait_selection/traits/object_safety.rs b/src/librustc_trait_selection/traits/object_safety.rs index 5befc797a517a..63714c2bae92b 100644 --- a/src/librustc_trait_selection/traits/object_safety.rs +++ b/src/librustc_trait_selection/traits/object_safety.rs @@ -631,7 +631,7 @@ fn receiver_is_dispatchable<'tcx>( // create a modified param env, with `Self: Unsize` and `U: Trait` added to caller bounds // `U: ?Sized` is already implied here let param_env = { - let mut param_env = tcx.param_env(method.def_id); + let param_env = tcx.param_env(method.def_id); // Self: Unsize let unsize_predicate = ty::TraitRef { @@ -656,15 +656,17 @@ fn receiver_is_dispatchable<'tcx>( }; let caller_bounds: Vec> = param_env - .caller_bounds + .caller_bounds() .iter() .chain(iter::once(unsize_predicate)) .chain(iter::once(trait_predicate)) .collect(); - param_env.caller_bounds = tcx.intern_predicates(&caller_bounds); - - param_env + ty::ParamEnv::new( + tcx.intern_predicates(&caller_bounds), + param_env.reveal(), + param_env.def_id, + ) }; // Receiver: DispatchFromDyn U]> diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs index f71b3fcf129da..bd86109e5a491 100644 --- a/src/librustc_trait_selection/traits/project.rs +++ b/src/librustc_trait_selection/traits/project.rs @@ -326,7 +326,7 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. - match self.param_env.reveal { + match self.param_env.reveal() { Reveal::UserFacing => ty, Reveal::All => { @@ -869,7 +869,7 @@ fn assemble_candidates_from_param_env<'cx, 'tcx>( obligation_trait_ref, candidate_set, ProjectionTyCandidate::ParamEnv, - obligation.param_env.caller_bounds.iter(), + obligation.param_env.caller_bounds().iter(), ); } @@ -1028,7 +1028,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // and the obligation is monomorphic, otherwise passes such as // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. - if obligation.param_env.reveal == Reveal::All { + if obligation.param_env.reveal() == Reveal::All { // NOTE(eddyb) inference variables can resolve to parameters, so // assume `poly_trait_ref` isn't monomorphic, if it contains any. let poly_trait_ref = diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs index ca49ff5884f98..59fa4c1598d41 100644 --- a/src/librustc_trait_selection/traits/query/normalize.rs +++ b/src/librustc_trait_selection/traits/query/normalize.rs @@ -104,7 +104,7 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> { ty::Opaque(def_id, substs) if !substs.has_escaping_bound_vars() => { // (*) // Only normalize `impl Trait` after type-checking, usually in codegen. - match self.param_env.reveal { + match self.param_env.reveal() { Reveal::UserFacing => ty, Reveal::All => { diff --git a/src/librustc_trait_selection/traits/select/candidate_assembly.rs b/src/librustc_trait_selection/traits/select/candidate_assembly.rs index 597a7a58022cd..1d5441b8eff85 100644 --- a/src/librustc_trait_selection/traits/select/candidate_assembly.rs +++ b/src/librustc_trait_selection/traits/select/candidate_assembly.rs @@ -186,7 +186,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let all_bounds = stack .obligation .param_env - .caller_bounds + .caller_bounds() .iter() .filter_map(|o| o.to_opt_poly_trait_ref()); diff --git a/src/librustc_trait_selection/traits/select/mod.rs b/src/librustc_trait_selection/traits/select/mod.rs index c41a27c6f431f..ba5e60012da19 100644 --- a/src/librustc_trait_selection/traits/select/mod.rs +++ b/src/librustc_trait_selection/traits/select/mod.rs @@ -552,7 +552,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { if !self.intercrate && obligation.is_global() - && obligation.param_env.caller_bounds.iter().all(|bound| bound.needs_subst()) + && obligation.param_env.caller_bounds().iter().all(|bound| bound.needs_subst()) { // If a param env has no global bounds, global obligations do not // depend on its particular value in order to work, so we can clear diff --git a/src/librustc_trait_selection/traits/specialize/mod.rs b/src/librustc_trait_selection/traits/specialize/mod.rs index 42901102c1076..9b737d464174a 100644 --- a/src/librustc_trait_selection/traits/specialize/mod.rs +++ b/src/librustc_trait_selection/traits/specialize/mod.rs @@ -231,7 +231,10 @@ fn fulfill_implication<'a, 'tcx>( debug!( "fulfill_implication: for impls on {:?} and {:?}, \ could not fulfill: {:?} given {:?}", - source_trait_ref, target_trait_ref, errors, param_env.caller_bounds + source_trait_ref, + target_trait_ref, + errors, + param_env.caller_bounds() ); Err(()) } diff --git a/src/librustc_ty/instance.rs b/src/librustc_ty/instance.rs index 0acf769168137..de4cdbb3b7916 100644 --- a/src/librustc_ty/instance.rs +++ b/src/librustc_ty/instance.rs @@ -126,7 +126,7 @@ fn resolve_associated_item<'tcx>( // and the obligation is monomorphic, otherwise passes such as // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. - if param_env.reveal == Reveal::All { + if param_env.reveal() == Reveal::All { !trait_ref.still_further_specializable() } else { false diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index e6217e0cc1b6e..a90ed455d048b 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -218,7 +218,7 @@ fn compare_predicate_entailment<'tcx>( let inh = Inherited::new(infcx, impl_m.def_id.expect_local()); let infcx = &inh.infcx; - debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds); + debug!("compare_impl_method: caller_bounds={:?}", param_env.caller_bounds()); let mut selcx = traits::SelectionContext::new(&infcx); @@ -1141,7 +1141,7 @@ fn compare_type_predicate_entailment<'tcx>( let inh = Inherited::new(infcx, impl_ty.def_id.expect_local()); let infcx = &inh.infcx; - debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds); + debug!("compare_type_predicate_entailment: caller_bounds={:?}", param_env.caller_bounds()); let mut selcx = traits::SelectionContext::new(&infcx); diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 8842ca877268a..78bf973e9e3f8 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -798,26 +798,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // FIXME: do we want to commit to this behavior for param bounds? debug!("assemble_inherent_candidates_from_param(param_ty={:?})", param_ty); - let bounds = - self.param_env.caller_bounds.iter().filter_map(|predicate| match predicate.kind() { - ty::PredicateKind::Trait(ref trait_predicate, _) => { - match trait_predicate.skip_binder().trait_ref.self_ty().kind { - ty::Param(ref p) if *p == param_ty => { - Some(trait_predicate.to_poly_trait_ref()) - } - _ => None, - } + let bounds = self.param_env.caller_bounds().iter().filter_map(|predicate| match predicate + .kind() + { + ty::PredicateKind::Trait(ref trait_predicate, _) => { + match trait_predicate.skip_binder().trait_ref.self_ty().kind { + ty::Param(ref p) if *p == param_ty => Some(trait_predicate.to_poly_trait_ref()), + _ => None, } - ty::PredicateKind::Subtype(..) - | ty::PredicateKind::Projection(..) - | ty::PredicateKind::RegionOutlives(..) - | ty::PredicateKind::WellFormed(..) - | ty::PredicateKind::ObjectSafe(..) - | ty::PredicateKind::ClosureKind(..) - | ty::PredicateKind::TypeOutlives(..) - | ty::PredicateKind::ConstEvaluatable(..) - | ty::PredicateKind::ConstEquate(..) => None, - }); + } + ty::PredicateKind::Subtype(..) + | ty::PredicateKind::Projection(..) + | ty::PredicateKind::RegionOutlives(..) + | ty::PredicateKind::WellFormed(..) + | ty::PredicateKind::ObjectSafe(..) + | ty::PredicateKind::ClosureKind(..) + | ty::PredicateKind::TypeOutlives(..) + | ty::PredicateKind::ConstEvaluatable(..) + | ty::PredicateKind::ConstEquate(..) => None, + }); self.elaborate_bounds(bounds, |this, poly_trait_ref, item| { let trait_ref = this.erase_late_bound_regions(&poly_trait_ref); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 58fd0f989c678..4ddfd8cdd9874 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -2927,18 +2927,20 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> { let index = generics.param_def_id_to_index[&def_id]; ty::GenericPredicates { parent: None, - predicates: tcx.arena.alloc_from_iter(self.param_env.caller_bounds.iter().filter_map( - |predicate| match predicate.kind() { - ty::PredicateKind::Trait(ref data, _) - if data.skip_binder().self_ty().is_param(index) => - { - // HACK(eddyb) should get the original `Span`. - let span = tcx.def_span(def_id); - Some((predicate, span)) + predicates: tcx.arena.alloc_from_iter( + self.param_env.caller_bounds().iter().filter_map(|predicate| { + match predicate.kind() { + ty::PredicateKind::Trait(ref data, _) + if data.skip_binder().self_ty().is_param(index) => + { + // HACK(eddyb) should get the original `Span`. + let span = tcx.def_span(def_id); + Some((predicate, span)) + } + _ => None, } - _ => None, - }, - )), + }), + ), } } diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs index 423160f3a9e01..3a798158c8bc6 100644 --- a/src/librustdoc/clean/auto_trait.rs +++ b/src/librustdoc/clean/auto_trait.rs @@ -459,9 +459,9 @@ impl<'a, 'tcx> AutoTraitFinder<'a, 'tcx> { let mut replacer = RegionReplacer { vid_to_region: &vid_to_region, tcx }; let orig_bounds: FxHashSet<_> = - self.cx.tcx.param_env(param_env_def_id).caller_bounds.iter().collect(); + self.cx.tcx.param_env(param_env_def_id).caller_bounds().iter().collect(); let clean_where_predicates = param_env - .caller_bounds + .caller_bounds() .iter() .filter(|p| { !orig_bounds.contains(p) diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index 6954f0cc683f1..2c68ebc1f8a90 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -111,7 +111,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NeedlessPassByValue { let fn_def_id = cx.tcx.hir().local_def_id(hir_id); - let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds.iter()) + let preds = traits::elaborate_predicates(cx.tcx, cx.param_env.caller_bounds().iter()) .filter(|p| !p.is_global()) .filter_map(|obligation| { if let ty::PredicateKind::Trait(poly_trait_ref, _) = obligation.predicate.kind() { From 8512d2efdef2c41aa529f44941f4c1f0e5fdd7de Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 3 Jul 2020 07:40:37 -0400 Subject: [PATCH 2/2] Avoid deconstructing pointer for hashing --- src/librustc_middle/ty/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs index fde99f5c2709f..ffb41b094dcd5 100644 --- a/src/librustc_middle/ty/mod.rs +++ b/src/librustc_middle/ty/mod.rs @@ -1621,8 +1621,9 @@ impl<'tcx> fmt::Debug for ParamEnv<'tcx> { impl<'tcx> Hash for ParamEnv<'tcx> { fn hash(&self, state: &mut H) { - self.caller_bounds().hash(state); - self.reveal().hash(state); + // List hashes as the raw pointer, so we can skip splitting into the + // pointer and the enum. + self.packed_data.hash(state); self.def_id.hash(state); } }