Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
7630884
Avoid `unsafe fn` in remaining x86 tests
eduardosm Jan 6, 2026
c7c5adb
compiler-builtins: Remove the no-f16-f128 feature
tgross35 Jan 11, 2026
f09b0bc
Creates README for stdarch-gen-arm
CrooseGit Dec 22, 2025
f4731a1
Bump `std`'s `backtrace`'s `rustc-demangle`
fmease Jan 25, 2026
a8e9147
tests: Reproduce the issue with missing MIR for ambiguous reexports
petrochenkov Dec 28, 2025
4bdccab
Borrowck: Simplify SCC annotation computation, placeholder rewriting
amandasystems Jan 26, 2026
44e89f8
resolve: Mark items under ambigous imports as exported
petrochenkov Jan 8, 2026
e20d484
Merge pull request #1989 from eduardosm/unsafe-tests
Amanieu Jan 27, 2026
333ce17
Merge pull request #1995 from CrooseGit/dev/reucru01/documentation
Amanieu Jan 27, 2026
354365a
Adds some arm intrinsics to bring more up-to-date with acle
CrooseGit Jan 14, 2026
57a42db
Makes some A64 intrinsics available on A32
CrooseGit Dec 17, 2025
9ce0ebf
Disables `assert_instr` tests on windows msvc
CrooseGit Jan 14, 2026
9fddd28
Ammends typo in generator & generated
CrooseGit Jan 14, 2026
5a6e867
Merge pull request #1994 from CrooseGit/dev/reucru01/add-missing-intr…
folkertdev Jan 27, 2026
5dbaac1
Remove Fuchsia from target OS list in unix.rs for sleep
PiJoules Jan 27, 2026
35ccf18
Add regression test for #151411
GuillaumeGomez Jan 21, 2026
b0d9649
fix undefined behavior in VecDeque::splice
Qelxiros Jan 28, 2026
5ddb7f6
clean up checks for integer div/rem promotion
dianne Jan 28, 2026
10e053d
Implement `set_output_kind` for Emscripten linker
hoodmane Jan 26, 2026
11ae531
diagnostics: don't suggest `#[derive]` if impl already exists
WhyNovaa Jan 5, 2026
f4b4ab3
remove fp16 target feature from some vreinterpret intrinsics
usamoi Jan 10, 2026
18a4a3a
fix overflowing_literals in avx512fp16 tests
usamoi Jan 28, 2026
9ca8ed3
rustc_parse: improve the error diagnostic for "missing let in let chain"
Unique-Usman Jan 27, 2026
70a07c9
Merge pull request #1991 from usamoi/fp16-transmute
folkertdev Jan 28, 2026
8bdd8dc
Rollup merge of #150491 - petrochenkov:ambigeffvis, r=yaahc
JonathanBrouwer Jan 28, 2026
3787595
Rollup merge of #150720 - WhyNovaa:diagnostics-impl-fix, r=lcnr
JonathanBrouwer Jan 28, 2026
3f23c09
Rollup merge of #150968 - tgross35:remove-no-f16-f128, r=Amanieu
JonathanBrouwer Jan 28, 2026
41caa6e
Rollup merge of #151493 - Unique-Usman:ua/missinglet, r=estebank
JonathanBrouwer Jan 28, 2026
1eba55e
Rollup merge of #151660 - fmease:bump-backtrace-demangler-alt, r=tgro…
JonathanBrouwer Jan 28, 2026
d0a9dac
Rollup merge of #151696 - amandasystems:scc-annotations-update, r=lcnr
JonathanBrouwer Jan 28, 2026
b84cf6f
Rollup merge of #151704 - hoodmane:emscripten-set-output-kind, r=petr…
JonathanBrouwer Jan 28, 2026
b841ab2
Rollup merge of #151706 - PiJoules:fuchsia-nanosleep, r=joboet
JonathanBrouwer Jan 28, 2026
3ffbf6e
Rollup merge of #151769 - Qelxiros:vecdeque_splice_fix, r=joboet
JonathanBrouwer Jan 28, 2026
e3da016
Rollup merge of #151779 - folkertdev:stdarch-sync-2026-01-28, r=folke…
JonathanBrouwer Jan 28, 2026
775abf4
Rollup merge of #151449 - GuillaumeGomez:regression-test-for-151411, …
JonathanBrouwer Jan 28, 2026
aeba7d5
Rollup merge of #151773 - dianne:cleanup-division-promotion, r=oli-obk
JonathanBrouwer Jan 28, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 42 additions & 73 deletions compiler/rustc_borrowck/src/handle_placeholders.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,65 +62,31 @@ impl scc::Annotations<RegionVid> for SccAnnotations<'_, '_, RegionTracker> {
}

#[derive(Copy, Debug, Clone, PartialEq, Eq)]
enum PlaceholderReachability {
/// This SCC reaches no placeholders.
NoPlaceholders,
/// This SCC reaches at least one placeholder.
Placeholders {
/// The largest-universed placeholder we can reach
max_universe: (UniverseIndex, RegionVid),

/// The placeholder with the smallest ID
min_placeholder: RegionVid,

/// The placeholder with the largest ID
max_placeholder: RegionVid,
},
struct PlaceholderReachability {
/// The largest-universed placeholder we can reach
max_universe: (UniverseIndex, RegionVid),

/// The placeholder with the smallest ID
min_placeholder: RegionVid,

/// The placeholder with the largest ID
max_placeholder: RegionVid,
}

impl PlaceholderReachability {
/// Merge the reachable placeholders of two graph components.
fn merge(self, other: PlaceholderReachability) -> PlaceholderReachability {
use PlaceholderReachability::*;
match (self, other) {
(NoPlaceholders, NoPlaceholders) => NoPlaceholders,
(NoPlaceholders, p @ Placeholders { .. })
| (p @ Placeholders { .. }, NoPlaceholders) => p,
(
Placeholders {
min_placeholder: min_pl,
max_placeholder: max_pl,
max_universe: max_u,
},
Placeholders { min_placeholder, max_placeholder, max_universe },
) => Placeholders {
min_placeholder: min_pl.min(min_placeholder),
max_placeholder: max_pl.max(max_placeholder),
max_universe: max_u.max(max_universe),
},
}
}

fn max_universe(&self) -> Option<(UniverseIndex, RegionVid)> {
match self {
Self::NoPlaceholders => None,
Self::Placeholders { max_universe, .. } => Some(*max_universe),
}
}

/// If we have reached placeholders, determine if they can
/// be named from this universe.
fn can_be_named_by(&self, from: UniverseIndex) -> bool {
self.max_universe()
.is_none_or(|(max_placeholder_universe, _)| from.can_name(max_placeholder_universe))
fn merge(&mut self, other: &Self) {
self.max_universe = self.max_universe.max(other.max_universe);
self.min_placeholder = self.min_placeholder.min(other.min_placeholder);
self.max_placeholder = self.max_placeholder.max(other.max_placeholder);
}
}

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

/// The largest universe nameable from this SCC.
/// It is the smallest nameable universes of all
Expand All @@ -135,13 +101,13 @@ impl RegionTracker {
pub(crate) fn new(rvid: RegionVid, definition: &RegionDefinition<'_>) -> Self {
let reachable_placeholders =
if matches!(definition.origin, NllRegionVariableOrigin::Placeholder(_)) {
PlaceholderReachability::Placeholders {
Some(PlaceholderReachability {
max_universe: (definition.universe, rvid),
min_placeholder: rvid,
max_placeholder: rvid,
}
})
} else {
PlaceholderReachability::NoPlaceholders
None
};

Self {
Expand All @@ -159,43 +125,46 @@ impl RegionTracker {
}

pub(crate) fn max_placeholder_universe_reached(self) -> UniverseIndex {
if let Some((universe, _)) = self.reachable_placeholders.max_universe() {
universe
} else {
UniverseIndex::ROOT
}
self.reachable_placeholders.map(|pls| pls.max_universe.0).unwrap_or(UniverseIndex::ROOT)
}

/// Can all reachable placeholders be named from `from`?
/// True vacuously in case no placeholders were reached.
fn placeholders_can_be_named_by(&self, from: UniverseIndex) -> bool {
self.reachable_placeholders.is_none_or(|pls| from.can_name(pls.max_universe.0))
}

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

/// If this SCC reaches a placeholder it can't name, return it.
fn unnameable_placeholder(&self) -> Option<(UniverseIndex, RegionVid)> {
self.reachable_placeholders.max_universe().filter(|&(placeholder_universe, _)| {
!self.max_nameable_universe().can_name(placeholder_universe)
})
self.reachable_placeholders
.filter(|pls| !self.max_nameable_universe().can_name(pls.max_universe.0))
.map(|pls| pls.max_universe)
}
}

impl scc::Annotation for RegionTracker {
fn merge_scc(self, other: Self) -> Self {
fn update_scc(&mut self, other: &Self) {
trace!("{:?} << {:?}", self.representative, other.representative);

Self {
representative: self.representative.min(other.representative),
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
}
self.representative = self.representative.min(other.representative);
self.update_reachable(other);
}

fn merge_reached(self, other: Self) -> Self {
Self {
max_nameable_universe: self.max_nameable_universe.min(other.max_nameable_universe),
reachable_placeholders: self.reachable_placeholders.merge(other.reachable_placeholders),
representative: self.representative,
}
fn update_reachable(&mut self, other: &Self) {
self.max_nameable_universe = self.max_nameable_universe.min(other.max_nameable_universe);
match (self.reachable_placeholders.as_mut(), other.reachable_placeholders.as_ref()) {
(None, None) | (Some(_), None) => (),
(None, Some(theirs)) => self.reachable_placeholders = Some(*theirs),
(Some(ours), Some(theirs)) => ours.merge(theirs),
};
}
}

Expand Down
15 changes: 14 additions & 1 deletion compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1208,10 +1208,23 @@ impl<'a> Linker for EmLinker<'a> {

fn set_output_kind(
&mut self,
_output_kind: LinkOutputKind,
output_kind: LinkOutputKind,
_crate_type: CrateType,
_out_filename: &Path,
) {
match output_kind {
LinkOutputKind::DynamicNoPicExe | LinkOutputKind::DynamicPicExe => {
self.cmd.arg("-sMAIN_MODULE=2");
}
LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
self.cmd.arg("-sSIDE_MODULE=2");
}
// -fno-pie is the default on Emscripten.
LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {}
LinkOutputKind::WasiReactorExe => {
unreachable!();
}
}
}

fn link_dylib_by_name(&mut self, name: &str, _verbatim: bool, _as_needed: bool) {
Expand Down
28 changes: 8 additions & 20 deletions compiler/rustc_data_structures/src/graph/scc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,26 +27,18 @@ mod tests;
/// the max/min element of the SCC, or all of the above.
///
/// Concretely, the both merge operations must commute, e.g. where `merge`
/// is `merge_scc` and `merge_reached`: `a.merge(b) == b.merge(a)`
/// is `update_scc` and `update_reached`: `a.merge(b) == b.merge(a)`
///
/// In general, what you want is probably always min/max according
/// to some ordering, potentially with side constraints (min x such
/// that P holds).
pub trait Annotation: Debug + Copy {
/// Merge two existing annotations into one during
/// path compression.o
fn merge_scc(self, other: Self) -> Self;
/// path compression.
fn update_scc(&mut self, other: &Self);

/// Merge a successor into this annotation.
fn merge_reached(self, other: Self) -> Self;

fn update_scc(&mut self, other: Self) {
*self = self.merge_scc(other)
}

fn update_reachable(&mut self, other: Self) {
*self = self.merge_reached(other)
}
fn update_reachable(&mut self, other: &Self);
}

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

/// The empty annotation, which does nothing.
impl Annotation for () {
fn merge_reached(self, _other: Self) -> Self {
()
}
fn merge_scc(self, _other: Self) -> Self {
()
}
fn update_reachable(&mut self, _other: &Self) {}
fn update_scc(&mut self, _other: &Self) {}
}

/// Strongly connected components (SCC) of a graph. The type `N` is
Expand Down Expand Up @@ -614,7 +602,7 @@ where
*min_depth = successor_min_depth;
*min_cycle_root = successor_node;
}
current_component_annotation.update_scc(successor_annotation);
current_component_annotation.update_scc(&successor_annotation);
}
// The starting node `node` is succeeded by a fully identified SCC
// which is now added to the set under `scc_index`.
Expand All @@ -629,7 +617,7 @@ where
// the `successors_stack` for later.
trace!(?node, ?successor_scc_index);
successors_stack.push(successor_scc_index);
current_component_annotation.update_reachable(successor_annotation);
current_component_annotation.update_reachable(&successor_annotation);
}
// `node` has no more (direct) successors; search recursively.
None => {
Expand Down
17 changes: 8 additions & 9 deletions compiler/rustc_data_structures/src/graph/scc/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ impl Maxes {
}

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

fn merge_reached(self, other: Self) -> Self {
Self(std::cmp::max(other.0, self.0))
fn update_reachable(&mut self, other: &Self) {
self.0 = self.0.max(other.0);
}
}

Expand Down Expand Up @@ -75,13 +75,12 @@ impl Annotations<usize> for MinMaxes {
}

impl Annotation for MinMaxIn {
fn merge_scc(self, other: Self) -> Self {
Self { min: std::cmp::min(self.min, other.min), max: std::cmp::max(self.max, other.max) }
fn update_scc(&mut self, other: &Self) {
self.min = self.min.min(other.min);
self.max = self.max.max(other.max);
}

fn merge_reached(self, _other: Self) -> Self {
self
}
fn update_reachable(&mut self, _other: &Self) {}
}

#[test]
Expand Down
88 changes: 59 additions & 29 deletions compiler/rustc_hir_typeck/src/method/suggest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3281,6 +3281,63 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
}
}

/// Checks if we can suggest a derive macro for the unmet trait bound.
/// Returns Some(list_of_derives) if possible, or None if not.
fn consider_suggesting_derives_for_ty(
&self,
trait_pred: ty::TraitPredicate<'tcx>,
adt: ty::AdtDef<'tcx>,
) -> Option<Vec<(String, Span, Symbol)>> {
let diagnostic_name = self.tcx.get_diagnostic_name(trait_pred.def_id())?;

let can_derive = match diagnostic_name {
sym::Default
| sym::Eq
| sym::PartialEq
| sym::Ord
| sym::PartialOrd
| sym::Clone
| sym::Copy
| sym::Hash
| sym::Debug => true,
_ => false,
};

if !can_derive {
return None;
}

let trait_def_id = trait_pred.def_id();
let self_ty = trait_pred.self_ty();

// We need to check if there is already a manual implementation of the trait
// for this specific ADT to avoid suggesting `#[derive(..)]` that would conflict.
if self.tcx.non_blanket_impls_for_ty(trait_def_id, self_ty).any(|impl_def_id| {
self.tcx
.type_of(impl_def_id)
.instantiate_identity()
.ty_adt_def()
.is_some_and(|def| def.did() == adt.did())
}) {
return None;
}

let mut derives = Vec::new();
let self_name = self_ty.to_string();
let self_span = self.tcx.def_span(adt.did());

for super_trait in supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref)) {
if let Some(parent_diagnostic_name) = self.tcx.get_diagnostic_name(super_trait.def_id())
{
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
}
}

derives.push((self_name, self_span, diagnostic_name));

Some(derives)
}

fn note_predicate_source_and_get_derives(
&self,
err: &mut Diag<'_>,
Expand All @@ -3298,35 +3355,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
Some(adt) if adt.did().is_local() => adt,
_ => continue,
};
if let Some(diagnostic_name) = self.tcx.get_diagnostic_name(trait_pred.def_id()) {
let can_derive = match diagnostic_name {
sym::Default
| sym::Eq
| sym::PartialEq
| sym::Ord
| sym::PartialOrd
| sym::Clone
| sym::Copy
| sym::Hash
| sym::Debug => true,
_ => false,
};
if can_derive {
let self_name = trait_pred.self_ty().to_string();
let self_span = self.tcx.def_span(adt.did());
for super_trait in
supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref))
{
if let Some(parent_diagnostic_name) =
self.tcx.get_diagnostic_name(super_trait.def_id())
{
derives.push((self_name.clone(), self_span, parent_diagnostic_name));
}
}
derives.push((self_name, self_span, diagnostic_name));
} else {
traits.push(trait_pred.def_id());
}
if let Some(new_derives) = self.consider_suggesting_derives_for_ty(trait_pred, adt) {
derives.extend(new_derives);
} else {
traits.push(trait_pred.def_id());
}
Expand Down
Loading
Loading