diff options
Diffstat (limited to 'compiler')
5 files changed, 45 insertions, 17 deletions
diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index ea3602e8a05..0cf04b369de 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -917,6 +917,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// The idea then is to lower the `T: 'X` constraint into multiple /// bounds -- e.g., if `'X` is the union of two free lifetimes, /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. + #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] fn try_promote_type_test( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -934,11 +935,41 @@ impl<'tcx> RegionInferenceContext<'tcx> { return false; }; + debug!("subject = {:?}", subject); + + let r_scc = self.constraint_sccs.scc(*lower_bound); + + debug!( + "lower_bound = {:?} r_scc={:?} universe={:?}", + lower_bound, r_scc, self.scc_universes[r_scc] + ); + + // If the type test requires that `T: 'a` where `'a` is a + // placeholder from another universe, that effectively requires + // `T: 'static`, so we have to propagate that requirement. + // + // It doesn't matter *what* universe because the promoted `T` will + // always be in the root universe. + if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { + debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); + let static_r = self.universal_regions.fr_static; + propagated_outlives_requirements.push(ClosureOutlivesRequirement { + subject, + outlived_free_region: static_r, + blame_span: locations.span(body), + category: ConstraintCategory::Boring, + }); + + // we can return here -- the code below might push add'l constraints + // but they would all be weaker than this one. + return true; + } + // For each region outlived by lower_bound find a non-local, // universal region (it may be the same region) and add it to // `ClosureOutlivesRequirement`. - let r_scc = self.constraint_sccs.scc(*lower_bound); for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + debug!("universal_region_outlived_by ur={:?}", ur); // Check whether we can already prove that the "subject" outlives `ur`. // If so, we don't have to propagate this requirement to our caller. // @@ -963,8 +994,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { continue; } - debug!("try_promote_type_test: ur={:?}", ur); - let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); debug!("try_promote_type_test: non_local_ub={:?}", non_local_ub); @@ -1001,6 +1030,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// will use it's *external name*, which will be a `RegionKind` /// variant that can be used in query responses such as /// `ReEarlyBound`. + #[instrument(level = "debug", skip(self, infcx))] fn try_promote_type_test_subject( &self, infcx: &InferCtxt<'_, 'tcx>, @@ -1008,8 +1038,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> Option<ClosureOutlivesSubject<'tcx>> { let tcx = infcx.tcx; - debug!("try_promote_type_test_subject(ty = {:?})", ty); - let ty = tcx.fold_regions(ty, |r, _depth| { let region_vid = self.to_region_vid(r); diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index f933f1c3c94..52ca23c4b30 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -13,7 +13,7 @@ use crate::traits::{ self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; -//use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::Diagnostic; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; @@ -44,7 +44,7 @@ pub enum Conflict { pub struct OverlapResult<'tcx> { pub impl_header: ty::ImplHeader<'tcx>, - pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>, + pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>, /// `true` if the overlap might've been permitted before the shift /// to universes. diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 21e14eae0ee..96d83deeeb7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -110,7 +110,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { IntercrateAmbiguityCause::DownstreamCrate { trait_desc, self_desc } }; debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index b205ca8fa11..2bb53a466ca 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -24,7 +24,7 @@ use crate::traits::error_reporting::InferCtxtExt; use crate::traits::project::ProjectAndUnifyResult; use crate::traits::project::ProjectionCacheKeyExt; use crate::traits::ProjectionCacheKey; -use rustc_data_structures::fx::{FxHashMap, FxHashSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_errors::{Diagnostic, ErrorGuaranteed}; use rustc_hir as hir; @@ -52,7 +52,7 @@ pub use rustc_middle::traits::select::*; mod candidate_assembly; mod confirmation; -#[derive(Clone, Debug)] +#[derive(Clone, Debug, Eq, PartialEq, Hash)] pub enum IntercrateAmbiguityCause { DownstreamCrate { trait_desc: String, self_desc: Option<String> }, UpstreamCrateUpdate { trait_desc: String, self_desc: Option<String> }, @@ -128,7 +128,7 @@ pub struct SelectionContext<'cx, 'tcx> { /// We don't do his until we detect a coherence error because it can /// lead to false overflow results (#47139) and because always /// computing it may negatively impact performance. - intercrate_ambiguity_causes: Option<Vec<IntercrateAmbiguityCause>>, + intercrate_ambiguity_causes: Option<FxIndexSet<IntercrateAmbiguityCause>>, /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated @@ -254,14 +254,14 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { assert!(self.intercrate); assert!(self.intercrate_ambiguity_causes.is_none()); - self.intercrate_ambiguity_causes = Some(vec![]); + self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); } /// Gets the intercrate ambiguity causes collected since tracking /// was enabled and disables tracking at the same time. If /// tracking is not enabled, just returns an empty vector. - pub fn take_intercrate_ambiguity_causes(&mut self) -> Vec<IntercrateAmbiguityCause> { + pub fn take_intercrate_ambiguity_causes(&mut self) -> FxIndexSet<IntercrateAmbiguityCause> { assert!(self.intercrate); self.intercrate_ambiguity_causes.take().unwrap_or_default() } @@ -960,7 +960,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { }); debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().push(cause); + self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); } } } @@ -1252,7 +1252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { reservation impl ambiguity on {:?}", def_id ); - intercrate_ambiguity_clauses.push( + intercrate_ambiguity_clauses.insert( IntercrateAmbiguityCause::ReservationImpl { message: value.to_string(), }, diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 13848d37890..2c4a453aefc 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -15,7 +15,7 @@ use specialization_graph::GraphExt; use crate::infer::{InferCtxt, InferOk, TyCtxtInferExt}; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{self, coherence, FutureCompatOverlapErrorKind, ObligationCause, TraitEngine}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::{struct_span_err, EmissionGuarantee, LintDiagnosticBuilder}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::ty::subst::{InternalSubsts, Subst, SubstsRef}; @@ -33,7 +33,7 @@ pub struct OverlapError { pub with_impl: DefId, pub trait_desc: String, pub self_desc: Option<String>, - pub intercrate_ambiguity_causes: Vec<IntercrateAmbiguityCause>, + pub intercrate_ambiguity_causes: FxIndexSet<IntercrateAmbiguityCause>, pub involves_placeholder: bool, } |
