Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
1b5c239
Stabilize `int_format_into` feature
GuillaumeGomez Mar 28, 2026
5c95bf5
lower edition requirements for some async-closure test helpers
tshepang May 28, 2026
d6c42dd
move a section in a doc comment
WaffleLapkin Apr 24, 2026
4d69f79
document that `ManuallyDrop`'s `Box` interaction has been fixed
WaffleLapkin Apr 24, 2026
417015d
fixed: avoid reporting unreachable initializations for uninitialized …
mazam-97 Jun 5, 2026
6b0e5cf
Add test to check for normalize instead of evaluation for type constants
Shourya742 Jun 11, 2026
b1cc6b0
in case of type constant make sure to normalize
Shourya742 Jun 11, 2026
228c65e
update type_const_in_pattern test to include issue-156409
Shourya742 Jun 12, 2026
d1fadce
add const evaluation test which is too generic to evaluate
Shourya742 Jun 12, 2026
c1f6331
add suggestion for mgca to add assoc type
Kivooeo Jun 15, 2026
5afb1df
reword section about `ManuallyDrop` hazards
WaffleLapkin Jun 5, 2026
d31e98e
abi: scalable vector size incl. num vectors
davidtwco Jun 15, 2026
07d3384
target: no sret for scalable vectors
davidtwco Jun 15, 2026
021ee7c
add regression test for cfg_attr invalid predicate ICE
TaKO8Ki Jun 15, 2026
4349d1f
avoid requiring features for invalid cfg predicate diagnostics
TaKO8Ki Jun 15, 2026
e4ef990
mention in the tailcc error that it's supported on x86
WaffleLapkin Jun 15, 2026
6188ac6
mailmap: add mu001999
mu001999 Jun 15, 2026
43f6625
Update books
rustbot Jun 15, 2026
d297af4
remove LLVM `va_end` calls
folkertdev Jun 8, 2026
c4c61c0
Don't trim non-parenthesis spans in unused_parens for bounds
sanidhyasin Jun 10, 2026
04ba92b
Rollup merge of #152544 - GuillaumeGomez:stabilize-int_format_into, r…
jhpratt Jun 15, 2026
4020cba
Rollup merge of #157507 - mazam-97:fix-uninit-vs-possibly-uninitializ…
jhpratt Jun 15, 2026
17728da
Rollup merge of #155750 - WaffleLapkin:manually-drop-unbox, r=jhpratt
jhpratt Jun 15, 2026
0c01345
Rollup merge of #157075 - tshepang:lower-edition-requirement, r=wesle…
jhpratt Jun 15, 2026
fcfdcb8
Rollup merge of #157627 - folkertdev:remove-llvm-va_end, r=RalfJung
jhpratt Jun 15, 2026
2ad3bd4
Rollup merge of #157660 - Shourya742:2026-06-08-add-type-const-evalua…
jhpratt Jun 15, 2026
b35f383
Rollup merge of #157692 - sanidhyasin:fix-unused-parens-proc-macro-sp…
jhpratt Jun 15, 2026
8292a6b
Rollup merge of #157908 - Kivooeo:fix-mgca-assoc-sugg, r=fmease
jhpratt Jun 15, 2026
b005848
Rollup merge of #157915 - davidtwco:scalable-vector-size-w-num-vector…
jhpratt Jun 15, 2026
b7b1e4b
Rollup merge of #157916 - TaKO8Ki:fix-cfg-attr-invalid-predicate-ice,…
jhpratt Jun 15, 2026
ad55d52
Rollup merge of #157919 - WaffleLapkin:x86tc, r=folkertdev
jhpratt Jun 15, 2026
f5c9891
Rollup merge of #157920 - mu001999-contrib:mailmap, r=mu001999
jhpratt Jun 15, 2026
e1af1a0
Rollup merge of #157924 - rustbot:docs-update, r=ehuss
jhpratt Jun 15, 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
1 change: 1 addition & 0 deletions .mailmap
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,7 @@ Milan Landaverde <milanlandaverde@gmail.com>
mjptree <michael.prantl@hotmail.de>
Ms2ger <ms2ger@gmail.com> <Ms2ger@gmail.com>
msizanoen1 <qtmlabs@protonmail.com>
mu001999 <mu001999@outlook.com> <rcu@live.com>
Mukilan Thiagarajan <mukilanthiagarajan@gmail.com>
Nadrieril Feneanar <Nadrieril@users.noreply.github.com>
Nadrieril Feneanar <Nadrieril@users.noreply.github.com> <nadrieril+rust@gmail.com>
Expand Down
8 changes: 5 additions & 3 deletions compiler/rustc_abi/src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1498,19 +1498,21 @@ where
// Compute the size and alignment of the vector
let size =
elt.size.checked_mul(count, dl).ok_or_else(|| LayoutCalculatorError::SizeOverflow)?;
let (repr, align) = match kind {
let (repr, size, align) = match kind {
SimdVectorKind::Scalable(number_of_vectors) => (
BackendRepr::SimdScalableVector { element, count, number_of_vectors },
size.checked_mul(number_of_vectors.0 as u64, dl)
.ok_or_else(|| LayoutCalculatorError::SizeOverflow)?,
dl.llvmlike_vector_align(size),
),
// Non-power-of-two vectors have padding up to the next power-of-two.
// If we're a packed repr, remove the padding while keeping the alignment as close
// to a vector as possible.
SimdVectorKind::PackedFixed if !count.is_power_of_two() => {
(BackendRepr::Memory { sized: true }, Align::max_aligned_factor(size))
(BackendRepr::Memory { sized: true }, size, Align::max_aligned_factor(size))
}
SimdVectorKind::PackedFixed | SimdVectorKind::Fixed => {
(BackendRepr::SimdVector { element, count }, dl.llvmlike_vector_align(size))
(BackendRepr::SimdVector { element, count }, size, dl.llvmlike_vector_align(size))
}
};
let size = size.align_to(align);
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/cfg.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ pub fn parse_cfg_entry(
Some(sym::version) => parse_cfg_entry_version(cx, list, meta.span())?,
_ => {
let mut possibilities = vec![sym::any, sym::all, sym::not, sym::target];
if cx.features().cfg_version() {
if cx.features_option().is_some_and(Features::cfg_version) {
possibilities.push(sym::version);
}
return Err(cx.adcx().expected_specific_argument(meta.span(), &possibilities));
Expand Down
80 changes: 71 additions & 9 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ use rustc_hir::intravisit::{Visitor, walk_block, walk_expr};
use rustc_hir::{
CoroutineDesugaring, CoroutineKind, CoroutineSource, LangItem, PatField, find_attr,
};
use rustc_index::bit_set::DenseBitSet;
use rustc_middle::bug;
use rustc_middle::hir::nested_filter::OnlyBodies;
use rustc_middle::mir::{
Expand All @@ -28,7 +29,7 @@ use rustc_middle::ty::{
self, PredicateKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitor, Upcast,
suggest_constraining_type_params,
};
use rustc_mir_dataflow::move_paths::{InitKind, MoveOutIndex, MovePathIndex};
use rustc_mir_dataflow::move_paths::{Init, InitKind, InitLocation, MoveOutIndex, MovePathIndex};
use rustc_span::def_id::{DefId, LocalDefId};
use rustc_span::hygiene::DesugaringKind;
use rustc_span::{BytePos, ExpnKind, Ident, MacroKind, Span, Symbol, kw, sym};
Expand Down Expand Up @@ -110,6 +111,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
used_place,
moved_place,
desired_action,
location,
span,
use_spans,
);
Expand Down Expand Up @@ -769,12 +771,61 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}

/// Returns `true` if the given initialization can reach the error location.
///
/// This is used to determine whether an initialization should be considered
/// when reporting diagnostics at `err_location`.
///
/// The check proceeds in two stages:
///
/// 1. If the initialization originates from a function argument, it is
/// considered reachable by definition.
/// 2. If the initialization's basic block dominates the error block, then
/// every path to the error must pass through the initialization, so it is
/// reachable.
/// 3. Otherwise, perform a graph traversal over the MIR control-flow graph to
/// determine whether any path exists from the initialization block to the
/// error block.
///
/// The dominance check acts as a fast path for the common case, while the CFG
/// traversal handles cases where the initialization does not dominate the
/// error location but can still reach it through an alternate control-flow
/// path.
fn is_init_reachable(&self, init: &Init, err_location: mir::Location) -> bool {
let dominators = self.body.basic_blocks.dominators();
let init_block = match init.location {
InitLocation::Argument(_) => return true,
InitLocation::Statement(location) => location.block,
};
let err_block = err_location.block;
if dominators.dominates(init_block, err_block) {
return true;
}
// If init_block doesn't dominate error_block, check if there is any valid path from the
// initialization block to the error block in the Control Flow Graph.
let mut visited = DenseBitSet::new_empty(self.body.basic_blocks.len());
let mut stack = vec![init_block];
while let Some(block) = stack.pop() {
if block == err_block {
return true;
}
if visited.insert(block) {
let data = &self.body.basic_blocks[block];
for successor in data.terminator().successors() {
stack.push(successor);
}
}
}
false
}

fn report_use_of_uninitialized(
&self,
mpi: MovePathIndex,
used_place: PlaceRef<'tcx>,
moved_place: PlaceRef<'tcx>,
desired_action: InitializationRequiringAction,
location: Location,
span: Span,
use_spans: UseSpans<'tcx>,
) -> Diag<'infcx> {
Expand All @@ -783,15 +834,20 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let inits = &self.move_data.init_path_map[mpi];
let move_path = &self.move_data.move_paths[mpi];
let decl_span = self.body.local_decls[move_path.place.local].source_info.span;
let mut spans_set = FxIndexSet::default();
let mut all_init_spans_set = FxIndexSet::default();
let mut reachable_spans_set = FxIndexSet::default();
for init_idx in inits {
let init = &self.move_data.inits[*init_idx];
let span = init.span(self.body);
if !span.is_dummy() {
spans_set.insert(span);
all_init_spans_set.insert(span);
if self.is_init_reachable(init, location) {
reachable_spans_set.insert(span);
}
}
}
let spans: Vec<_> = spans_set.into_iter().collect();
let all_init_spans: Vec<_> = all_init_spans_set.into_iter().collect();
let reachable_spans: Vec<_> = reachable_spans_set.into_iter().collect();

let (name, desc) = match self.describe_place_with_options(
moved_place,
Expand All @@ -812,9 +868,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// for the branching codepaths that aren't covered, to point at them.
let tcx = self.infcx.tcx;
let body = tcx.hir_body_owned_by(self.mir_def_id());
let mut visitor = ConditionVisitor { tcx, spans, name, errors: vec![] };
let mut visitor =
ConditionVisitor { tcx, spans: all_init_spans.clone(), name, errors: vec![] };
visitor.visit_body(&body);
let spans = visitor.spans;

let mut show_assign_sugg = false;
let isnt_initialized = if let InitializationRequiringAction::PartialAssignment
Expand All @@ -824,7 +880,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
// that are *partially* initialized by assigning to a field of an uninitialized
// binding. We differentiate between them for more accurate wording here.
"isn't fully initialized"
} else if !spans.iter().any(|i| {
} else if !reachable_spans.iter().any(|i| {
// We filter these to avoid misleading wording in cases like the following,
// where `x` has an `init`, but it is in the same place we're looking at:
// ```
Expand All @@ -840,7 +896,13 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
.any(|sp| span < sp && !sp.contains(span))
}) {
show_assign_sugg = true;
"isn't initialized"
if all_init_spans.iter().any(|init_span| !init_span.contains(span))
&& reachable_spans.is_empty()
{
"isn't initialized on any path leading to this point"
} else {
"isn't initialized"
}
} else {
"is possibly-uninitialized"
};
Expand Down Expand Up @@ -887,7 +949,7 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}
}
if !shown {
for sp in &spans {
for sp in &reachable_spans {
if *sp < span && !sp.overlaps(span) {
err.span_label(*sp, "binding initialized here in some conditions");
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1512,7 +1512,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
}

// FIXME implement variadics in cranelift
sym::va_arg | sym::va_end => {
sym::va_arg => {
fx.tcx.dcx().span_fatal(
source_info.span,
"Defining variadic functions is not yet supported by Cranelift",
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_codegen_gcc/src/intrinsic/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -705,10 +705,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc
unimplemented!();
}

fn va_end(&mut self, _va_list: RValue<'gcc>) {
// FIXME(antoyo): implement.
}

fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo<Self::Value>) -> Self::Value {
unimplemented!()
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_codegen_llvm/src/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -725,7 +725,7 @@ pub(crate) fn to_llvm_calling_convention(sess: &Session, abi: CanonAbi) -> llvm:
},
CanonAbi::RustTail => match &sess.target.arch {
Arch::X86 | Arch::X86_64 | Arch::AArch64 => llvm::Tail,
_ => sess.dcx().fatal("extern \"tail\" is only supported on x86_64 and aarch64"),
_ => sess.dcx().fatal("extern \"tail\" is only supported on x86, x86_64 and aarch64"),
},
// Functions with this calling convention can only be called from assembly, but it is
// possible to declare an `extern "custom"` block, so the backend still needs a calling
Expand Down
4 changes: 0 additions & 4 deletions compiler/rustc_codegen_llvm/src/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1070,10 +1070,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
self.call_intrinsic("llvm.va_start", &[self.val_ty(va_list)], &[va_list]);
}

fn va_end(&mut self, va_list: &'ll Value) {
self.call_intrinsic("llvm.va_end", &[self.val_ty(va_list)], &[va_list]);
}

fn retag_reg(&mut self, ptr: Self::Value, info: &RetagInfo<Self::Value>) -> Self::Value {
codegen_retag_inner(self, "__rust_retag_reg", ptr, info)
}
Expand Down
8 changes: 6 additions & 2 deletions compiler/rustc_codegen_ssa/src/mir/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -525,13 +525,17 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
}

fn codegen_return_terminator(&mut self, bx: &mut Bx) {
// Call `va_end` if this is the definition of a C-variadic function.
// Explicitly end the lifetime of the VaList if this function is c-variadic. We explicitly
// start the lifetime when desugaring `...`. Ending the lifetime meaningfully improves
// codegen.
if self.fn_abi.c_variadic {
// The `VaList` "spoofed" argument is just after all the real arguments.
let va_list_arg_idx = self.fn_abi.args.len();
match self.locals[mir::Local::arg(va_list_arg_idx)] {
LocalRef::Place(va_list) => {
bx.va_end(va_list.val.llval);
// NOTE: we don't actually call LLVM's va_end here. We know it's a no-op for
// all current targets and hence don't bother
// (as permitted by https://llvm.org/docs/LangRef.html#llvm-va-end-intrinsic).

// Explicitly end the lifetime of the `va_list`, improves LLVM codegen.
bx.lifetime_end(va_list.val.llval, va_list.layout.size);
Expand Down
3 changes: 0 additions & 3 deletions compiler/rustc_codegen_ssa/src/traits/intrinsic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -52,9 +52,6 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
/// Trait method used to inject `va_start` on the "spoofed" `VaList` in
/// Rust defined C-variadic functions.
fn va_start(&mut self, val: Self::Value);
/// Trait method used to inject `va_end` on the "spoofed" `VaList` before
/// Rust defined C-variadic functions return.
fn va_end(&mut self, val: Self::Value);
/// Trait method used to retag a pointer stored within a place.
fn retag_mem(&mut self, place: Self::Value, info: &RetagInfo<Self::Value>);
/// Trait method used to retag a pointer that has been loaded into a register.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::iter;

use GenericArgsInfo::*;
use rustc_errors::codes::*;
use rustc_errors::{Applicability, Diag, Diagnostic, EmissionGuarantee, MultiSpan, pluralize};
use rustc_hir as hir;
use rustc_middle::ty::{self as ty, AssocItems, TyCtxt};
use rustc_middle::ty::{self as ty, AssocItem, AssocItems, TyCtxt};
use rustc_span::def_id::DefId;
use tracing::debug;

Expand Down Expand Up @@ -485,21 +483,20 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
.collect()
}

fn get_unbound_associated_types(&self) -> Vec<String> {
fn get_unbound_associated_item(&self) -> Vec<&AssocItem> {
if self.tcx.is_trait(self.def_id) {
let items: &AssocItems = self.tcx.associated_items(self.def_id);
items
.in_definition_order()
.filter(|item| {
item.is_type()
(item.is_type() || item.is_type_const())
&& !item.is_impl_trait_in_trait()
&& !self
.gen_args
.constraints
.iter()
.any(|constraint| constraint.ident.name == item.name())
})
.map(|item| self.tcx.item_ident(item.def_id).to_string())
.collect()
} else {
Vec::default()
Expand Down Expand Up @@ -905,7 +902,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_, impl EmissionGuarantee>) {
let num_provided_lt_args = self.num_provided_lifetime_args();
let num_provided_type_const_args = self.num_provided_type_or_const_args();
let unbound_types = self.get_unbound_associated_types();
let unbound_assoc_items = self.get_unbound_associated_item();
let num_provided_args = num_provided_lt_args + num_provided_type_const_args;
assert!(num_provided_args > 0);

Expand All @@ -917,8 +914,6 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
let redundant_type_or_const_args = num_redundant_type_or_const_args > 0;

let remove_entire_generics = num_redundant_args >= self.gen_args.args.len();
let provided_args_matches_unbound_traits =
unbound_types.len() == num_redundant_type_or_const_args;

let remove_lifetime_args = |err: &mut Diag<'_, _>| {
let mut lt_arg_spans = Vec::new();
Expand Down Expand Up @@ -1012,24 +1007,41 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> {
);
};

// If there is a single unbound associated type and a single excess generic param
// suggest replacing the generic param with the associated type bound
if provided_args_matches_unbound_traits && !unbound_types.is_empty() {
// If there is an identical amount of unbound associated items and excess generic args
// suggest turning the generic args into associated item bindings
if unbound_assoc_items.len() == num_redundant_type_or_const_args
&& !unbound_assoc_items.is_empty()
{
// Don't suggest if we're in a trait impl as
// that would result in invalid syntax (fixes #116464)
if !self.is_in_trait_impl() {
let unused_generics = &self.gen_args.args[self.num_expected_type_or_const_args()..];
let suggestions = iter::zip(unused_generics, &unbound_types)
.map(|(potential, name)| {
(potential.span().shrink_to_lo(), format!("{name} = "))
let mut unbound_assoc_consts =
unbound_assoc_items.iter().filter(|item| item.is_type_const());
let mut unbound_assoc_types =
unbound_assoc_items.iter().filter(|item| item.is_type());
let suggestions = unused_generics
.iter()
.filter_map(|potential| {
let item = match potential {
hir::GenericArg::Const(_) => unbound_assoc_consts.next(),
hir::GenericArg::Type(_) => unbound_assoc_types.next(),
_ => None,
}?;
Some((
potential.span().shrink_to_lo(),
// FIXME: This doesn't account for generic associated items
format!("{} = ", self.tcx.item_ident(item.def_id)),
))
})
.collect::<Vec<_>>();

if !suggestions.is_empty() {
let s = pluralize!(suggestions.len());
let article = if suggestions.len() == 1 { "an " } else { "" };
err.multipart_suggestion(
format!(
"replace the generic bound{s} with the associated type{s}",
s = pluralize!(unbound_types.len())
"turn the generic argument{s} into {article}associated item binding{s}"
),
suggestions,
Applicability::MaybeIncorrect,
Expand Down
Loading
Loading