Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
7c96471
perf: Make stable_crate_ids reads lock-free after crate loading
xmakro Jun 20, 2026
b429456
Move some methods that only need the region context onto that
oli-obk Jun 23, 2026
7ebb859
Consistently taint root cx
oli-obk Jun 24, 2026
f44093d
Remove some unnecessary mutabilities
oli-obk Jun 24, 2026
7102a6c
Typeck children always have the same param env as their parent
oli-obk Jun 24, 2026
7cb94f0
Don't compute opaque types for typeck children. They are always the s…
oli-obk Jun 24, 2026
7ccc34f
Add a convenience helper for doing type ops
oli-obk Jun 24, 2026
b2a46c9
Move `check_ffi_pure` into the attribute parser
obeis Jun 24, 2026
c19c462
Use `NoArgsAttributeParser` for parsing `#[ffi_pure]`
obeis Jun 24, 2026
0d2070c
Add safety section for SliceIndex::get_unchecked(mut)
yilin0518 Jun 25, 2026
ba2c9ba
std: truncate thread names on NetBSD
joboet Jun 25, 2026
5ba35ba
Eliminate double length check in `Vec::into_array`
Jun 25, 2026
b6a4c3a
Suggest `>=` for `=>` typo in closure and call argument positions
ChronoCoders Jun 24, 2026
6b9de05
Attribute docs `deprecated` , `warn`, `allow`, `cfg`, `deny`, and `fo…
kantnero Jun 26, 2026
9b188dd
cg_LLVM: Stop needing an alloca for volatile loads
scottmcm May 23, 2026
6d6fcc9
add regression test for clone suggestion empty obligations
TaKO8Ki Jun 26, 2026
f08762c
guard clone suggestion against empty obligation errors
TaKO8Ki Jun 26, 2026
c200d2f
fixup the refactoring errors in 156246
jdonszelmann Jun 24, 2026
6c52a70
Limit splat AST and FnDecl to 255 args
teor2345 Jun 22, 2026
5d0c6ba
Impl HIR FnSig for #[splat]
teor2345 Jun 10, 2026
e0a35a0
Impl HIR typeck for #[splat]
teor2345 Jun 10, 2026
472c197
Remove a leftover direct call to fn_ctxt.label_generic_mismatches
teor2345 Jun 5, 2026
50c5d85
Fix ICE in `label_fn_like` when splatted arg index is out of bounds
Ajay-singh1 Jun 3, 2026
9e48cd9
Impl MIR lowering side-tables for #[splat]
teor2345 Jun 12, 2026
2bb9dab
Impl actual MIR lowering for #[splat]
teor2345 Jun 12, 2026
50c658c
Impl TypeInfo for splat
teor2345 Mar 11, 2026
dc3889a
Add UI tests for `#[splat]` unhappy path, generics, fn colors
Ajay-singh1 Jun 3, 2026
633b89b
Add failing test for #[splat] with dyn AsRef<T> where T: Tuple
Ajay-singh1 Jun 22, 2026
3173c8b
Add splat UI tests for 255 splatted arg limit
teor2345 Jun 22, 2026
18185d0
UI test arg diffs greater than u8::MAX
teor2345 Jun 23, 2026
4d9ae09
Fix output normtn in splat-fn-ptr-tuple.rs
teor2345 Jun 26, 2026
5d41c45
Update Enzyme submodule
ZuseZ4 Jun 26, 2026
b049d2b
make use of rigidness marker in fast_reject
adwinwhite Jun 24, 2026
8b90f5c
Remove `FIXME` comment that is not needed anymore
GuillaumeGomez Jun 26, 2026
eb78d13
Replace `ilog(10)` with `ilog10()`
GuillaumeGomez Jun 26, 2026
69ffb8e
Rollup merge of #153697 - teor2345:fn-arg-splat-experiment, r=oli-obk
JonathanBrouwer Jun 26, 2026
64f56e7
Rollup merge of #158360 - oli-obk:borrowck-cleanups, r=lcnr
JonathanBrouwer Jun 26, 2026
8002964
Rollup merge of #158438 - adwinwhite:deep-reject, r=lcnr
JonathanBrouwer Jun 26, 2026
6fddd30
Rollup merge of #157127 - scottmcm:tweak-layout-of-alternative, r=nikic
JonathanBrouwer Jun 26, 2026
f5c2bd7
Rollup merge of #158376 - ChronoCoders:diag-eq-gt-closure-arg, r=chen…
JonathanBrouwer Jun 26, 2026
4631799
Rollup merge of #158185 - xmakro:perf/stable-crate-ids-lockfree, r=mu…
JonathanBrouwer Jun 26, 2026
8ee4336
Rollup merge of #158244 - kantnero:attribute-docs-deprecated-warn, r=…
JonathanBrouwer Jun 26, 2026
2ba8845
Rollup merge of #158355 - jdonszelmann:fixuop, r=lcnr
JonathanBrouwer Jun 26, 2026
a922cbc
Rollup merge of #158361 - obeis:move-check-ffi-pure, r=JonathanBrouwer
JonathanBrouwer Jun 26, 2026
d940e7e
Rollup merge of #158382 - yilin0518:fix_slice_index, r=clarfonthey
JonathanBrouwer Jun 26, 2026
f95bd0c
Rollup merge of #158399 - joboet:netbsd_threadname_truncate, r=jhpratt
JonathanBrouwer Jun 26, 2026
985d304
Rollup merge of #158418 - viliml:vec_into_array_unwrap_unchecked, r=D…
JonathanBrouwer Jun 26, 2026
7aa21c1
Rollup merge of #158430 - TaKO8Ki:fix-clone-suggestion-empty-obligati…
JonathanBrouwer Jun 26, 2026
f271ee6
Rollup merge of #158446 - ZuseZ4:main, r=oli-obk
JonathanBrouwer Jun 26, 2026
2ea8268
Rollup merge of #158448 - GuillaumeGomez:cleanup-numbuffer, r=Amanieu
JonathanBrouwer Jun 26, 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
10 changes: 6 additions & 4 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3059,21 +3059,23 @@ impl FnDecl {
}

/// The marker index for "no splatted arguments".
/// Higher values are also not supported, for performance reasons.
///
/// Must have the same value as `FnSigKind::NO_SPLATTED_ARG_INDEX` and `FnDeclFlags::NO_SPLATTED_ARG_INDEX`.
pub const NO_SPLATTED_ARG_INDEX: u16 = u16::MAX;
pub const NO_SPLATTED_ARG_INDEX: u8 = u8::MAX;

/// Returns a splatted argument index, if any are present.
pub fn splatted(&self) -> Option<u16> {
pub fn splatted(&self) -> Option<u8> {
self.inputs.iter().enumerate().find_map(|(index, arg)| {
if index == Self::NO_SPLATTED_ARG_INDEX as usize {
if index >= usize::from(Self::NO_SPLATTED_ARG_INDEX) {
// AST validation has already checked the splatted argument index is valid, so just
// ignore invalid indexes here.
None
} else {
arg.attrs
.iter()
.any(|attr| attr.has_name(sym::splat))
.then_some(u16::try_from(index).unwrap())
.then_some(u8::try_from(index).unwrap())
}
})
}
Expand Down
5 changes: 2 additions & 3 deletions compiler/rustc_ast_lowering/src/delegation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ struct ParamInfo {
pub c_variadic: bool,

/// The index of the splatted parameter, if any.
pub splatted: Option<u16>,
pub splatted: Option<u8>,
}

const PARENT_ID: hir::ItemLocalId = hir::ItemLocalId::ZERO;
Expand Down Expand Up @@ -364,11 +364,10 @@ impl<'hir> LoweringContext<'_, 'hir> {
fn param_info(&self, def_id: DefId) -> ParamInfo {
let sig = self.tcx.fn_sig(def_id).skip_binder().skip_binder();

// FIXME(splat): use `sig.splatted()` once FnSig has it
ParamInfo {
param_count: sig.inputs().len() + usize::from(sig.c_variadic()),
c_variadic: sig.c_variadic(),
splatted: None,
splatted: sig.splatted(),
}
}

Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -412,11 +412,11 @@ impl<'a> AstValidator<'a> {
})
.unzip();

// A splatted argument at the "no splatted" marker index is not supported (this is an
// unlikely edge case).
// A splatted argument greater than or equal to the "no splatted" marker index is not
// supported.
if let (Some(&splatted_arg_index), Some(&splatted_span)) =
(splatted_arg_indexes.last(), splatted_spans.last())
&& splatted_arg_index == FnDecl::NO_SPLATTED_ARG_INDEX
&& splatted_arg_index >= u16::from(FnDecl::NO_SPLATTED_ARG_INDEX)
{
self.dcx().emit_err(diagnostics::InvalidSplattedArg {
splatted_arg_index,
Expand Down
17 changes: 12 additions & 5 deletions compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@ use super::util::parse_single_integer;
use crate::attributes::AttributeSafety;
use crate::attributes::cfg::parse_cfg_entry;
use crate::session_diagnostics::{
AsNeededCompatibility, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic,
ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, InvalidLinkModifier,
InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, LinkOrdinalOutOfRange,
LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection, RawDylibOnlyWindows,
WholeArchiveNeedsStatic,
AsNeededCompatibility, BothFfiConstAndPure, BundleNeedsStatic, EmptyLinkName,
ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink,
InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple,
LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection,
RawDylibOnlyWindows, WholeArchiveNeedsStatic,
};

pub(crate) struct LinkNameParser;
Expand Down Expand Up @@ -575,6 +575,13 @@ impl NoArgsAttributeParser for FfiPureParser {
AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);
const STABILITY: AttributeStability = unstable!(ffi_pure);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;

fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) {
// `#[ffi_const]` functions cannot be `#[ffi_pure]`.
if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) {
cx.emit_err(BothFfiConstAndPure { attr_span });
}
}
}

pub(crate) struct RustcStdInternalSymbolParser;
Expand Down
26 changes: 24 additions & 2 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,14 @@ pub(crate) trait SingleAttributeParser: 'static {

/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind>;

/// Optional cross-attribute validation, run once during finalization after all
/// attributes on the item have been parsed. Unlike [`convert`](Self::convert), this
/// has access to the sibling attributes via [`FinalizeContext::all_attrs`], so it can
/// reject incompatible combinations. `attr_span` is the span of this attribute.
///
/// Defaults to a no-op.
fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {}
}

/// Use in combination with [`SingleAttributeParser`].
Expand Down Expand Up @@ -177,8 +185,10 @@ impl<T: SingleAttributeParser> AttributeParser for Single<T> {
const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS;
const SAFETY: AttributeSafety = T::SAFETY;

fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
Some(self.1?.0)
fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
let (kind, span) = self.1?;
T::finalize_check(span, cx);
Some(kind)
}
}

Expand Down Expand Up @@ -258,6 +268,14 @@ pub(crate) trait NoArgsAttributeParser: 'static {

/// Create the [`AttributeKind`] given attribute's [`Span`].
const CREATE: fn(Span) -> AttributeKind;

/// Optional cross-attribute validation, run once during finalization after all
/// attributes on the item have been parsed. Has access to the sibling attributes via
/// [`FinalizeContext::all_attrs`], so it can reject incompatible combinations.
/// `attr_span` is the span of this attribute.
///
/// Defaults to a no-op.
fn finalize_check(_attr_span: Span, _cx: &FinalizeContext<'_, '_>) {}
}

pub(crate) struct WithoutArgs<T: NoArgsAttributeParser>(PhantomData<T>);
Expand All @@ -280,6 +298,10 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> {
let _ = cx.expect_no_args(args);
Some(T::CREATE(cx.attr_span))
}

fn finalize_check(attr_span: Span, cx: &FinalizeContext<'_, '_>) {
T::finalize_check(attr_span, cx)
}
}

type ConvertFn<E> = fn(ThinVec<E>, Span) -> AttributeKind;
Expand Down
7 changes: 7 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,13 @@ use rustc_target::spec::TargetTuple;
use crate::AttributeTemplate;
use crate::context::Suggestion;

#[derive(Diagnostic)]
#[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)]
pub(crate) struct BothFfiConstAndPure {
#[primary_span]
pub attr_span: Span,
}

#[derive(Diagnostic)]
#[diag("{$attr_str} attribute cannot have empty value")]
pub(crate) struct DocAliasEmpty<'a> {
Expand Down
22 changes: 13 additions & 9 deletions compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1461,15 +1461,19 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
let cause = ObligationCause::misc(expr.span, self.mir_def_id());
ocx.register_bound(cause, self.infcx.param_env, ty, clone_trait);
let errors = ocx.evaluate_obligations_error_on_ambiguity();
if errors.iter().all(|error| {
match error.obligation.predicate.as_clause().and_then(|c| c.as_trait_clause()) {
Some(clause) => match clause.self_ty().skip_binder().kind() {
ty::Adt(def, _) => def.did().is_local() && clause.def_id() == clone_trait,
_ => false,
},
None => false,
}
}) {
if !errors.is_empty()
&& errors.iter().all(|error| {
match error.obligation.predicate.as_clause().and_then(|c| c.as_trait_clause()) {
Some(clause) => match clause.self_ty().skip_binder().kind() {
ty::Adt(def, _) => {
def.did().is_local() && clause.def_id() == clone_trait
}
_ => false,
},
None => false,
}
})
{
let mut type_spans = vec![];
let mut types = FxIndexSet::default();
for clause in errors
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs
Original file line number Diff line number Diff line change
Expand Up @@ -706,7 +706,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> {
Some(Cause::LiveVar(..) | Cause::DropVar(..)) | None => {
// Here, under NLL: no cause was found. Under polonius: no cause was found, or a
// boring local was found, which we ignore like NLLs do to match its diagnostics.
if let Some(region) = self.to_error_region_vid(borrow_region_vid) {
if let Some(region) = self.regioncx.to_error_region_vid(borrow_region_vid) {
let (category, from_closure, span, region_name, path) =
self.free_region_constraint_info(borrow_region_vid, region);
if let Some(region_name) = region_name {
Expand Down
61 changes: 32 additions & 29 deletions compiler/rustc_borrowck/src/diagnostics/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -116,11 +116,42 @@ impl<'infcx, 'tcx> BorrowckDiagnosticsBuffer<'infcx, 'tcx> {
pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
self.buffered_diags.push(BufferedDiag::NonError(diag));
}
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
self.buffered_diags.push(BufferedDiag::Error(diag));
}

pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
let mut res = None;

// Buffer any move errors that we collected and de-duplicated.
for (_, (_, diag)) in std::mem::take(&mut self.buffered_move_errors) {
// We have already set tainted for this error, so just buffer it.
self.buffer_error(diag);
}
for (_, (mut diag, count)) in std::mem::take(&mut self.buffered_mut_errors) {
if count > 10 {
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
}
self.buffer_error(diag);
}

if !self.buffered_diags.is_empty() {
self.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
for buffered_diag in self.buffered_diags.drain(..) {
match buffered_diag {
BufferedDiag::Error(diag) => res = Some(diag.emit()),
BufferedDiag::NonError(diag) => diag.emit(),
}
}
}

res
}
}

impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
pub(crate) fn buffer_error(&mut self, diag: Diag<'infcx>) {
self.diags_buffer.buffered_diags.push(BufferedDiag::Error(diag));
self.diags_buffer.buffer_error(diag);
}

pub(crate) fn buffer_non_error(&mut self, diag: Diag<'infcx, ()>) {
Expand Down Expand Up @@ -152,34 +183,6 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
self.diags_buffer.buffered_mut_errors.insert(span, (diag, count));
}

pub(crate) fn emit_errors(&mut self) -> Option<ErrorGuaranteed> {
let mut res = self.infcx.tainted_by_errors();

// Buffer any move errors that we collected and de-duplicated.
for (_, (_, diag)) in std::mem::take(&mut self.diags_buffer.buffered_move_errors) {
// We have already set tainted for this error, so just buffer it.
self.buffer_error(diag);
}
for (_, (mut diag, count)) in std::mem::take(&mut self.diags_buffer.buffered_mut_errors) {
if count > 10 {
diag.note(format!("...and {} other attempted mutable borrows", count - 10));
}
self.buffer_error(diag);
}

if !self.diags_buffer.buffered_diags.is_empty() {
self.diags_buffer.buffered_diags.sort_by_key(|buffered_diag| buffered_diag.sort_span());
for buffered_diag in self.diags_buffer.buffered_diags.drain(..) {
match buffered_diag {
BufferedDiag::Error(diag) => res = Some(diag.emit()),
BufferedDiag::NonError(diag) => diag.emit(),
}
}
}

res
}

pub(crate) fn has_buffered_diags(&self) -> bool {
self.diags_buffer.buffered_diags.is_empty()
}
Expand Down
8 changes: 2 additions & 6 deletions compiler/rustc_borrowck/src/diagnostics/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,10 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
}

let infcx = self.infcx;
let mut guar = None;
let mut last_unexpected_hidden_region: Option<(Span, Ty<'_>, ty::OpaqueTypeKey<'tcx>)> =
None;
for error in errors {
guar = Some(match error {
match error {
DeferredOpaqueTypeError::InvalidOpaqueTypeArgs(err) => err.report(infcx),
DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam(err) => {
infcx.dcx().emit_err(err)
Expand Down Expand Up @@ -82,11 +81,8 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> {
)
),
),
});
};
}
let guar = guar.unwrap();
self.root_cx.set_tainted_by_errors(guar);
self.infcx.set_tainted_by_errors(guar);
}

/// Try to note when an opaque is involved in a borrowck error and that
Expand Down
Loading
Loading