diff options
| author | bors <bors@rust-lang.org> | 2022-01-31 17:36:11 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2022-01-31 17:36:11 +0000 |
| commit | 498eeb72f590e518e19746b346be53713689e207 (patch) | |
| tree | 2c2e49bd9abfcfa662cfb75ea9cd2428885657d3 /compiler/rustc_trait_selection/src | |
| parent | 24b8bb13bff98bb747cd403b86596af43aceee78 (diff) | |
| parent | 0decf14ef1e63e7e7b70805cdf3d03b42d2f457c (diff) | |
Auto merge of #93348 - spastorino:fix-perf-overlap-mode2, r=nikomatsakis
Move overlap_mode into trait level attribute r? `@nikomatsakis` Should fix some performance regressions noted on https://github.com/rust-lang/rust/pull/93175
Diffstat (limited to 'compiler/rustc_trait_selection/src')
3 files changed, 30 insertions, 60 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index ab1dc8fcbfe..21775a5c49f 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -13,8 +13,8 @@ use crate::traits::{ self, FulfillmentContext, Normalized, Obligation, ObligationCause, PredicateObligation, PredicateObligations, SelectionContext, }; -use rustc_ast::Attribute; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::traits::specialization_graph::OverlapMode; use rustc_middle::ty::fast_reject::{self, SimplifyParams, StripReferences}; use rustc_middle::ty::fold::TypeFoldable; use rustc_middle::ty::subst::Subst; @@ -62,6 +62,7 @@ pub fn overlapping_impls<F1, F2, R>( impl1_def_id: DefId, impl2_def_id: DefId, skip_leak_check: SkipLeakCheck, + overlap_mode: OverlapMode, on_overlap: F1, no_overlap: F2, ) -> R @@ -99,7 +100,7 @@ where let overlaps = tcx.infer_ctxt().enter(|infcx| { let selcx = &mut SelectionContext::intercrate(&infcx); - overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).is_some() + overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).is_some() }); if !overlaps { @@ -112,7 +113,9 @@ where tcx.infer_ctxt().enter(|infcx| { let selcx = &mut SelectionContext::intercrate(&infcx); selcx.enable_tracking_intercrate_ambiguity_causes(); - on_overlap(overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id).unwrap()) + on_overlap( + overlap(selcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode).unwrap(), + ) }) } @@ -138,56 +141,6 @@ fn with_fresh_ty_vars<'cx, 'tcx>( header } -/// What kind of overlap check are we doing -- this exists just for testing and feature-gating -/// purposes. -#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] -enum OverlapMode { - /// The 1.0 rules (either types fail to unify, or where clauses are not implemented for crate-local types) - Stable, - /// Feature-gated test: Stable, *or* there is an explicit negative impl that rules out one of the where-clauses. - WithNegative, - /// Just check for negative impls, not for "where clause not implemented": used for testing. - Strict, -} - -impl OverlapMode { - fn use_negative_impl(&self) -> bool { - *self == OverlapMode::Strict || *self == OverlapMode::WithNegative - } - - fn use_implicit_negative(&self) -> bool { - *self == OverlapMode::Stable || *self == OverlapMode::WithNegative - } -} - -fn overlap_mode<'tcx>(tcx: TyCtxt<'tcx>, impl1_def_id: DefId, impl2_def_id: DefId) -> OverlapMode { - // Find the possible coherence mode override opt-in attributes for each `DefId` - let find_coherence_attr = |attr: &Attribute| { - let name = attr.name_or_empty(); - match name { - sym::rustc_with_negative_coherence | sym::rustc_strict_coherence => Some(name), - _ => None, - } - }; - let impl1_coherence_mode = tcx.get_attrs(impl1_def_id).iter().find_map(find_coherence_attr); - let impl2_coherence_mode = tcx.get_attrs(impl2_def_id).iter().find_map(find_coherence_attr); - - // If there are any (that currently happens in tests), they need to match. Otherwise, the - // default 1.0 rules are used. - match (impl1_coherence_mode, impl2_coherence_mode) { - (None, None) => OverlapMode::Stable, - (Some(sym::rustc_with_negative_coherence), Some(sym::rustc_with_negative_coherence)) => { - OverlapMode::WithNegative - } - (Some(sym::rustc_strict_coherence), Some(sym::rustc_strict_coherence)) => { - OverlapMode::Strict - } - (Some(mode), _) | (_, Some(mode)) => { - bug!("Use the same coherence mode on both impls: {}", mode) - } - } -} - /// Can both impl `a` and impl `b` be satisfied by a common type (including /// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls. fn overlap<'cx, 'tcx>( @@ -195,11 +148,19 @@ fn overlap<'cx, 'tcx>( skip_leak_check: SkipLeakCheck, impl1_def_id: DefId, impl2_def_id: DefId, + overlap_mode: OverlapMode, ) -> Option<OverlapResult<'tcx>> { debug!("overlap(impl1_def_id={:?}, impl2_def_id={:?})", impl1_def_id, impl2_def_id); selcx.infcx().probe_maybe_skip_leak_check(skip_leak_check.is_yes(), |snapshot| { - overlap_within_probe(selcx, skip_leak_check, impl1_def_id, impl2_def_id, snapshot) + overlap_within_probe( + selcx, + skip_leak_check, + impl1_def_id, + impl2_def_id, + overlap_mode, + snapshot, + ) }) } @@ -208,12 +169,10 @@ fn overlap_within_probe<'cx, 'tcx>( skip_leak_check: SkipLeakCheck, impl1_def_id: DefId, impl2_def_id: DefId, + overlap_mode: OverlapMode, snapshot: &CombinedSnapshot<'_, 'tcx>, ) -> Option<OverlapResult<'tcx>> { let infcx = selcx.infcx(); - let tcx = infcx.tcx; - - let overlap_mode = overlap_mode(tcx, impl1_def_id, impl2_def_id); if overlap_mode.use_negative_impl() { if negative_impl(selcx, impl1_def_id, impl2_def_id) diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 2c5e7e40cc8..b098e8590da 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -257,6 +257,7 @@ pub(super) fn specialization_graph_provider( trait_id: DefId, ) -> specialization_graph::Graph { let mut sg = specialization_graph::Graph::new(); + let overlap_mode = specialization_graph::OverlapMode::get(tcx, trait_id); let mut trait_impls: Vec<_> = tcx.all_impls(trait_id).collect(); @@ -270,7 +271,7 @@ pub(super) fn specialization_graph_provider( for impl_def_id in trait_impls { if let Some(impl_def_id) = impl_def_id.as_local() { // This is where impl overlap checking happens: - let insert_result = sg.insert(tcx, impl_def_id.to_def_id()); + let insert_result = sg.insert(tcx, impl_def_id.to_def_id(), overlap_mode); // Report error if there was one. let (overlap, used_to_be_allowed) = match insert_result { Err(overlap) => (Some(overlap), None), diff --git a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs index 3ac273fd19b..5ee8b45e66b 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/specialization_graph.rs @@ -41,6 +41,7 @@ trait ChildrenExt<'tcx> { tcx: TyCtxt<'tcx>, impl_def_id: DefId, simplified_self: Option<SimplifiedType>, + overlap_mode: OverlapMode, ) -> Result<Inserted, OverlapError>; } @@ -92,6 +93,7 @@ impl ChildrenExt<'_> for Children { tcx: TyCtxt<'_>, impl_def_id: DefId, simplified_self: Option<SimplifiedType>, + overlap_mode: OverlapMode, ) -> Result<Inserted, OverlapError> { let mut last_lint = None; let mut replace_children = Vec::new(); @@ -142,6 +144,7 @@ impl ChildrenExt<'_> for Children { possible_sibling, impl_def_id, traits::SkipLeakCheck::default(), + overlap_mode, |_| true, || false, ); @@ -166,6 +169,7 @@ impl ChildrenExt<'_> for Children { possible_sibling, impl_def_id, traits::SkipLeakCheck::Yes, + overlap_mode, |overlap| { if let Some(overlap_kind) = tcx.impls_are_allowed_to_overlap(impl_def_id, possible_sibling) @@ -273,6 +277,7 @@ pub trait GraphExt { &mut self, tcx: TyCtxt<'_>, impl_def_id: DefId, + overlap_mode: OverlapMode, ) -> Result<Option<FutureCompatOverlapError>, OverlapError>; /// Insert cached metadata mapping from a child impl back to its parent. @@ -287,6 +292,7 @@ impl GraphExt for Graph { &mut self, tcx: TyCtxt<'_>, impl_def_id: DefId, + overlap_mode: OverlapMode, ) -> Result<Option<FutureCompatOverlapError>, OverlapError> { assert!(impl_def_id.is_local()); @@ -327,8 +333,12 @@ impl GraphExt for Graph { loop { use self::Inserted::*; - let insert_result = - self.children.entry(parent).or_default().insert(tcx, impl_def_id, simplified)?; + let insert_result = self.children.entry(parent).or_default().insert( + tcx, + impl_def_id, + simplified, + overlap_mode, + )?; match insert_result { BecameNewSibling(opt_lint) => { |
