Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
6c4c438
destabilise target-spec-json
davidtwco Dec 19, 2025
ee12ffe
Add example for profiling diff locally
Mattias-Petersson Dec 14, 2025
f4112ee
Fix commit according to PR review
Mattias-Petersson Dec 28, 2025
8233943
Fix indent in rust code
reddevilmidzy Jan 6, 2026
7ba5fbc
Merge pull request #2696 from Mattias-Petersson/fix-1692
tshepang Jan 7, 2026
e2c73b8
docs:improve const generics
xonx4l Jan 8, 2026
3c77e23
Merge pull request #2719 from xonx4l/const_generics_docs
BoxyUwU Jan 8, 2026
48ccb1f
Retire outdated stage0 std remarks
jieyouxu Jan 9, 2026
b9bf986
Merge pull request #2720 from jieyouxu/fix-stage0
jieyouxu Jan 9, 2026
6f12b86
s390x: support `f16` and `f16x8` in inline assembly
folkertdev Jan 8, 2026
f9c71df
Improve span for "unresolved intra doc link" on `deprecated` attribute
GuillaumeGomez Jan 9, 2026
ef1e4e6
Move checks from `check_doc_attrs` directly into `rustc_attr_parsing`
GuillaumeGomez Jan 10, 2026
e20d903
Prepare for merging from rust-lang/rust
invalid-email-address Jan 12, 2026
d53ec2a
Merge ref '44a5b55557c2' from rust-lang/rust
invalid-email-address Jan 12, 2026
b327e30
core: ptr: split_at_mut: fix typo in safety doc
lschuermann Jan 12, 2026
a40e484
Merge pull request #2721 from rust-lang/rustc-pull
tshepang Jan 12, 2026
6ca9501
Relax test expectation for @__llvm_profile_runtime_user
zmodem Jan 12, 2026
d2cd1ff
Merge pull request #2722 from reddevilmidzy/ambig
Noratrieb Jan 12, 2026
c451e9b
Remove a workaround for a bug
bjorn3 Sep 19, 2021
90b32e7
Fix typo in `MaybeUninit` docs
tbu- Jan 12, 2026
50b60aa
std: sys: net: uefi: Make TcpStream Send
Ayush1325 Jan 12, 2026
439da07
Update books
rustbot Jan 12, 2026
418cff3
Port `#[must_not_suspend]` to attribute parser
Bryntet Jan 10, 2026
ffe359f
another corner case
tshepang Jan 12, 2026
52a5023
sembr src/external-repos.md
tshepang Jan 12, 2026
2204cbd
"in tree" should be "in-tree"
tshepang Jan 12, 2026
c4b05c3
fix sembr tool limitation
tshepang Jan 12, 2026
9a81699
use a stronger pause
tshepang Jan 12, 2026
98e65aa
handle another numbered list notation
tshepang Jan 12, 2026
ef5bae8
Merge pull request #2723 from rust-lang/tshepang/sembr
tshepang Jan 12, 2026
419655b
sembr src/tests/directives.md
tshepang Jan 12, 2026
e0d9c07
add missing pause
tshepang Jan 12, 2026
257f629
Merge pull request #2724 from rust-lang/tshepang/sembr
tshepang Jan 12, 2026
31c0191
sembr src/building/new-target.md
tshepang Jan 12, 2026
d442a79
sembr src/rustdoc-internals/rustdoc-html-test-suite.md
tshepang Jan 12, 2026
3289426
sembr src/profiling/with_rustc_perf.md
tshepang Jan 12, 2026
c451d97
a more natural continuation
tshepang Jan 12, 2026
2d9616a
add missing pause
tshepang Jan 12, 2026
d89da80
sembr src/tests/best-practices.md
tshepang Jan 12, 2026
579e2b3
some improvements to tests/best-practices.md
tshepang Jan 12, 2026
da5aa28
sembr src/tests/perf.md
tshepang Jan 12, 2026
46ea5b4
Merge pull request #2725 from rust-lang/tshepang/sembr
tshepang Jan 12, 2026
2d49cfe
fix: added missing type in triagebot.toml
JayanAXHF Jan 12, 2026
afe76df
Don't suggest replacing closure parameter with type name
heathdutton Jan 12, 2026
a89683d
Rollup merge of #150151 - destabilise-target-spec-json, r=Kivooeo
JonathanBrouwer Jan 13, 2026
002b68d
Rollup merge of #150826 - s390x-asm-f16-vector, r=uweigand,tgross35
JonathanBrouwer Jan 13, 2026
dc6afd7
Rollup merge of #150883 - improve-deprecated-intra-doc-span, r=camelid
JonathanBrouwer Jan 13, 2026
e33f5aa
Rollup merge of #150934 - move-doc-attr-checks, r=JonathanBrouwer
JonathanBrouwer Jan 13, 2026
a299406
Rollup merge of #150943 - port_must_not_suspend, r=jdonszelmann,Jonat…
JonathanBrouwer Jan 13, 2026
a830a9a
Rollup merge of #150990 - uefi-run-test, r=joboet
JonathanBrouwer Jan 13, 2026
66bd4c4
Rollup merge of #150995 - dev/core-ptr-split-at-mut-docs-fix, r=joboet
JonathanBrouwer Jan 13, 2026
7090787
Rollup merge of #150998 - win___llvm_profile_runtime_user, r=durin42
JonathanBrouwer Jan 13, 2026
6e2d304
Rollup merge of #151002 - remove_bug_workaround, r=lqd
JonathanBrouwer Jan 13, 2026
d47c0d0
Rollup merge of #151005 - pr_doc_maybeuninit_typo, r=joboet
JonathanBrouwer Jan 13, 2026
ced35f8
Rollup merge of #151011 - docs-update, r=ehuss
JonathanBrouwer Jan 13, 2026
0a200ad
Rollup merge of #151029 - rdg-sync, r=tshepang
JonathanBrouwer Jan 13, 2026
2ad4bf2
Rollup merge of #151032 - main, r=Urgau
JonathanBrouwer Jan 13, 2026
7ee6257
Rollup merge of #151035 - issue-150693-closure-arg-suggestion, r=jiey…
JonathanBrouwer Jan 13, 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
8 changes: 4 additions & 4 deletions compiler/rustc_ast/src/attr/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -235,14 +235,14 @@ impl AttributeExt for Attribute {
}
}

fn deprecation_note(&self) -> Option<Symbol> {
fn deprecation_note(&self) -> Option<Ident> {
match &self.kind {
AttrKind::Normal(normal) if normal.item.path == sym::deprecated => {
let meta = &normal.item;

// #[deprecated = "..."]
if let Some(s) = meta.value_str() {
return Some(s);
return Some(Ident { name: s, span: meta.span() });
}

// #[deprecated(note = "...")]
Expand All @@ -252,7 +252,7 @@ impl AttributeExt for Attribute {
&& mi.path == sym::note
&& let Some(s) = mi.value_str()
{
return Some(s);
return Some(Ident { name: s, span: mi.span });
}
}
}
Expand Down Expand Up @@ -905,7 +905,7 @@ pub trait AttributeExt: Debug {
/// Returns the deprecation note if this is deprecation attribute.
/// * `#[deprecated = "note"]` returns `Some("note")`.
/// * `#[deprecated(note = "note", ...)]` returns `Some("note")`.
fn deprecation_note(&self) -> Option<Symbol>;
fn deprecation_note(&self) -> Option<Ident>;

fn is_proc_macro_attr(&self) -> bool {
[sym::proc_macro, sym::proc_macro_attribute, sym::proc_macro_derive]
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_attr_parsing/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ attr_parsing_doc_alias_malformed =
attr_parsing_doc_alias_start_end =
{$attr_str} cannot start or end with ' '

attr_parsing_doc_attr_not_crate_level =
`#![doc({$attr_name} = "...")]` isn't allowed as a crate-level attribute

attr_parsing_doc_attribute_not_attribute =
nonexistent builtin attribute `{$attribute}` used in `#[doc(attribute = "...")]`
.help = only existing builtin attributes are allowed in core/std
Expand Down
22 changes: 14 additions & 8 deletions compiler/rustc_attr_parsing/src/attributes/deprecation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,14 @@ fn get<S: Stage>(
name: Symbol,
param_span: Span,
arg: &ArgParser,
item: &Option<Symbol>,
) -> Option<Symbol> {
item: Option<Symbol>,
) -> Option<Ident> {
if item.is_some() {
cx.duplicate_key(param_span, name);
return None;
}
if let Some(v) = arg.name_value() {
if let Some(value_str) = v.value_as_str() {
if let Some(value_str) = v.value_as_ident() {
Some(value_str)
} else {
cx.expected_string_literal(v.value_span, Some(&v.value_as_lit()));
Expand Down Expand Up @@ -72,7 +72,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
let features = cx.features();

let mut since = None;
let mut note = None;
let mut note: Option<Ident> = None;
let mut suggestion = None;

let is_rustc = features.staged_api();
Expand All @@ -92,10 +92,16 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {

match ident_name {
Some(name @ sym::since) => {
since = Some(get(cx, name, param.span(), param.args(), &since)?);
since = Some(get(cx, name, param.span(), param.args(), since)?.name);
}
Some(name @ sym::note) => {
note = Some(get(cx, name, param.span(), param.args(), &note)?);
note = Some(get(
cx,
name,
param.span(),
param.args(),
note.map(|ident| ident.name),
)?);
}
Some(name @ sym::suggestion) => {
if !features.deprecated_suggestion() {
Expand All @@ -107,7 +113,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
}

suggestion =
Some(get(cx, name, param.span(), param.args(), &suggestion)?);
Some(get(cx, name, param.span(), param.args(), suggestion)?.name);
}
_ => {
cx.expected_specific_argument(
Expand All @@ -124,7 +130,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
}
}
ArgParser::NameValue(v) => {
let Some(value) = v.value_as_str() else {
let Some(value) = v.value_as_ident() else {
cx.expected_string_literal(v.value_span, Some(v.value_as_lit()));
return None;
};
Expand Down
119 changes: 96 additions & 23 deletions compiler/rustc_attr_parsing/src/attributes/doc.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit};
use rustc_feature::template;
use rustc_hir::Target;
use rustc_hir::attrs::{
AttributeKind, CfgEntry, CfgHideShow, CfgInfo, DocAttribute, DocInline, HideOrShow,
};
Expand All @@ -12,8 +13,8 @@ use super::{AcceptMapping, AttributeParser};
use crate::context::{AcceptContext, FinalizeContext, Stage};
use crate::parser::{ArgParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser};
use crate::session_diagnostics::{
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttributeNotAttribute,
DocKeywordNotKeyword,
DocAliasBadChar, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel,
DocAttributeNotAttribute, DocKeywordNotKeyword,
};

fn check_keyword<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, keyword: Symbol, span: Span) -> bool {
Expand Down Expand Up @@ -43,16 +44,39 @@ fn check_attribute<S: Stage>(
false
}

fn parse_keyword_and_attribute<S, F>(
/// Checks that an attribute is *not* used at the crate level. Returns `true` if valid.
fn check_attr_not_crate_level<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
span: Span,
attr_name: Symbol,
) -> bool {
if cx.shared.target.is_some_and(|target| target == Target::Crate) {
cx.emit_err(DocAttrNotCrateLevel { span, attr_name });
return false;
}
true
}

/// Checks that an attribute is used at the crate level. Returns `true` if valid.
fn check_attr_crate_level<S: Stage>(cx: &mut AcceptContext<'_, '_, S>, span: Span) -> bool {
if cx.shared.target.is_some_and(|target| target != Target::Crate) {
cx.emit_lint(
rustc_session::lint::builtin::INVALID_DOC_ATTRIBUTES,
AttributeLintKind::AttrCrateLevelOnly,
span,
);
return false;
}
true
}

fn parse_keyword_and_attribute<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
path: &OwnedPathParser,
args: &ArgParser,
attr_value: &mut Option<(Symbol, Span)>,
callback: F,
) where
S: Stage,
F: FnOnce(&mut AcceptContext<'_, '_, S>, Symbol, Span) -> bool,
{
attr_name: Symbol,
) {
let Some(nv) = args.name_value() else {
cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym());
return;
Expand All @@ -63,16 +87,26 @@ fn parse_keyword_and_attribute<S, F>(
return;
};

if !callback(cx, value, nv.value_span) {
let ret = if attr_name == sym::keyword {
check_keyword(cx, value, nv.value_span)
} else {
check_attribute(cx, value, nv.value_span)
};
if !ret {
return;
}

let span = path.span();
if attr_value.is_some() {
cx.duplicate_key(path.span(), path.word_sym().unwrap());
cx.duplicate_key(span, path.word_sym().unwrap());
return;
}

*attr_value = Some((value, path.span()));
if !check_attr_not_crate_level(cx, span, attr_name) {
return;
}

*attr_value = Some((value, span));
}

#[derive(Default, Debug)]
Expand Down Expand Up @@ -102,6 +136,10 @@ impl DocParser {
return;
}

if !check_attr_crate_level(cx, path.span()) {
return;
}

self.attribute.no_crate_inject = Some(path.span())
}
Some(sym::attr) => {
Expand Down Expand Up @@ -155,6 +193,9 @@ impl DocParser {
cx.emit_err(DocAliasStartEnd { span, attr_str });
return;
}
if !check_attr_not_crate_level(cx, span, sym::alias) {
return;
}

if let Some(first_definition) = self.attribute.aliases.get(&alias).copied() {
cx.emit_lint(
Expand Down Expand Up @@ -366,7 +407,33 @@ impl DocParser {
self.attribute.$ident = Some(path.span());
}};
}
macro_rules! string_arg {
macro_rules! no_args_and_not_crate_level {
($ident: ident) => {{
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
return;
}
let span = path.span();
if !check_attr_not_crate_level(cx, span, sym::$ident) {
return;
}
self.attribute.$ident = Some(span);
}};
}
macro_rules! no_args_and_crate_level {
($ident: ident) => {{
if let Err(span) = args.no_args() {
cx.expected_no_args(span);
return;
}
let span = path.span();
if !check_attr_crate_level(cx, span) {
return;
}
self.attribute.$ident = Some(span);
}};
}
macro_rules! string_arg_and_crate_level {
($ident: ident) => {{
let Some(nv) = args.name_value() else {
cx.expected_name_value(args.span().unwrap_or(path.span()), path.word_sym());
Expand All @@ -378,6 +445,10 @@ impl DocParser {
return;
};

if !check_attr_crate_level(cx, path.span()) {
return;
}

// FIXME: It's errorring when the attribute is passed multiple times on the command
// line.
// The right fix for this would be to only check this rule if the attribute is
Expand All @@ -394,12 +465,14 @@ impl DocParser {
match path.word_sym() {
Some(sym::alias) => self.parse_alias(cx, path, args),
Some(sym::hidden) => no_args!(hidden),
Some(sym::html_favicon_url) => string_arg!(html_favicon_url),
Some(sym::html_logo_url) => string_arg!(html_logo_url),
Some(sym::html_no_source) => no_args!(html_no_source),
Some(sym::html_playground_url) => string_arg!(html_playground_url),
Some(sym::html_root_url) => string_arg!(html_root_url),
Some(sym::issue_tracker_base_url) => string_arg!(issue_tracker_base_url),
Some(sym::html_favicon_url) => string_arg_and_crate_level!(html_favicon_url),
Some(sym::html_logo_url) => string_arg_and_crate_level!(html_logo_url),
Some(sym::html_no_source) => no_args_and_crate_level!(html_no_source),
Some(sym::html_playground_url) => string_arg_and_crate_level!(html_playground_url),
Some(sym::html_root_url) => string_arg_and_crate_level!(html_root_url),
Some(sym::issue_tracker_base_url) => {
string_arg_and_crate_level!(issue_tracker_base_url)
}
Some(sym::inline) => self.parse_inline(cx, path, args, DocInline::Inline),
Some(sym::no_inline) => self.parse_inline(cx, path, args, DocInline::NoInline),
Some(sym::masked) => no_args!(masked),
Expand All @@ -410,18 +483,18 @@ impl DocParser {
path,
args,
&mut self.attribute.keyword,
check_keyword,
sym::keyword,
),
Some(sym::attribute) => parse_keyword_and_attribute(
cx,
path,
args,
&mut self.attribute.attribute,
check_attribute,
sym::attribute,
),
Some(sym::fake_variadic) => no_args!(fake_variadic),
Some(sym::search_unbox) => no_args!(search_unbox),
Some(sym::rust_logo) => no_args!(rust_logo),
Some(sym::fake_variadic) => no_args_and_not_crate_level!(fake_variadic),
Some(sym::search_unbox) => no_args_and_not_crate_level!(search_unbox),
Some(sym::rust_logo) => no_args_and_crate_level!(rust_logo),
Some(sym::auto_cfg) => self.parse_auto_cfg(cx, path, args),
Some(sym::test) => {
let Some(list) = args.list() else {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod macro_attrs;
pub(crate) mod must_not_suspend;
pub(crate) mod must_use;
pub(crate) mod no_implicit_prelude;
pub(crate) mod no_link;
Expand Down
35 changes: 35 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/must_not_suspend.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
use super::prelude::*;

pub(crate) struct MustNotSuspendParser;

impl<S: Stage> SingleAttributeParser<S> for MustNotSuspendParser {
const PATH: &[rustc_span::Symbol] = &[sym::must_not_suspend];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::Union),
Allow(Target::Trait),
]);
const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let reason = match args {
ArgParser::NameValue(reason) => match reason.value_as_str() {
Some(val) => Some(val),
None => {
cx.expected_nv_or_no_args(reason.value_span);
return None;
}
},
ArgParser::NoArgs => None,
ArgParser::List(list) => {
cx.expected_nv_or_no_args(list.span);
return None;
}
};

Some(AttributeKind::MustNotSupend { reason })
}
}
4 changes: 3 additions & 1 deletion compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ use crate::attributes::macro_attrs::{
AllowInternalUnsafeParser, CollapseDebugInfoParser, MacroEscapeParser, MacroExportParser,
MacroUseParser,
};
use crate::attributes::must_not_suspend::MustNotSuspendParser;
use crate::attributes::must_use::MustUseParser;
use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
use crate::attributes::no_link::NoLinkParser;
Expand Down Expand Up @@ -89,7 +90,6 @@ use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, ParsedDescription,
};
use crate::target_checking::AllowedTargets;

type GroupType<S> = LazyLock<GroupTypeInner<S>>;

pub(super) struct GroupTypeInner<S: Stage> {
Expand Down Expand Up @@ -208,6 +208,7 @@ attribute_parsers!(
Single<LinkageParser>,
Single<MacroExportParser>,
Single<MoveSizeLimitParser>,
Single<MustNotSuspendParser>,
Single<MustUseParser>,
Single<ObjcClassParser>,
Single<ObjcSelectorParser>,
Expand Down Expand Up @@ -655,6 +656,7 @@ pub struct SharedContext<'p, 'sess, S: Stage> {
pub(crate) target_span: Span,
/// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
pub(crate) target_id: S::Id,
pub(crate) target: Option<rustc_hir::Target>,

pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
}
Expand Down
Loading
Loading