Skip to content

Commit e9bbadf

Browse files
committed
Auto merge of #164224 - JonathanBrouwer:rollup-HbN5FJA, r=JonathanBrouwer
Rollup of 4 perf-sensitive pull requests Successful merges: - #163425 (Treat union fields as aliasing each other in value_analysis) - #164074 (Avoid cloning impl trait AST nodes in late resolution) - #164089 (Implement `clone_from` for `BorrowckDomain`) - #164150 (Reserve more capacity for Symbol interner)
2 parents d64de46 + 4dbaa9d commit e9bbadf

11 files changed

Lines changed: 294 additions & 19 deletions

‎compiler/rustc_borrowck/src/dataflow.rs‎

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,13 +103,29 @@ impl JoinSemiLattice for BorrowckDomain {
103103
}
104104

105105
/// The transient state of the dataflow analyses used by the borrow checker.
106-
#[derive(Clone, Debug, PartialEq, Eq)]
106+
#[derive(Debug, PartialEq, Eq)]
107107
pub(crate) struct BorrowckDomain {
108108
pub(crate) borrows: BorrowsDomain,
109109
pub(crate) uninits: MaybeUninitializedPlacesDomain,
110110
pub(crate) ever_inits: EverInitializedPlacesDomain,
111111
}
112112

113+
impl Clone for BorrowckDomain {
114+
fn clone(&self) -> Self {
115+
Self {
116+
borrows: self.borrows.clone(),
117+
uninits: self.uninits.clone(),
118+
ever_inits: self.ever_inits.clone(),
119+
}
120+
}
121+
122+
fn clone_from(&mut self, source: &Self) {
123+
self.borrows.clone_from(&source.borrows);
124+
self.uninits.clone_from(&source.uninits);
125+
self.ever_inits.clone_from(&source.ever_inits);
126+
}
127+
}
128+
113129
rustc_index::newtype_index! {
114130
#[orderable]
115131
#[debug_format = "bw{}"]

‎compiler/rustc_mir_dataflow/src/value_analysis.rs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -786,6 +786,12 @@ impl<'tcx> Map<'tcx> {
786786
};
787787
let elems = place.projection.iter().map(|&elem| elem.try_into()).chain(tail_elem.map(Ok));
788788
for elem in elems {
789+
// All fields of a union alias each other.
790+
if self.places[index].ty.is_union() {
791+
self.for_each_value_inside(index, f);
792+
return;
793+
}
794+
789795
// A field aliases the parent place.
790796
if let Some(vi) = self.places[index].value_index {
791797
f(vi);

‎compiler/rustc_resolve/src/late.rs‎

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -824,7 +824,7 @@ pub(crate) struct DiagMetadata<'ast> {
824824
current_impl_item: Option<&'ast AssocItem>,
825825

826826
/// When processing impl trait
827-
currently_processing_impl_trait: Option<(TraitRef, Ty)>,
827+
currently_processing_impl_trait: Option<(&'ast TraitRef, &'ast Ty)>,
828828

829829
/// Accumulate the errors due to missed lifetime elision,
830830
/// and report them all at once for each function.
@@ -857,7 +857,7 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
857857
lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>,
858858

859859
/// The trait that the current context can refer to.
860-
current_trait_ref: Option<(Module<'ra>, TraitRef)>,
860+
current_trait_ref: Option<(Module<'ra>, &'ast TraitRef)>,
861861

862862
/// Fields used to add information to diagnostic errors.
863863
diag_metadata: Box<DiagMetadata<'ast>>,
@@ -2004,8 +2004,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
20042004
// are we trying to use an anonymous lifetime
20052005
// on a non GAT associated trait type?
20062006
if !self.in_func_body
2007-
&& let Some((module, _)) = &self.current_trait_ref
2008-
&& let Some(ty) = &self.diag_metadata.current_self_type
2007+
&& let Some((module, _)) = self.current_trait_ref
2008+
&& let Some(ty) = self.diag_metadata.current_self_type
20092009
&& Some(true) == self.diag_metadata.in_non_gat_assoc_type
20102010
&& let crate::ModuleKind::Def(DefKind::Trait, trait_id, _, _) =
20112011
module.kind
@@ -3509,16 +3509,15 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
35093509
/// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`).
35103510
fn with_optional_trait_ref<T>(
35113511
&mut self,
3512-
opt_trait_ref: Option<&TraitRef>,
3512+
opt_trait_ref: Option<&'ast TraitRef>,
35133513
self_type: &'ast Ty,
35143514
f: impl FnOnce(&mut Self, Option<DefId>) -> T,
35153515
) -> T {
35163516
let mut new_val = None;
35173517
let mut new_id = None;
35183518
if let Some(trait_ref) = opt_trait_ref {
35193519
let path: Vec<_> = Segment::from_path(&trait_ref.path);
3520-
self.diag_metadata.currently_processing_impl_trait =
3521-
Some((trait_ref.clone(), self_type.clone()));
3520+
self.diag_metadata.currently_processing_impl_trait = Some((trait_ref, self_type));
35223521
let res = self.smart_resolve_path_fragment(
35233522
&None,
35243523
&path,
@@ -3530,7 +3529,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
35303529
self.diag_metadata.currently_processing_impl_trait = None;
35313530
if let Some(def_id) = res.expect_full_res().opt_def_id() {
35323531
new_id = Some(def_id);
3533-
new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
3532+
new_val = Some((self.r.expect_module(def_id), trait_ref));
35343533
}
35353534
}
35363535
let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
@@ -3917,7 +3916,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
39173916
let Some(decl) = decl else {
39183917
// We could not find the method: report an error.
39193918
let candidate = self.find_similarly_named_assoc_item(reported_ident.name, kind);
3920-
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
3919+
let path = &self.current_trait_ref.unwrap().1.path;
39213920
let path_names = path_names_to_string(path);
39223921
self.report_error(span, err(reported_ident, path_names, candidate));
39233922
feed_visibility(self, module.def_id());
@@ -3931,7 +3930,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
39313930
match seen_trait_items.entry(id_in_trait) {
39323931
Entry::Occupied(entry) => {
39333932
let trait_span = decl.parent_module.unwrap().span.shrink_to_lo();
3934-
let impl_span = self.current_trait_ref.as_ref().unwrap().1.path.span;
3933+
let impl_span = self.current_trait_ref.unwrap().1.path.span;
39353934
self.report_error(
39363935
span,
39373936
ResolutionError::TraitImplDuplicate {
@@ -3961,7 +3960,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
39613960
}
39623961

39633962
// The method kind does not correspond to what appeared in the trait, report.
3964-
let path = &self.current_trait_ref.as_ref().unwrap().1.path;
3963+
let path = &self.current_trait_ref.unwrap().1.path;
39653964
let (code, kind) = match kind {
39663965
AssocItemKind::Const(..) => (E0323, "const"),
39673966
AssocItemKind::Fn(..) => (E0324, "method"),
@@ -3973,7 +3972,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
39733972
};
39743973
let trait_path = path_names_to_string(path);
39753974
let trait_span = decl.parent_module.unwrap().span.shrink_to_lo();
3976-
let impl_span = self.current_trait_ref.as_ref().unwrap().1.path.span;
3975+
let impl_span = self.current_trait_ref.unwrap().1.path.span;
39773976
self.report_error(
39783977
span,
39793978
ResolutionError::TraitImplMismatch {
@@ -5542,7 +5541,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
55425541

55435542
fn record_traits_in_scope(&mut self, node_id: NodeId, ident: Ident) {
55445543
let traits = self.r.traits_in_scope(
5545-
self.current_trait_ref.as_ref().map(|(module, _)| *module),
5544+
self.current_trait_ref.map(|(module, _)| module),
55465545
&self.parent_scope,
55475546
ident.span,
55485547
Some((ident.name, ValueNS)),

‎compiler/rustc_resolve/src/late/diagnostics.rs‎

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1884,8 +1884,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
18841884
res: Option<Res>,
18851885
span: Span,
18861886
) {
1887-
if let Some((trait_ref, self_ty)) =
1888-
self.diag_metadata.currently_processing_impl_trait.clone()
1887+
if let Some((trait_ref, self_ty)) = self.diag_metadata.currently_processing_impl_trait
18891888
&& let TyKind::Path(_, self_ty_path) = &self_ty.kind
18901889
&& let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
18911890
self.resolve_path(&Segment::from_path(self_ty_path), Some(TypeNS), None, source)
@@ -2921,15 +2920,15 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
29212920
ident: Symbol,
29222921
kind: &AssocItemKind,
29232922
) -> Option<Symbol> {
2924-
let (module, _) = self.current_trait_ref.as_ref()?;
2923+
let (module, _) = self.current_trait_ref?;
29252924
if ident == kw::Underscore {
29262925
// We do nothing for `_`.
29272926
return None;
29282927
}
29292928

29302929
let targets = self
29312930
.r
2932-
.resolutions(*module)
2931+
.resolutions(module)
29332932
.iter()
29342933
.filter_map(|(key, res)| {
29352934
res.borrow(self.r).best_decl().map(|binding| (key, binding.res()))

‎compiler/rustc_span/src/symbol.rs‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2896,7 +2896,15 @@ impl Interner {
28962896
// `ByteSymbol`.
28972897
fn prefill(init: &[&'static str], extra: &[&'static str]) -> Self {
28982898
let values = init.iter().copied().chain(extra.iter().copied()).map(|str| str.as_bytes());
2899-
let (size_hint, _) = values.size_hint();
2899+
// At the time of writing, `helloworld` Check benchmark interns ~1k additional symbols.
2900+
// Some of the noisy ones (`include-blob`, `tt-muncher`, `externs`, `large-workspace`, etc.)
2901+
// are between 1k and 2k. Lowest number among non-artificial benchmarks is ~5k for `ucd`.
2902+
// This was chosen to make small, artificial benchmarks more stable, and to
2903+
// reduce resizing for normal code without regresing memory use for smaller crates.
2904+
// FIXME(panstromek): we could do better if we take into account whether this is
2905+
// Debug/Opt build. Those builds intern at least 6k more symbols than Check ones.
2906+
let additional_capacity = 2400;
2907+
let size_hint = values.size_hint().0 + additional_capacity;
29002908
let mut conflicting_values: Vec<&[u8]> = Vec::new();
29012909

29022910
let mut indices: HashTable<(&'static [u8], u32)> = HashTable::with_capacity(size_hint);
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
- // MIR for `read_other_field` before DataflowConstProp
2+
+ // MIR for `read_other_field` after DataflowConstProp
3+
4+
fn read_other_field() -> u8 {
5+
let mut _0: u8;
6+
let mut _1: U;
7+
scope 1 {
8+
debug u => _1;
9+
}
10+
11+
bb0: {
12+
StorageLive(_1);
13+
_1 = U { a: const 0_u8 };
14+
(_1.0: u8) = const 1_u8;
15+
(_1.1: u8) = const 5_u8;
16+
_0 = copy (_1.0: u8);
17+
StorageDead(_1);
18+
return;
19+
}
20+
}
21+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
- // MIR for `read_other_field` before DataflowConstProp
2+
+ // MIR for `read_other_field` after DataflowConstProp
3+
4+
fn read_other_field() -> u8 {
5+
let mut _0: u8;
6+
let mut _1: U;
7+
scope 1 {
8+
debug u => _1;
9+
}
10+
11+
bb0: {
12+
StorageLive(_1);
13+
_1 = U { a: const 0_u8 };
14+
(_1.0: u8) = const 1_u8;
15+
(_1.1: u8) = const 5_u8;
16+
_0 = copy (_1.0: u8);
17+
StorageDead(_1);
18+
return;
19+
}
20+
}
21+
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
2+
// Writing to one union field must also invalidate what is known about the other fields,
3+
// since they share the same storage.
4+
5+
//@ test-mir-pass: DataflowConstProp
6+
//@ compile-flags: --crate-type=lib
7+
8+
union U {
9+
a: u8,
10+
b: u8,
11+
}
12+
13+
// EMIT_MIR union_field.read_other_field.DataflowConstProp.diff
14+
pub fn read_other_field() -> u8 {
15+
// CHECK-LABEL: fn read_other_field(
16+
// CHECK: _0 = copy ({{_.*}}.0: u8);
17+
let mut u = U { a: 0 };
18+
u.a = 1;
19+
u.b = 5;
20+
unsafe { u.a }
21+
}

‎tests/mir-opt/jump_threading.rs‎

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -656,6 +656,42 @@ fn chained_conditions() -> u8 {
656656
}
657657
}
658658

659+
union U {
660+
a: u8,
661+
b: u8,
662+
}
663+
664+
fn union_field(x: u8) -> u8 {
665+
// CHECK-LABEL: fn union_field(
666+
// CHECK: debug u => [[u:_.*]];
667+
// CHECK: bb0: {
668+
// CHECK: switchInt(copy ([[u]].0: u8)) -> [0: bb2, otherwise: bb1];
669+
// CHECK: bb1: {
670+
// CHECK: goto -> bb3;
671+
// CHECK: bb2: {
672+
// CHECK: goto -> bb3;
673+
// CHECK: bb3: {
674+
// CHECK: ([[u]].1: u8) = const 5_u8;
675+
// CHECK: switchInt(copy ([[u]].0: u8)) -> [0: bb5, otherwise: bb4];
676+
677+
// Test for #161898, where the write to `u.b` did not invalidate what was known about `u.a`.
678+
let mut u = U { a: x };
679+
let r = unsafe {
680+
match u.a {
681+
0 => 100,
682+
_ => 200,
683+
}
684+
};
685+
u.b = 5;
686+
let r2 = unsafe {
687+
match u.a {
688+
0 => 1,
689+
_ => 2,
690+
}
691+
};
692+
r + r2
693+
}
694+
659695
fn main() {
660696
// CHECK-LABEL: fn main(
661697
too_complex(Ok(0));
@@ -673,6 +709,7 @@ fn main() {
673709
floats();
674710
bitwise_not();
675711
logical_not();
712+
union_field(0);
676713
}
677714

678715
// EMIT_MIR jump_threading.too_complex.JumpThreading.diff
@@ -693,3 +730,4 @@ fn main() {
693730
// EMIT_MIR jump_threading.bitwise_not.JumpThreading.diff
694731
// EMIT_MIR jump_threading.logical_not.JumpThreading.diff
695732
// EMIT_MIR jump_threading.chained_conditions.JumpThreading.diff
733+
// EMIT_MIR jump_threading.union_field.JumpThreading.diff
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
- // MIR for `union_field` before JumpThreading
2+
+ // MIR for `union_field` after JumpThreading
3+
4+
fn union_field(_1: u8) -> u8 {
5+
debug x => _1;
6+
let mut _0: u8;
7+
let mut _2: U;
8+
let mut _3: u8;
9+
let mut _6: u8;
10+
let mut _7: u8;
11+
scope 1 {
12+
debug u => _2;
13+
let _4: u8;
14+
scope 2 {
15+
debug r => _4;
16+
let _5: u8;
17+
scope 3 {
18+
debug r2 => _5;
19+
}
20+
}
21+
}
22+
23+
bb0: {
24+
StorageLive(_2);
25+
StorageLive(_3);
26+
_3 = copy _1;
27+
_2 = U { a: move _3 };
28+
StorageDead(_3);
29+
StorageLive(_4);
30+
switchInt(copy (_2.0: u8)) -> [0: bb2, otherwise: bb1];
31+
}
32+
33+
bb1: {
34+
_4 = const 200_u8;
35+
goto -> bb3;
36+
}
37+
38+
bb2: {
39+
_4 = const 100_u8;
40+
goto -> bb3;
41+
}
42+
43+
bb3: {
44+
(_2.1: u8) = const 5_u8;
45+
StorageLive(_5);
46+
switchInt(copy (_2.0: u8)) -> [0: bb5, otherwise: bb4];
47+
}
48+
49+
bb4: {
50+
_5 = const 2_u8;
51+
goto -> bb6;
52+
}
53+
54+
bb5: {
55+
_5 = const 1_u8;
56+
goto -> bb6;
57+
}
58+
59+
bb6: {
60+
StorageLive(_6);
61+
_6 = copy _4;
62+
StorageLive(_7);
63+
_7 = copy _5;
64+
_0 = Add(move _6, move _7);
65+
StorageDead(_7);
66+
StorageDead(_6);
67+
StorageDead(_5);
68+
StorageDead(_4);
69+
StorageDead(_2);
70+
return;
71+
}
72+
}
73+

0 commit comments

Comments
 (0)