Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
0bd28ea
feat: Update method signature of int_from_ascii
ajtribick Jul 19, 2026
87c8b4e
Don't re-derive the terminator
nnethercote Jul 20, 2026
205f590
Clarify `MoveData`
nnethercote Jul 20, 2026
06a0c50
Simplify a discriminants iteration
nnethercote Jul 21, 2026
3fb482f
Remove `MaybeUninitializedPlaces::include_inactive_in_otherwise`
nnethercote Jul 21, 2026
b2c8b50
use PostBorrowck typing mode in LateContext
Gri-ffin Jul 24, 2026
176ea43
add next solver revision test for future_not_send
Gri-ffin Jul 25, 2026
964e8ee
remove lints mention from InferCtxt Drop comment
Gri-ffin Jul 25, 2026
ce472c9
Ensure noone can observe the thread spawn hooks being taken
maxdexh Jul 26, 2026
f80e5c1
Explicitly document that spawn hooks are not guaranteed to run
maxdexh Jul 26, 2026
216f9d2
sanitize_standard_fds: Miri supports poll now
RalfJung Jul 26, 2026
8bf37ce
Fix decoding attributes of `SyntheticCoroutineBody`
JonathanBrouwer Jul 26, 2026
e12d28f
Add regression test
JonathanBrouwer Jul 26, 2026
a4caad8
add missing direct test for fcntl(F_GETFD)
RalfJung Jul 26, 2026
8b1803a
Add suggestions for using `#[export_name]` instead of `#[link_name]` …
asuto15 Jul 13, 2026
5e5367b
Remove redundant suggestion filter and consolidate UI tests
asuto15 Jul 26, 2026
b0bc5a0
rustc_target: callconv: mips64: Return structs with single f128 in FPRs
Gelbpunkt Jul 26, 2026
705b6f6
Rollup merge of #159085 - JonathanBrouwer:fix-def-path-attrs, r=folke…
JonathanBrouwer Jul 27, 2026
cb6fec1
Rollup merge of #159554 - ajtribick:int_from_ascii_bytes, r=Mark-Simu…
JonathanBrouwer Jul 27, 2026
411c320
Rollup merge of #159637 - nnethercote:Place-Analysis-tweaks, r=cjgillot
JonathanBrouwer Jul 27, 2026
58e709a
Rollup merge of #159961 - RalfJung:miri-sanitize_standard_fds, r=clar…
JonathanBrouwer Jul 27, 2026
4683313
Rollup merge of #159967 - Gelbpunkt:mips64-struct-return-single-f128,…
JonathanBrouwer Jul 27, 2026
15467e0
Rollup merge of #159253 - asuto15:suggest-export-name, r=JonathanBrouwer
JonathanBrouwer Jul 27, 2026
f2de52c
Rollup merge of #159840 - Gri-ffin:lint-post-borrowck-typing-mode, r=…
JonathanBrouwer Jul 27, 2026
c7b2615
Rollup merge of #159956 - maxdexh:fix-thread-spawn-hook-159923, r=Mar…
JonathanBrouwer Jul 27, 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
12 changes: 12 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -403,6 +403,18 @@ pub(crate) struct InvalidTarget {

#[derive(Subdiagnostic)]
pub(crate) enum InvalidTargetHelp {
#[multipart_suggestion(
"did you mean to use `#[export_name]`?",
applicability = "maybe-incorrect"
)]
UseExportName {
#[suggestion_part(code = "unsafe(")]
unsafe_open: Option<Span>,
#[suggestion_part(code = "export_name")]
name: Span,
#[suggestion_part(code = ")")]
unsafe_close: Option<Span>,
},
#[help("use `#[rustc_align(...)]` instead")]
UseRustcAlign,
#[help("use `#[rustc_align_static(...)]` instead")]
Expand Down
11 changes: 10 additions & 1 deletion compiler/rustc_attr_parsing/src/target_checking.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::borrow::Cow;

use rustc_ast::AttrStyle;
use rustc_ast::{AttrStyle, Safety};
use rustc_errors::{DiagArgValue, MultiSpan, StashKey};
use rustc_feature::Features;
use rustc_hir::attrs::AttributeKind;
Expand Down Expand Up @@ -187,6 +187,15 @@ impl<'sess> AttributeParser<'sess> {
cx: &AcceptContext<'_, '_>,
) -> Option<InvalidTargetHelp> {
match &*cx.attr_path.segments {
[sym::link_name] if cx.target == Target::Static => {
let needs_unsafe_wrapper = matches!(cx.attr_safety, Safety::Default);

Some(InvalidTargetHelp::UseExportName {
unsafe_open: needs_unsafe_wrapper.then(|| cx.inner_span.shrink_to_lo()),
name: cx.attr_path.span,
unsafe_close: needs_unsafe_wrapper.then(|| cx.inner_span.shrink_to_hi()),
})
}
[sym::repr] if attribute_args == "(align(...))" => match cx.target {
Target::Fn | Target::Method(..) if cx.features().fn_align() => {
Some(InvalidTargetHelp::UseRustcAlign)
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/borrow_set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ impl LocalsStateAtExit {
HasStorageDead(DenseBitSet::new_empty(body.local_decls.len()));
has_storage_dead.visit_body(body);
let mut has_storage_dead_or_moved = has_storage_dead.0;
for move_out in &move_data.moves {
for move_out in &move_data.move_outs {
has_storage_dead_or_moved.insert(move_data.base_local(move_out.path));
}
LocalsStateAtExit::SomeAreInvalidated { has_storage_dead_or_moved }
Expand Down
10 changes: 5 additions & 5 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
}

let is_partial_move = move_site_vec.iter().any(|move_site| {
let move_out = self.move_data.moves[(*move_site).moi];
let move_out = self.move_data.move_outs[(*move_site).moi];
let moved_place = &self.move_data.move_paths[move_out.path].place;
// `*(_1)` where `_1` is a `Box` is actually a move out.
let is_box_move = moved_place.as_ref().projection == [ProjectionElem::Deref]
Expand Down Expand Up @@ -215,7 +215,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
let mut seen_spans = FxIndexSet::default();

for move_site in &move_site_vec {
let move_out = self.move_data.moves[(*move_site).moi];
let move_out = self.move_data.move_outs[(*move_site).moi];
let moved_place = &self.move_data.move_paths[move_out.path].place;

let move_spans = self.move_spans(moved_place.as_ref(), move_out.source);
Expand Down Expand Up @@ -281,7 +281,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
_ => true,
};

let mpi = self.move_data.moves[move_out_indices[0]].path;
let mpi = self.move_data.move_outs[move_out_indices[0]].path;
let place = &self.move_data.move_paths[mpi].place;
let ty = place.ty(self.body, self.infcx.tcx).ty;

Expand Down Expand Up @@ -3855,9 +3855,9 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> {
// worry about the other case: that is, if there is a move of a.b.c, it is already
// marked as a move of a.b and a as well, so we will generate the correct errors
// there.
for moi in &self.move_data.loc_map[location] {
for moi in &self.move_data.move_out_loc_map[location] {
debug!("report_use_of_moved_or_uninitialized: moi={:?}", moi);
let path = self.move_data.moves[*moi].path;
let path = self.move_data.move_outs[*moi].path;
if mpis.contains(&path) {
debug!(
"report_use_of_moved_or_uninitialized: found {:?}",
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2373,8 +2373,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, '_, 'tcx> {
// of the union - we should error in that case.
let tcx = this.infcx.tcx;
if base.ty(this.body(), tcx).ty.is_union()
&& this.move_data.path_map[mpi].iter().any(|moi| {
this.move_data.moves[*moi].source.is_predecessor_of(location, this.body)
&& this.move_data.move_out_path_map[mpi].iter().any(|moi| {
this.move_data.move_outs[*moi].source.is_predecessor_of(location, this.body)
})
{
return;
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_borrowck/src/polonius/legacy/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,9 +132,9 @@ fn emit_move_facts(

// moved_out_at
// deinitialisation is assumed to always happen!
facts
.path_moved_at_base
.extend(move_data.moves.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))));
facts.path_moved_at_base.extend(
move_data.move_outs.iter().map(|mo| (mo.path, location_table.mid_index(mo.source))),
);
}

/// Emit universal regions facts, and their relations.
Expand Down
4 changes: 2 additions & 2 deletions compiler/rustc_borrowck/src/used_muts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ impl<'tcx> Visitor<'tcx> for GatherUsedMutsVisitor<'_, '_, '_, 'tcx> {
fn visit_local(&mut self, local: Local, place_context: PlaceContext, location: Location) {
if place_context.is_place_assignment() && self.temporary_used_locals.contains(&local) {
// Propagate the Local assigned at this Location as a used mutable local variable
for moi in &self.mbcx.move_data.loc_map[location] {
let mpi = &self.mbcx.move_data.moves[*moi].path;
for moi in &self.mbcx.move_data.move_out_loc_map[location] {
let mpi = &self.mbcx.move_data.move_outs[*moi].path;
let path = &self.mbcx.move_data.move_paths[*mpi];
debug!(
"assignment of {:?} to {:?}, adding {:?} to used mutable set",
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,7 +355,7 @@ impl<'tcx> Drop for InferCtxt<'tcx> {

// No need for the drop bomb when we're in `TypingMode::PostTypeckUntilBorrowck`, and the `InferCtxt`
// doesn't consider regions. This is okay since after typeck, the only reason we care about opaques is
// in relation to regions. In some places *after* typeck that aren't borrowck, like in lints we use
// in relation to regions. In some places *after* typeck that aren't borrowck, we use
// `TypingMode::PostTypeckUntilBorrowck` to prevent defining opaque types and we simply don't care about regions.
match self.typing_mode_raw() {
TypingMode::Coherence
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ impl<'tcx> LateContext<'tcx> {
&& self.tcx.use_typing_mode_post_typeck_until_borrowck()
{
let def_id = self.tcx.hir_enclosing_body_owner(body_id.hir_id);
TypingMode::borrowck(self.tcx, def_id)
TypingMode::post_borrowck_analysis(self.tcx, def_id)
} else {
TypingMode::non_body_analysis()
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for OpaqueHiddenInferredBound {
}

let def_id = opaque.def_id.to_def_id();
let infcx = &cx.tcx.infer_ctxt().ignoring_regions().build(cx.typing_mode());
let infcx = &cx.tcx.infer_ctxt().build(cx.typing_mode());
// For every projection predicate in the opaque type's explicit bounds,
// check that the type that we're assigning actually satisfies the bounds
// of the associated type.
Expand Down
29 changes: 19 additions & 10 deletions compiler/rustc_metadata/src/rmeta/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1432,17 +1432,26 @@ impl CrateMetadata {
.attributes
.get(self, id)
.unwrap_or_else(|| {
// Structure and variant constructors don't have any attributes encoded for them,
// but we assume that someone passing a constructor ID actually wants to look at
// the attributes on the corresponding struct or variant.
let def_key = self.def_key(id);
assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
let parent_id = def_key.parent.expect("no parent for a constructor");
self.root
.tables
.attributes
.get(self, parent_id)
.expect("no encoded attributes for a structure or variant")
match def_key.disambiguated_data.data {
DefPathData::Ctor => {
// Structure and variant constructors don't have any attributes encoded for them,
// but we assume that someone passing a constructor ID actually wants to look at
// the attributes on the corresponding struct or variant.
assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor);
let parent_id = def_key.parent.expect("no parent for a constructor");
self.root
.tables
.attributes
.get(self, parent_id)
.expect("no encoded attributes for a structure or variant")
}
DefPathData::SyntheticCoroutineBody => {
// SyntheticCoroutineBodies cannot have attributes
LazyArray::default()
}
_ => panic!("Definition key {def_key:?} of type `{:?}` did not have any attributes stored", def_key.disambiguated_data.data)
}
})
.decode((self, tcx))
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_mir_dataflow/src/drop_flag_effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ pub fn drop_flag_effects_for_location<'tcx, F>(
debug!("drop_flag_effects_for_location({:?})", loc);

// first, move out of the RHS
for mi in &move_data.loc_map[loc] {
for mi in &move_data.move_out_loc_map[loc] {
let path = mi.move_path_index(move_data);
debug!("moving out of path {:?}", move_data.move_paths[path]);

Expand Down
39 changes: 11 additions & 28 deletions compiler/rustc_mir_dataflow/src/impls/initialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,25 +59,21 @@ impl<'tcx> MaybePlacesSwitchIntData<'tcx> {
{
match enum_place.ty(body, tcx).ty.kind() {
ty::Adt(enum_def, _) => {
// The value of each discriminant, in AdtDef order.
let discriminant_vals: SmallVec<[u128; 4]> =
enum_def.discriminants(tcx).map(|(_, discr)| discr.val).collect();
let mut i = 0;

// For each value in the SwitchInt, find the VariantIdx for the variant
// with that value. This works because `discriminant_vals` and
// `targets.all_values()` are guaranteed to list variants in the same
// order. (If that ever changes we will get out-of-bounds panics here.)
// AdtDef order. (If that ever changes the `expect` will panic.)
let mut discriminants = enum_def.discriminants(tcx);
let variants = targets
.all_values()
.iter()
.map(|value| {
loop {
if discriminant_vals[i] == value.get() {
return VariantIdx::new(i);
}
i += 1;
}
// On each call to this closure `find` only consumes part of
// the `discriminants` iterator.
discriminants
.find(|(_, discr)| discr.val == value.get())
.expect("SwitchInt vals should match a variant")
.0
})
.collect();

Expand Down Expand Up @@ -232,7 +228,6 @@ pub struct MaybeUninitializedPlaces<'a, 'tcx> {
move_data: &'a MoveData<'tcx>,

mark_inactive_variants_as_uninit: bool,
include_inactive_in_otherwise: bool,
skip_unreachable_unwind: DenseBitSet<mir::BasicBlock>,
}

Expand All @@ -243,7 +238,6 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
body,
move_data,
mark_inactive_variants_as_uninit: false,
include_inactive_in_otherwise: false,
skip_unreachable_unwind: DenseBitSet::new_empty(body.basic_blocks.len()),
}
}
Expand All @@ -258,13 +252,6 @@ impl<'a, 'tcx> MaybeUninitializedPlaces<'a, 'tcx> {
self
}

/// Ensures definitely inactive variants are included in the set of uninitialized places for
/// blocks reached through an `otherwise` edge.
pub fn include_inactive_in_otherwise(mut self) -> Self {
self.include_inactive_in_otherwise = true;
self
}

pub fn skipping_unreachable_unwind(
mut self,
unreachable_unwind: DenseBitSet<mir::BasicBlock>,
Expand Down Expand Up @@ -589,10 +576,7 @@ impl<'tcx> Analysis<'tcx> for MaybeUninitializedPlaces<'_, 'tcx> {
SwitchTargetIndex::Normal(target_idx) => {
InactiveVariants::Active(data.variants[target_idx])
}
SwitchTargetIndex::Otherwise if self.include_inactive_in_otherwise => {
InactiveVariants::Inactives(data.variants.clone())
}
_ => return,
SwitchTargetIndex::Otherwise => InactiveVariants::Inactives(data.variants.clone()),
};

// Mark all move paths that correspond to variants other than this one as maybe
Expand Down Expand Up @@ -658,10 +642,9 @@ impl<'tcx> Analysis<'tcx> for EverInitializedPlaces<'_, 'tcx> {
terminator: &'mir mir::Terminator<'tcx>,
location: Location,
) -> TerminatorEdges<'mir, 'tcx> {
let (body, move_data) = (self.body, self.move_data());
let term = body[location.block].terminator();
let move_data = self.move_data();
let init_loc_map = &move_data.init_loc_map;
debug!(?term);
debug!(?terminator);
debug!("initializes move_indexes {:?}", init_loc_map[location]);
state.gen_all(
init_loc_map[location]
Expand Down
28 changes: 14 additions & 14 deletions compiler/rustc_mir_dataflow/src/move_paths/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ struct MoveDataBuilder<'a, 'tcx, F> {
impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
fn new(body: &'a Body<'tcx>, tcx: TyCtxt<'tcx>, filter: F) -> Self {
let mut move_paths = IndexVec::new();
let mut path_map = IndexVec::new();
let mut move_out_path_map = IndexVec::new();
let mut init_path_map = IndexVec::new();

let locals = body
Expand All @@ -36,7 +36,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
if filter(l.ty) {
Some(new_move_path(
&mut move_paths,
&mut path_map,
&mut move_out_path_map,
&mut init_path_map,
None,
Place::from(i),
Expand All @@ -52,15 +52,15 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
loc: Location::START,
tcx,
data: MoveData {
moves: IndexVec::new(),
loc_map: LocationMap::new(body),
move_outs: IndexVec::new(),
move_out_loc_map: LocationMap::new(body),
rev_lookup: MovePathLookup {
locals,
projections: Default::default(),
un_derefer: Default::default(),
},
move_paths,
path_map,
move_out_path_map,
inits: IndexVec::new(),
init_loc_map: LocationMap::new(body),
init_path_map,
Expand All @@ -72,7 +72,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {

fn new_move_path<'tcx>(
move_paths: &mut IndexVec<MovePathIndex, MovePath<'tcx>>,
path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
move_out_path_map: &mut IndexVec<MovePathIndex, SmallVec<[MoveOutIndex; 4]>>,
init_path_map: &mut IndexVec<MovePathIndex, SmallVec<[InitIndex; 4]>>,
parent: Option<MovePathIndex>,
place: Place<'tcx>,
Expand All @@ -85,7 +85,7 @@ fn new_move_path<'tcx>(
move_paths[move_path].next_sibling = next_sibling;
}

let path_map_ent = path_map.push(smallvec![]);
let path_map_ent = move_out_path_map.push(smallvec![]);
assert_eq!(path_map_ent, move_path);

let init_path_map_ent = init_path_map.push(smallvec![]);
Expand Down Expand Up @@ -279,7 +279,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
base = *data.rev_lookup.projections.entry((base, move_elem)).or_insert_with(|| {
new_move_path(
&mut data.move_paths,
&mut data.path_map,
&mut data.move_out_path_map,
&mut data.init_path_map,
Some(base),
place_ref.project_deeper(&[elem], tcx),
Expand All @@ -305,12 +305,12 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
mk_place: impl FnOnce(TyCtxt<'tcx>) -> Place<'tcx>,
) -> MovePathIndex {
let MoveDataBuilder {
data: MoveData { rev_lookup, move_paths, path_map, init_path_map, .. },
data: MoveData { rev_lookup, move_paths, move_out_path_map, init_path_map, .. },
tcx,
..
} = self;
*rev_lookup.projections.entry((base, elem)).or_insert_with(move || {
new_move_path(move_paths, path_map, init_path_map, Some(base), mk_place(*tcx))
new_move_path(move_paths, move_out_path_map, init_path_map, Some(base), mk_place(*tcx))
})
}

Expand All @@ -323,7 +323,7 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
fn finalize(self) -> MoveData<'tcx> {
debug!("{}", {
debug!("moves for {:?}:", self.body.span);
for (j, mo) in self.data.moves.iter_enumerated() {
for (j, mo) in self.data.move_outs.iter_enumerated() {
debug!(" {:?} = {:?}", j, mo);
}
debug!("move paths for {:?}:", self.body.span);
Expand Down Expand Up @@ -553,13 +553,13 @@ impl<'a, 'tcx, F: Fn(Ty<'tcx>) -> bool> MoveDataBuilder<'a, 'tcx, F> {
}

fn record_move(&mut self, place: Place<'tcx>, path: MovePathIndex) {
let move_out = self.data.moves.push(MoveOut { path, source: self.loc });
let move_out = self.data.move_outs.push(MoveOut { path, source: self.loc });
debug!(
"gather_move({:?}, {:?}): adding move {:?} of {:?}",
self.loc, place, move_out, path
);
self.data.path_map[path].push(move_out);
self.data.loc_map[self.loc].push(move_out);
self.data.move_out_path_map[path].push(move_out);
self.data.move_out_loc_map[self.loc].push(move_out);
}

fn gather_init(&mut self, place: PlaceRef<'tcx>, kind: InitKind) {
Expand Down
Loading
Loading