Skip to content

Commit ba284f4

Browse files
committed
Auto merge of #151794 - JonathanBrouwer:rollup-rGbYGX2, r=JonathanBrouwer
Rollup of 12 pull requests Successful merges: - #150491 (resolve: Mark items under exported ambiguous imports as exported) - #150720 (Do not suggest `derive` if there is already an impl) - #150968 (compiler-builtins: Remove the no-f16-f128 feature) - #151493 ([RFC] rustc_parse: improve the error diagnostic for "missing let in let chain") - #151660 (Bump `std`'s `backtrace`'s `rustc-demangle`) - #151696 (Borrowck: Simplify SCC annotation computation, placeholder rewriting) - #151704 (Implement `set_output_kind` for Emscripten linker) - #151706 (Remove Fuchsia from target OS list in unix.rs for sleep) - #151769 (fix undefined behavior in VecDeque::splice) - #151779 (stdarch subtree update) - #151449 ([rustdoc] Add regression test for #151411) - #151773 (clean up checks for constant promotion of integer division/remainder operations)
2 parents de6d33c + aeba7d5 commit ba284f4

File tree

72 files changed

+7318
-3877
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

72 files changed

+7318
-3877
lines changed

compiler/rustc_borrowck/src/handle_placeholders.rs

Lines changed: 42 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -62,65 +62,31 @@ impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
6262
}
6363

6464
#[derive(Copy, Debug, Clone, PartialEq, Eq)]
65-
enum PlaceholderReachability {
66-
/// This SCC reaches no placeholders.
67-
NoPlaceholders,
68-
/// This SCC reaches at least one placeholder.
69-
Placeholders {
70-
/// The largest-universed placeholder we can reach
71-
max_universe: (UniverseIndex, RegionVid),
72-
73-
/// The placeholder with the smallest ID
74-
min_placeholder: RegionVid,
75-
76-
/// The placeholder with the largest ID
77-
max_placeholder: RegionVid,
78-
},
65+
struct PlaceholderReachability {
66+
/// The largest-universed placeholder we can reach
67+
max_universe: (UniverseIndex, RegionVid),
68+
69+
/// The placeholder with the smallest ID
70+
min_placeholder: RegionVid,
71+
72+
/// The placeholder with the largest ID
73+
max_placeholder: RegionVid,
7974
}
8075

8176
impl PlaceholderReachability {
8277
/// Merge the reachable placeholders of two graph components.
83-
fn merge(self, other: PlaceholderReachability) -> PlaceholderReachability {
84-
use PlaceholderReachability::*;
85-
match (self, other) {
86-
(NoPlaceholders, NoPlaceholders) => NoPlaceholders,
87-
(NoPlaceholders, p @ Placeholders { .. })
88-
| (p @ Placeholders { .. }, NoPlaceholders) => p,
89-
(
90-
Placeholders {
91-
min_placeholder: min_pl,
92-
max_placeholder: max_pl,
93-
max_universe: max_u,
94-
},
95-
Placeholders { min_placeholder, max_placeholder, max_universe },
96-
) => Placeholders {
97-
min_placeholder: min_pl.min(min_placeholder),
98-
max_placeholder: max_pl.max(max_placeholder),
99-
max_universe: max_u.max(max_universe),
100-
},
101-
}
102-
}
103-
104-
fn max_universe(&self) -> Option<(UniverseIndex, RegionVid)> {
105-
match self {
106-
Self::NoPlaceholders => None,
107-
Self::Placeholders { max_universe, .. } => Some(*max_universe),
108-
}
109-
}
110-
111-
/// If we have reached placeholders, determine if they can
112-
/// be named from this universe.
113-
fn can_be_named_by(&self, from: UniverseIndex) -> bool {
114-
self.max_universe()
115-
.is_none_or(|(max_placeholder_universe, _)| from.can_name(max_placeholder_universe))
78+
fn merge(&mut self, other: &Self) {
79+
self.max_universe = self.max_universe.max(other.max_universe);
80+
self.min_placeholder = self.min_placeholder.min(other.min_placeholder);
81+
self.max_placeholder = self.max_placeholder.max(other.max_placeholder);
11682
}
11783
}
11884

11985
/// An annotation for region graph SCCs that tracks
12086
/// the values of its elements. This annotates a single SCC.
12187
#[derive(Copy, Debug, Clone)]
12288
pub(crate) struct RegionTracker {
123-
reachable_placeholders: PlaceholderReachability,
89+
reachable_placeholders: Option<PlaceholderReachability>,
12490

12591
/// The largest universe nameable from this SCC.
12692
/// It is the smallest nameable universes of all
@@ -135,13 +101,13 @@ impl RegionTracker {
135101
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
136102
let reachable_placeholders =
137103
if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
138-
PlaceholderReachability::Placeholders {
104+
Some(PlaceholderReachability {
139105
max_universe: (definition.universe, rvid),
140106
min_placeholder: rvid,
141107
max_placeholder: rvid,
142-
}
108+
})
143109
} else {
144-
PlaceholderReachability::NoPlaceholders
110+
None
145111
};
146112

147113
Self {
@@ -159,43 +125,46 @@ impl RegionTracker {
159125
}
160126

161127
pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
162-
if let Some((universe, _)) = self.reachable_placeholders.max_universe() {
163-
universe
164-
} else {
165-
UniverseIndex::ROOT
166-
}
128+
self.reachable_placeholders.map(|pls| pls.max_universe.0).unwrap_or(UniverseIndex::ROOT)
129+
}
130+
131+
/// Can all reachable placeholders be named from `from`?
132+
/// True vacuously in case no placeholders were reached.
133+
fn placeholders_can_be_named_by(&self, from: UniverseIndex) -> bool {
134+
self.reachable_placeholders.is_none_or(|pls| from.can_name(pls.max_universe.0))
167135
}
168136

169137
/// Determine if we can name all the placeholders in `other`.
170138
pub(crate) fn can_name_all_placeholders(&self, other: Self) -> bool {
171-
other.reachable_placeholders.can_be_named_by(self.max_nameable_universe.0)
139+
// HACK: We first check whether we can name the highest existential universe
140+
// of `other`. This only exists to avoid errors in case that scc already
141+
// depends on a placeholder it cannot name itself.
142+
self.max_nameable_universe().can_name(other.max_nameable_universe())
143+
|| other.placeholders_can_be_named_by(self.max_nameable_universe.0)
172144
}
173145

174146
/// If this SCC reaches a placeholder it can't name, return it.
175147
fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> {
176-
self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| {
177-
!self.max_nameable_universe().can_name(placeholder_universe)
178-
})
148+
self.reachable_placeholders
149+
.filter(|pls| !self.max_nameable_universe().can_name(pls.max_universe.0))
150+
.map(|pls| pls.max_universe)
179151
}
180152
}
181153

182154
impl scc::Annotation for RegionTracker {
183-
fn merge_scc(self, other: Self) -> Self {
155+
fn update_scc(&mut self, other: &Self) {
184156
trace!("{:?} << {:?}", self.representative, other.representative);
185-
186-
Self {
187-
representative: self.representative.min(other.representative),
188-
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
189-
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
190-
}
157+
self.representative = self.representative.min(other.representative);
158+
self.update_reachable(other);
191159
}
192160

193-
fn merge_reached(self, other: Self) -> Self {
194-
Self {
195-
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
196-
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
197-
representative: self.representative,
198-
}
161+
fn update_reachable(&mut self, other: &Self) {
162+
self.max_nameable_universe = self.max_nameable_universe.min(other.max_nameable_universe);
163+
match (self.reachable_placeholders.as_mut(), other.reachable_placeholders.as_ref()) {
164+
(None, None) | (Some(_), None) => (),
165+
(None, Some(theirs)) => self.reachable_placeholders = Some(*theirs),
166+
(Some(ours), Some(theirs)) => ours.merge(theirs),
167+
};
199168
}
200169
}
201170

compiler/rustc_codegen_ssa/src/back/linker.rs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1208,10 +1208,23 @@ impl<'a> Linker for EmLinker<'a> {
12081208

12091209
fn set_output_kind(
12101210
&mut self,
1211-
_output_kind: LinkOutputKind,
1211+
output_kind: LinkOutputKind,
12121212
_crate_type: CrateType,
12131213
_out_filename: &Path,
12141214
) {
1215+
match output_kind {
1216+
LinkOutputKind::DynamicNoPicExe | LinkOutputKind::DynamicPicExe => {
1217+
self.cmd.arg("-sMAIN_MODULE=2");
1218+
}
1219+
LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
1220+
self.cmd.arg("-sSIDE_MODULE=2");
1221+
}
1222+
// -fno-pie is the default on Emscripten.
1223+
LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {}
1224+
LinkOutputKind::WasiReactorExe => {
1225+
unreachable!();
1226+
}
1227+
}
12151228
}
12161229

12171230
fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {

compiler/rustc_data_structures/src/graph/scc/mod.rs

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -27,26 +27,18 @@ mod tests;
2727
/// the max/min element of the SCC, or all of the above.
2828
///
2929
/// Concretely, the both merge operations must commute, e.g. where `merge`
30-
/// is `merge_scc` and `merge_reached`: `a.merge(b) == b.merge(a)`
30+
/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)`
3131
///
3232
/// In general, what you want is probably always min/max according
3333
/// to some ordering, potentially with side constraints (min x such
3434
/// that P holds).
3535
pub trait Annotation: Debug + Copy {
3636
/// Merge two existing annotations into one during
37-
/// path compression.o
38-
fn merge_scc(self, other: Self) -> Self;
37+
/// path compression.
38+
fn update_scc(&mut self, other: &Self);
3939

4040
/// Merge a successor into this annotation.
41-
fn merge_reached(self, other: Self) -> Self;
42-
43-
fn update_scc(&mut self, other: Self) {
44-
*self = self.merge_scc(other)
45-
}
46-
47-
fn update_reachable(&mut self, other: Self) {
48-
*self = self.merge_reached(other)
49-
}
41+
fn update_reachable(&mut self, other: &Self);
5042
}
5143

5244
/// An accumulator for annotations.
@@ -70,12 +62,8 @@ impl<N: Idx, S: Idx + Ord> Annotations<N> for NoAnnotations<S> {
7062

7163
/// The empty annotation, which does nothing.
7264
impl Annotation for () {
73-
fn merge_reached(self, _other: Self) -> Self {
74-
()
75-
}
76-
fn merge_scc(self, _other: Self) -> Self {
77-
()
78-
}
65+
fn update_reachable(&mut self, _other: &Self) {}
66+
fn update_scc(&mut self, _other: &Self) {}
7967
}
8068

8169
/// Strongly connected components (SCC) of a graph. The type `N` is
@@ -614,7 +602,7 @@ where
614602
*min_depth = successor_min_depth;
615603
*min_cycle_root = successor_node;
616604
}
617-
current_component_annotation.update_scc(successor_annotation);
605+
current_component_annotation.update_scc(&successor_annotation);
618606
}
619607
// The starting node `node` is succeeded by a fully identified SCC
620608
// which is now added to the set under `scc_index`.
@@ -629,7 +617,7 @@ where
629617
// the `successors_stack` for later.
630618
trace!(?node, ?successor_scc_index);
631619
successors_stack.push(successor_scc_index);
632-
current_component_annotation.update_reachable(successor_annotation);
620+
current_component_annotation.update_reachable(&successor_annotation);
633621
}
634622
// `node` has no more (direct) successors; search recursively.
635623
None => {

compiler/rustc_data_structures/src/graph/scc/tests.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,12 +32,12 @@ impl Maxes {
3232
}
3333

3434
impl Annotation for MaxReached {
35-
fn merge_scc(self, other: Self) -> Self {
36-
Self(std::cmp::max(other.0, self.0))
35+
fn update_scc(&mut self, other: &Self) {
36+
self.0 = self.0.max(other.0);
3737
}
3838

39-
fn merge_reached(self, other: Self) -> Self {
40-
Self(std::cmp::max(other.0, self.0))
39+
fn update_reachable(&mut self, other: &Self) {
40+
self.0 = self.0.max(other.0);
4141
}
4242
}
4343

@@ -75,13 +75,12 @@ impl Annotations<usize> for MinMaxes {
7575
}
7676

7777
impl Annotation for MinMaxIn {
78-
fn merge_scc(self, other: Self) -> Self {
79-
Self { min: std::cmp::min(self.min, other.min), max: std::cmp::max(self.max, other.max) }
78+
fn update_scc(&mut self, other: &Self) {
79+
self.min = self.min.min(other.min);
80+
self.max = self.max.max(other.max);
8081
}
8182

82-
fn merge_reached(self, _other: Self) -> Self {
83-
self
84-
}
83+
fn update_reachable(&mut self, _other: &Self) {}
8584
}
8685

8786
#[test]

compiler/rustc_hir_typeck/src/method/suggest.rs

Lines changed: 59 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -3281,6 +3281,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32813281
}
32823282
}
32833283

3284+
/// Checks if we can suggest a derive macro for the unmet trait bound.
3285+
/// Returns Some(list_of_derives) if possible, or None if not.
3286+
fn consider_suggesting_derives_for_ty(
3287+
&self,
3288+
trait_pred: ty::TraitPredicate<'tcx>,
3289+
adt: ty::AdtDef<'tcx>,
3290+
) -> Option<Vec<(String, Span, Symbol)>> {
3291+
let diagnostic_name = self.tcx.get_diagnostic_name(trait_pred.def_id())?;
3292+
3293+
let can_derive = match diagnostic_name {
3294+
sym::Default
3295+
| sym::Eq
3296+
| sym::PartialEq
3297+
| sym::Ord
3298+
| sym::PartialOrd
3299+
| sym::Clone
3300+
| sym::Copy
3301+
| sym::Hash
3302+
| sym::Debug => true,
3303+
_ => false,
3304+
};
3305+
3306+
if !can_derive {
3307+
return None;
3308+
}
3309+
3310+
let trait_def_id = trait_pred.def_id();
3311+
let self_ty = trait_pred.self_ty();
3312+
3313+
// We need to check if there is already a manual implementation of the trait
3314+
// for this specific ADT to avoid suggesting `#[derive(..)]` that would conflict.
3315+
if self.tcx.non_blanket_impls_for_ty(trait_def_id, self_ty).any(|impl_def_id| {
3316+
self.tcx
3317+
.type_of(impl_def_id)
3318+
.instantiate_identity()
3319+
.ty_adt_def()
3320+
.is_some_and(|def| def.did() == adt.did())
3321+
}) {
3322+
return None;
3323+
}
3324+
3325+
let mut derives = Vec::new();
3326+
let self_name = self_ty.to_string();
3327+
let self_span = self.tcx.def_span(adt.did());
3328+
3329+
for super_trait in supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref)) {
3330+
if let Some(parent_diagnostic_name) = self.tcx.get_diagnostic_name(super_trait.def_id())
3331+
{
3332+
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
3333+
}
3334+
}
3335+
3336+
derives.push((self_name, self_span, diagnostic_name));
3337+
3338+
Some(derives)
3339+
}
3340+
32843341
fn note_predicate_source_and_get_derives(
32853342
&self,
32863343
err: &mut Diag<'_>,
@@ -3298,35 +3355,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
32983355
Some(adt) if adt.did().is_local() => adt,
32993356
_ => continue,
33003357
};
3301-
if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
3302-
let can_derive = match diagnostic_name {
3303-
sym::Default
3304-
| sym::Eq
3305-
| sym::PartialEq
3306-
| sym::Ord
3307-
| sym::PartialOrd
3308-
| sym::Clone
3309-
| sym::Copy
3310-
| sym::Hash
3311-
| sym::Debug => true,
3312-
_ => false,
3313-
};
3314-
if can_derive {
3315-
let self_name = trait_pred.self_ty().to_string();
3316-
let self_span = self.tcx.def_span(adt.did());
3317-
for super_trait in
3318-
supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
3319-
{
3320-
if let Some(parent_diagnostic_name) =
3321-
self.tcx.get_diagnostic_name(super_trait.def_id())
3322-
{
3323-
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
3324-
}
3325-
}
3326-
derives.push((self_name, self_span, diagnostic_name));
3327-
} else {
3328-
traits.push(trait_pred.def_id());
3329-
}
3358+
if let Some(new_derives) = self.consider_suggesting_derives_for_ty(trait_pred, adt) {
3359+
derives.extend(new_derives);
33303360
} else {
33313361
traits.push(trait_pred.def_id());
33323362
}

0 commit comments

Comments
 (0)