Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
47 commits
Select commit Hold shift + click to select a range
eb7cb89
implement our own `ulps` check to test `f16`
folkertdev Apr 12, 2026
f40da91
disable `f16` tests when not `target_has_reliable_f16_math`
folkertdev Apr 16, 2026
c4f3110
Fix pointer API to match what was stabilized
calebzulawski May 8, 2026
94a3ba2
Merge pull request #526 from rust-lang/update-pointer-api
calebzulawski May 9, 2026
beafe83
Optimize `swizzle_dyn` for AArch64 with N > 16
Kmeakin May 28, 2026
be090a7
Merge pull request #528 from Kmeakin/km/aarch64-dyn-swizzle
calebzulawski May 30, 2026
b16ee62
Provide `From` impls for AArch64 ACLE tuple types.
Kmeakin May 31, 2026
61ae55e
Use `impl` restrictions over hand-sealed traits
jhpratt May 30, 2026
ae33abe
Add `Mask::last_set` method
Kmeakin Jun 19, 2026
a27ae1d
Merge pull request #532 from Kmeakin/km/simd-last-set
calebzulawski Jun 20, 2026
8e3bfb0
Merge pull request #530 from Kmeakin/km/aarch64-tuple-from-impls
calebzulawski Jun 20, 2026
d7a525f
Merge pull request #529 from jhpratt/master
calebzulawski Jun 20, 2026
30bdfe3
Optimize `swizzle_dyn` for LoongArch64 with N is 16 or 32
heiher Jun 19, 2026
44a03e6
Merge pull request #533 from heiher/swizzle-dyn-loong64
calebzulawski Jun 23, 2026
5b7c840
Merge pull request #518 from folkertdev/test-float-f16
programmerjake Jul 3, 2026
7d497cc
Merge of rust-lang/portable-simd#520: disable `f16` tests for the cra…
workingjubilee Jul 3, 2026
8a07fcc
fix base_urls with periods
uselessgoddess Jul 18, 2026
e46cf87
Extract coroutine_closure_output_coroutine.
cjgillot May 31, 2026
2a4115d
Extract pretty_print_closure_inner.
cjgillot Jun 1, 2026
b010737
Merge commit '7d497cca160ae6062acc1a2db838667f83c0b58e' into sync-fro…
folkertdev Jul 19, 2026
f6d8df8
Move `std::io::buffered` to `alloc::io`
bushrat011899 May 12, 2026
f415df6
Reduce API surface of `Buffer`
bushrat011899 May 25, 2026
4af788e
Reduce API surface of `alloc::io::util`
bushrat011899 Jul 19, 2026
4f8a2a9
Reduce API surface of `alloc::io::read`
bushrat011899 Jul 19, 2026
44d9de2
Reduce API surface of `alloc::io` reexports from `core::io`
bushrat011899 Jul 19, 2026
f012e40
Use `String::try_push_str` instead of `unsafe` code
bushrat011899 Jul 20, 2026
295f7f4
Use `Vec::<u8>::try_extend_from_slice_of_bytes` instead of `unsafe` code
bushrat011899 Jul 20, 2026
3739d04
Make `Buffer` private
bushrat011899 Jul 20, 2026
69b3806
Standardize on `pub(super)` instead of `pub(in crate::io)`
bushrat011899 Jul 20, 2026
e09b887
fix feature gate
folkertdev Jul 20, 2026
b045903
remove now-dead `Sealed` trait
folkertdev Jul 20, 2026
7629861
fix simd tests that use `without_provenance{_mut}`
folkertdev Jul 20, 2026
9d38fe5
Add `inline` to new `BufReader` method
bushrat011899 Jul 20, 2026
6ef1cf3
Add `inline` to new `BufWriter` method
bushrat011899 Jul 20, 2026
f32f69b
disable `portable_simd` miri test that needs additional intrinsic sup…
folkertdev Jul 20, 2026
9204d14
ergonomic_clones_dotuse_capture_by_ref: Capture upvar by ref for `.us…
Dnreikronos Jul 20, 2026
192ce21
Make parsed attributes available in `finalize_check`
obeis Jun 28, 2026
d2777f4
Move `check_rustc_pub_transparent` into attribute parser
obeis Jun 28, 2026
02076ac
Add `FinalizeCheckContext` for attribute parser
obeis Jul 10, 2026
8c6aba0
Set the rustc lib path for unstable-book-gen
cuviper Jul 20, 2026
270fbc9
Rollup merge of #159582 - folkertdev:sync-from-portable-simd-2026-07-…
JonathanBrouwer Jul 20, 2026
95e4102
Rollup merge of #157270 - Dnreikronos:ergonomic_clones_dotuse_capture…
JonathanBrouwer Jul 20, 2026
b98f109
Rollup merge of #158496 - obeis:move-check-rustc-pub-transparen, r=Jo…
JonathanBrouwer Jul 20, 2026
5fad13a
Rollup merge of #158547 - bushrat011899:alloc_io_buffered, r=clarfonthey
JonathanBrouwer Jul 20, 2026
a4b0989
Rollup merge of #159505 - uselessgoddess:fix/issue-159480, r=lolbinar…
JonathanBrouwer Jul 20, 2026
c4bcdfa
Rollup merge of #159578 - cjgillot:coroutine-refactor, r=oli-obk
JonathanBrouwer Jul 20, 2026
158d2b6
Rollup merge of #159613 - cuviper:unstable-book-rpath, r=clubby789
JonathanBrouwer Jul 20, 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
Original file line number Diff line number Diff line change
Expand Up @@ -541,7 +541,7 @@ impl CombineAttributeParser for TargetFeatureParser {
parse_tf_attribute(cx, args)
}

fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
// `#[target_feature]` is incompatible with lang item functions,
// except on WASM where calling target-feature functions is safe (see #84988).
if !cx.sess().target.is_like_wasm && !cx.sess().opts.actually_rustdoc {
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/link_attrs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -576,7 +576,7 @@ impl NoArgsAttributeParser for FfiPureParser {
const STABILITY: AttributeStability = unstable!(ffi_pure);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure;

fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
// `#[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 });
Expand Down
14 changes: 14 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use rustc_feature::AttributeStability;
use rustc_hir::attrs::ReprAttr;
use rustc_hir::find_attr;

use super::prelude::*;
use crate::session_diagnostics::RustcPubTransparent;

pub(crate) struct RustcAsPtrParser;
impl NoArgsAttributeParser for RustcAsPtrParser {
Expand All @@ -26,6 +29,17 @@ impl NoArgsAttributeParser for RustcPubTransparentParser {
]);
const STABILITY: AttributeStability = unstable!(rustc_attrs);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent;

fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
// `#[rustc_pub_transparent]` may only be applied to `#[repr(transparent)]` types.
let is_transparent = find_attr!(
cx.parsed_attrs,
Repr { reprs, .. } if reprs.iter().any(|(r, _)| r == &ReprAttr::ReprTransparent)
);
if !is_transparent {
cx.emit_err(RustcPubTransparent { span: cx.target_span, attr_span });
}
}
}

pub(crate) struct RustcPassByValueParser;
Expand Down
71 changes: 46 additions & 25 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use rustc_span::edition::Edition;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;

use crate::context::{AcceptContext, FinalizeContext};
use crate::context::{AcceptContext, FinalizeCheckContext, FinalizeCheckFn, FinalizeContext};
use crate::parser::ArgParser;
use crate::session_diagnostics::UnusedMultiple;
use crate::target_checking::AllowedTargets;
Expand Down Expand Up @@ -117,6 +117,20 @@ pub(crate) trait AttributeParser: Default + 'static {
/// every single syntax item that could have attributes applied to it.
/// Your accept mappings should determine whether this returns something.
fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind>;

/// If this parser produced an attribute, optionally returns a cross-attribute check
/// to run once *all* attributes on the item have been finalized, together with the
/// span it should be reported at.
///
/// Running after finalization means the check can inspect the fully parsed attributes
/// via [`FinalizeCheckContext::parsed_attrs`], which are not yet all available during
/// [`finalize`](Self::finalize). This is queried right before `finalize` consumes the
/// parser state.
///
/// Defaults to no check.
fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> {
None
}
}

/// Alternative to [`AttributeParser`] that automatically handles state management.
Expand Down Expand Up @@ -148,13 +162,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.
/// Optional cross-attribute validation, run once *after* all attributes on the item
/// have been finalized. Unlike [`convert`](Self::convert), this has access to the
/// sibling attributes via [`FinalizeCheckContext::all_attrs`] and the fully parsed
/// attributes via [`FinalizeCheckContext::parsed_attrs`], so it can reject incompatible
/// combinations. `attr_span` is the span of this attribute.
///
/// Defaults to a no-op.
fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
}

/// Use in combination with [`SingleAttributeParser`].
Expand Down Expand Up @@ -185,11 +200,15 @@ 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> {
let (kind, span) = self.1?;
T::finalize_check(cx, span);
fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
let (kind, _span) = self.1?;
Some(kind)
}

fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> {
let (_, span) = self.1.as_ref()?;
Some((<T as SingleAttributeParser>::finalize_check, *span))
}
}

pub(crate) enum OnDuplicate {
Expand Down Expand Up @@ -269,13 +288,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.
/// Optional cross-attribute validation, run once *after* all attributes on the item
/// have been finalized. Has access to the sibling attributes via
/// [`FinalizeCheckContext::all_attrs`] and the fully parsed attributes via
/// [`FinalizeCheckContext::parsed_attrs`], so it can reject incompatible combinations.
/// `attr_span` is the span of this attribute.
///
/// Defaults to a no-op.
fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
}

pub(crate) struct WithoutArgs<T: NoArgsAttributeParser>(PhantomData<T>);
Expand All @@ -299,7 +319,7 @@ impl<T: NoArgsAttributeParser> SingleAttributeParser for WithoutArgs<T> {
Some(T::CREATE(cx.attr_span))
}

fn finalize_check(cx: &FinalizeContext<'_, '_>, attr_span: Span) {
fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
T::finalize_check(cx, attr_span)
}
}
Expand Down Expand Up @@ -336,13 +356,14 @@ pub(crate) trait CombineAttributeParser: 'static {
args: &ArgParser,
) -> impl IntoIterator<Item = Self::Item>;

/// 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.
/// Optional cross-attribute validation, run once *after* all attributes on the item
/// have been finalized. Has access to the sibling attributes via
/// [`FinalizeCheckContext::all_attrs`] and the fully parsed attributes via
/// [`FinalizeCheckContext::parsed_attrs`], so it can reject incompatible combinations.
/// `attr_span` is the span of the first attribute that was encountered.
///
/// Defaults to a no-op.
fn finalize_check(_cx: &FinalizeContext<'_, '_>, _attr_span: Span) {}
fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {}
}

/// Use in combination with [`CombineAttributeParser`].
Expand Down Expand Up @@ -375,12 +396,12 @@ impl<T: CombineAttributeParser> AttributeParser for Combine<T> {
const ALLOWED_TARGETS: AllowedTargets<'_> = T::ALLOWED_TARGETS;
const SAFETY: AttributeSafety = T::SAFETY;

fn finalize(self, cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
if let Some(first_span) = self.first_span {
T::finalize_check(cx, first_span);
Some(T::CONVERT(self.items, first_span))
} else {
None
}
fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
let first_span = self.first_span?;
Some(T::CONVERT(self.items, first_span))
}

fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> {
Some((<T as CombineAttributeParser>::finalize_check, self.first_span?))
}
}
2 changes: 1 addition & 1 deletion compiler/rustc_attr_parsing/src/attributes/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ pub(super) use crate::attributes::{
};
// contexts
#[doc(hidden)]
pub(super) use crate::context::{AcceptContext, FinalizeContext};
pub(super) use crate::context::{AcceptContext, FinalizeCheckContext, FinalizeContext};
#[doc(hidden)]
pub(super) use crate::parser::*;
// target checking
Expand Down
63 changes: 60 additions & 3 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,8 @@ use rustc_ast::{AttrStyle, MetaItemLit, Safety};
use rustc_data_structures::sync::{DynSend, DynSync};
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};
use rustc_feature::AttributeStability;
use rustc_hir::AttrPath;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{AttrPath, Attribute};
use rustc_parse::parser::Recovery;
use rustc_session::Session;
use rustc_session::lint::{Lint, LintId};
Expand Down Expand Up @@ -94,7 +94,24 @@ pub(super) struct GroupTypeInnerAccept {

pub(crate) type AcceptFn =
Box<dyn for<'sess> Fn(&mut AcceptContext<'_, 'sess>, &ArgParser) + Send + Sync>;
pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> Option<AttributeKind>;

pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> FinalizeOutput;

/// A cross-attribute check that runs *after* all attributes on an item have been
/// finalized, so it can inspect the fully parsed attributes via
/// [`FinalizeCheckContext::parsed_attrs`]. The [`Span`] is the span of the attribute the
/// check is associated with, used for diagnostics.
pub(crate) type FinalizeCheckFn = fn(&FinalizeCheckContext<'_, '_>, Span);

/// The result of finalizing a single attribute parser.
pub(crate) struct FinalizeOutput {
/// The attribute the parser produced, if any.
pub(crate) attr: Option<AttributeKind>,
/// A check to run once *all* attributes on the item have been finalized, together
/// with the span it should be reported at. Deferred so that it can inspect the fully
/// parsed attributes via [`FinalizeCheckContext::parsed_attrs`].
pub(crate) deferred_check: Option<(FinalizeCheckFn, Span)>,
}

macro_rules! attribute_parsers {
(
Expand Down Expand Up @@ -123,7 +140,11 @@ macro_rules! attribute_parsers {
allowed_targets: <$names as crate::attributes::AttributeParser>::ALLOWED_TARGETS,
finalizer: |cx| {
let state = STATE_OBJECT.take();
state.finalize(cx)
// Compute the deferred check (if any) before consuming
// the state in `finalize`.
let deferred_check = state.deferred_finalize_check();
let attr = state.finalize(cx);
FinalizeOutput { attr, deferred_check }
}
});
}
Expand Down Expand Up @@ -793,6 +814,42 @@ impl<'p, 'sess: 'p> DerefMut for FinalizeContext<'p, 'sess> {
}
}

/// Context given to deferred cross-attribute checks (`finalize_check`).
///
/// These checks run *after* every attribute on an item has been finalized, so unlike
/// [`FinalizeContext`] this context can also inspect the fully parsed attributes via
/// [`parsed_attrs`](Self::parsed_attrs).
pub(crate) struct FinalizeCheckContext<'p, 'sess> {
pub(crate) shared: SharedContext<'p, 'sess>,

/// A list of all attribute on this syntax node.
///
/// Useful for compatibility checks with other attributes.
///
/// Unlike [`parsed_attrs`](Self::parsed_attrs), this only contains the *paths* of the
/// attributes.
pub(crate) all_attrs: &'p [RefPathParser<'p>],

/// All attributes that have been parsed on this syntax node.
///
/// Unlike [`all_attrs`](Self::all_attrs), this contains the fully parsed attributes.
pub(crate) parsed_attrs: &'p [Attribute],
}

impl<'p, 'sess: 'p> Deref for FinalizeCheckContext<'p, 'sess> {
type Target = SharedContext<'p, 'sess>;

fn deref(&self) -> &Self::Target {
&self.shared
}
}

impl<'p, 'sess: 'p> DerefMut for FinalizeCheckContext<'p, 'sess> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.shared
}
}

impl<'p, 'sess: 'p> Deref for SharedContext<'p, 'sess> {
type Target = AttributeParser<'sess>;

Expand Down
37 changes: 34 additions & 3 deletions compiler/rustc_attr_parsing/src/interface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};

use crate::attributes::AttributeSafety;
use crate::context::{
ATTRIBUTE_PARSERS, AcceptContext, FinalizeContext, FinalizeFn, SharedContext,
ATTRIBUTE_PARSERS, AcceptContext, FinalizeCheckContext, FinalizeCheckFn, FinalizeContext,
FinalizeFn, FinalizeOutput, SharedContext,
};
use crate::parser::{AllowExprMetavar, ArgParser, PathParser, RefPathParser};
use crate::session_diagnostics::ParsedDescription;
Expand Down Expand Up @@ -448,8 +449,14 @@ impl<'sess> AttributeParser<'sess> {
}

synthetic_attr_state.finalize_synthetic_attrs(&mut attributes);

// First, run all finalizers to produce the parsed attributes. Cross-attribute
// checks that need to inspect the fully parsed attributes are deferred until all
// finalizers have run (see below), since the parsed attributes are not yet all
// available here.
let mut deferred_checks: Vec<(FinalizeCheckFn, Span)> = Vec::new();
for f in &finalizers {
if let Some(attr) = f(&mut FinalizeContext {
let FinalizeOutput { attr, deferred_check } = f(&mut FinalizeContext {
shared: SharedContext {
cx: self,
target_span,
Expand All @@ -459,9 +466,33 @@ impl<'sess> AttributeParser<'sess> {
has_lint_been_emitted: AtomicBool::new(false),
},
all_attrs: &attr_paths,
}) {
});
if let Some(attr) = attr {
attributes.push(Attribute::Parsed(attr));
}
if let Some(deferred_check) = deferred_check {
deferred_checks.push(deferred_check);
}
}

// Now that all attributes have been parsed, run the deferred checks. These can
// inspect the fully parsed attributes via `FinalizeCheckContext::parsed_attrs`.
for (check, attr_span) in deferred_checks {
check(
&FinalizeCheckContext {
shared: SharedContext {
cx: self,
target_span,
target,
emit_lint: &mut emit_lint,
#[cfg(debug_assertions)]
has_lint_been_emitted: AtomicBool::new(false),
},
all_attrs: &attr_paths,
parsed_attrs: &attributes,
},
attr_span,
);
}

if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate {
Expand Down
9 changes: 9 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ pub(crate) struct BothFfiConstAndPure {
pub attr_span: Span,
}

#[derive(Diagnostic)]
#[diag("attribute should be applied to `#[repr(transparent)]` types")]
pub(crate) struct RustcPubTransparent {
#[primary_span]
pub attr_span: Span,
#[label("not a `#[repr(transparent)]` type")]
pub span: Span,
}

#[derive(Diagnostic)]
#[diag("{$attr_str} attribute cannot have empty value")]
pub(crate) struct DocAliasEmpty<'a> {
Expand Down
12 changes: 11 additions & 1 deletion compiler/rustc_hir_typeck/src/upvar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2344,12 +2344,22 @@ fn adjust_for_non_move_closure(
place.projections.iter().position(|proj| proj.kind == ProjectionKind::Deref);

match kind {
ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse => {
ty::UpvarCapture::ByValue => {
if let Some(idx) = contains_deref {
truncate_place_to_len_and_update_capture_kind(&mut place, &mut kind, idx);
}
}

// A non-`move`/`use` closure that only `.use`s an upvar does not need to
// own (and thus clone-on-capture) the value. The `ByUse` kind here can only
// come from a `x.use` in the body (a `use ||` capture clause goes through
// `adjust_for_use_closure` instead). Capturing such a place by immutable
// borrow lets the `.use` expression clone per evaluation, rather than also
// cloning the value into the closure at construction time. See #157141.
ty::UpvarCapture::ByUse => {
kind = ty::UpvarCapture::ByRef(ty::BorrowKind::Immutable);
}

ty::UpvarCapture::ByRef(..) => {}
}

Expand Down
Loading
Loading