Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
329682d
rustdoc-json: move `target` to `json::conversions`
aDotInTheVoid Oct 17, 2025
4034ea3
Update substringing when orig & sugg have equal prefixes
faculerena Oct 24, 2025
052b702
Change existing test to reflect new behaviour
faculerena Nov 1, 2025
5b91fe5
Remove debug `instrument` and added comment explaning the special case
faculerena Nov 1, 2025
f183966
Handle macro invocation in attribute during parse
estebank Sep 15, 2025
d7b9a26
Rework attribute recovery logic
estebank Sep 28, 2025
9ca8198
review comment
estebank Nov 3, 2025
b21f96f
Move `let` inside `if` condition
faculerena Nov 3, 2025
a57969b
Added tests for correct highlighting of strings with shared prefix
faculerena Nov 3, 2025
79b3963
Add Steal::risky_hack_borrow_mut
Lysxia Nov 4, 2025
a49d4d7
Special case detecting `'static` lifetime requirement coming from `->…
estebank Nov 4, 2025
8075c98
Add test for success path
osamakader Nov 6, 2025
c8618d2
Refactor safety checking for attributes
JonathanBrouwer Nov 7, 2025
87b2796
Add test for unnecessary unsafe on proc macro attr
JonathanBrouwer Nov 7, 2025
09385f9
use bare_rustc to keep host toolchain
osamakader Nov 7, 2025
244eef6
a few small clippy fixes
hkBst Nov 7, 2025
1c1923f
tests: skip rustdoc test-builder success path when cross-compiling
osamakader Nov 8, 2025
a5814a5
Move `parse_cfg_select` to `rustc_builtin_macros`
JonathanBrouwer Nov 9, 2025
c111ccc
Add more tests for `cfg_select` parsing
JonathanBrouwer Nov 8, 2025
90f36af
Port `cfg_select!` to the new attribute parsing system
JonathanBrouwer Nov 8, 2025
c5f2eb6
rustc_target: hide TargetOptions::vendor
tamird Nov 9, 2025
f1bbe59
tests: skip rustdoc test-builder success path for remote client
osamakader Nov 9, 2025
3d44aca
Fix a typo in the documentation for the strict_shr function
reddevilmidzy Nov 10, 2025
ee8c913
test(rustdoc): move tests into jump-to-def
midsterx Nov 7, 2025
5ee331f
fix doc comment
luca3s Nov 10, 2025
1839cdb
Remove unneeded `allow(rustc::potential_query_instability)`
GuillaumeGomez Nov 10, 2025
a58500b
Rollup merge of #146579 - estebank:issue-146325, r=jdonszelmann
ChrisDenton Nov 10, 2025
d80aed8
Rollup merge of #147833 - aDotInTheVoid:rdj-shuffle, r=camelid
ChrisDenton Nov 10, 2025
e36ae1a
Rollup merge of #148061 - faculerena:master, r=BoxyUwU
ChrisDenton Nov 10, 2025
3fc315b
Rollup merge of #148480 - Lysxia:steal-mut, r=davidtwco
ChrisDenton Nov 10, 2025
ad68f54
Rollup merge of #148506 - estebank:issue-41966, r=davidtwco
ChrisDenton Nov 10, 2025
d8f02bb
Rollup merge of #148608 - osamakader:doc-test-builder, r=GuillaumeGomez
ChrisDenton Nov 10, 2025
21be3d1
Rollup merge of #148639 - midsterx:test/rustdoc, r=GuillaumeGomez
ChrisDenton Nov 10, 2025
f132514
Rollup merge of #148647 - JonathanBrouwer:unsafe_attr_refactor, r=jdo…
ChrisDenton Nov 10, 2025
e6cb41c
Rollup merge of #148667 - hkBst:clippy-fix-14, r=Kivooeo
ChrisDenton Nov 10, 2025
b897320
Rollup merge of #148712 - JonathanBrouwer:cfg_select, r=jdonszelmann
ChrisDenton Nov 10, 2025
9eff3af
Rollup merge of #148760 - tamird:avoid-vendor-logic, r=madsmtm
ChrisDenton Nov 10, 2025
62545b8
Rollup merge of #148775 - reddevilmidzy:fix-typo, r=joboet
ChrisDenton Nov 10, 2025
b6f11de
Rollup merge of #148781 - GuillaumeGomez:rm-unneeded-attr, r=yotamofek
ChrisDenton Nov 10, 2025
9ad7392
Rollup merge of #148791 - luca3s:fix-doc-comment, r=lqd
ChrisDenton Nov 10, 2025
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
13 changes: 13 additions & 0 deletions compiler/rustc_ast/src/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1256,6 +1256,19 @@ pub enum StmtKind {
MacCall(Box<MacCallStmt>),
}

impl StmtKind {
pub fn descr(&self) -> &'static str {
match self {
StmtKind::Let(_) => "local",
StmtKind::Item(_) => "item",
StmtKind::Expr(_) => "expression",
StmtKind::Semi(_) => "statement",
StmtKind::Empty => "semicolon",
StmtKind::MacCall(_) => "macro call",
}
}
}

#[derive(Clone, Encodable, Decodable, Debug, Walkable)]
pub struct MacCallStmt {
pub mac: Box<MacCall>,
Expand Down
6 changes: 3 additions & 3 deletions compiler/rustc_ast_lowering/src/index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -125,9 +125,9 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
}

impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
/// Because we want to track parent items and so forth, enable
/// deep walking so that we walk nested items in the context of
/// their outer items.
// Because we want to track parent items and so forth, enable
// deep walking so that we walk nested items in the context of
// their outer items.

fn visit_nested_item(&mut self, item: ItemId) {
debug!("visit_nested_item: {:?}", item);
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ attr_parsing_invalid_link_modifier =
attr_parsing_invalid_meta_item = expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found {$descr}
.remove_neg_sugg = negative numbers are not literals, try removing the `-` sign
.quote_ident_sugg = surround the identifier with quotation marks to make it into a string literal
.label = {$descr}s are not allowed here
attr_parsing_invalid_predicate =
invalid predicate `{$predicate}`
Expand Down
89 changes: 89 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
use rustc_ast::token::Token;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrStyle, NodeId, token};
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::AttrPath;
use rustc_hir::attrs::CfgEntry;
use rustc_parse::exp;
use rustc_parse::parser::Parser;
use rustc_session::Session;
use rustc_span::{ErrorGuaranteed, Ident, Span};

use crate::parser::MetaItemOrLitParser;
use crate::{AttributeParser, ParsedDescription, ShouldEmit, parse_cfg_entry};

pub enum CfgSelectPredicate {
Cfg(CfgEntry),
Wildcard(Token),
}

#[derive(Default)]
pub struct CfgSelectBranches {
/// All the conditional branches.
pub reachable: Vec<(CfgEntry, TokenStream, Span)>,
/// The first wildcard `_ => { ... }` branch.
pub wildcard: Option<(Token, TokenStream, Span)>,
/// All branches after the first wildcard, including further wildcards.
/// These branches are kept for formatting.
pub unreachable: Vec<(CfgSelectPredicate, TokenStream, Span)>,
}

pub fn parse_cfg_select(
p: &mut Parser<'_>,
sess: &Session,
features: Option<&Features>,
lint_node_id: NodeId,
) -> Result<CfgSelectBranches, ErrorGuaranteed> {
let mut branches = CfgSelectBranches::default();

while p.token != token::Eof {
if p.eat_keyword(exp!(Underscore)) {
let underscore = p.prev_token;
p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;

let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
let span = underscore.span.to(p.token.span);

match branches.wildcard {
None => branches.wildcard = Some((underscore, tts, span)),
Some(_) => {
branches.unreachable.push((CfgSelectPredicate::Wildcard(underscore), tts, span))
}
}
} else {
let meta = MetaItemOrLitParser::parse_single(p, ShouldEmit::ErrorsAndLints)
.map_err(|diag| diag.emit())?;
let cfg_span = meta.span();
let cfg = AttributeParser::parse_single_args(
sess,
cfg_span,
cfg_span,
AttrStyle::Inner,
AttrPath {
segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(),
span: cfg_span,
},
ParsedDescription::Macro,
cfg_span,
lint_node_id,
features,
ShouldEmit::ErrorsAndLints,
&meta,
parse_cfg_entry,
&AttributeTemplate::default(),
)?;

p.expect(exp!(FatArrow)).map_err(|e| e.emit())?;

let tts = p.parse_delimited_token_tree().map_err(|e| e.emit())?;
let span = cfg_span.to(p.token.span);

match branches.wildcard {
None => branches.reachable.push((cfg, tts, span)),
Some(_) => branches.unreachable.push((CfgSelectPredicate::Cfg(cfg), tts, span)),
}
}
}

Ok(branches)
}
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 @@ -33,6 +33,7 @@ pub(crate) mod allow_unstable;
pub(crate) mod body;
pub(crate) mod cfg;
pub(crate) mod cfg_old;
pub(crate) mod cfg_select;
pub(crate) mod codegen_attrs;
pub(crate) mod confusables;
pub(crate) mod crate_level;
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ pub use attributes::cfg::{
CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg, parse_cfg_attr, parse_cfg_entry,
};
pub use attributes::cfg_old::*;
pub use attributes::cfg_select::*;
pub use attributes::util::{is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version};
pub use context::{Early, Late, OmitDoc, ShouldEmit};
pub use interface::AttributeParser;
Expand Down
68 changes: 45 additions & 23 deletions compiler/rustc_attr_parsing/src/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,12 @@ use std::fmt::{Debug, Display};

use rustc_ast::token::{self, Delimiter, MetaVarKind};
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path};
use rustc_ast::{AttrArgs, Expr, ExprKind, LitKind, MetaItemLit, NormalAttr, Path, StmtKind, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::{Diag, PResult};
use rustc_hir::{self as hir, AttrPath};
use rustc_parse::exp;
use rustc_parse::parser::{Parser, PathStyle, token_descr};
use rustc_parse::parser::{ForceCollect, Parser, PathStyle, token_descr};
use rustc_session::errors::{create_lit_error, report_lit_error};
use rustc_session::parse::ParseSess;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
Expand Down Expand Up @@ -488,33 +488,55 @@ impl<'a, 'sess> MetaItemListParserContext<'a, 'sess> {
descr: token_descr(&self.parser.token),
quote_ident_sugg: None,
remove_neg_sugg: None,
label: None,
};

if let token::OpenInvisible(_) = self.parser.token.kind {
// Do not attempt to suggest anything when encountered as part of a macro expansion.
return self.parser.dcx().create_err(err);
}

// Suggest quoting idents, e.g. in `#[cfg(key = value)]`. We don't use `Token::ident` and
// don't `uninterpolate` the token to avoid suggesting anything butchered or questionable
// when macro metavariables are involved.
if self.parser.prev_token == token::Eq
&& let token::Ident(..) = self.parser.token.kind
{
let before = self.parser.token.span.shrink_to_lo();
while let token::Ident(..) = self.parser.token.kind {
self.parser.bump();
let snapshot = self.parser.create_snapshot_for_diagnostic();
let stmt = self.parser.parse_stmt_without_recovery(false, ForceCollect::No, false);
match stmt {
Ok(Some(stmt)) => {
// The user tried to write something like
// `#[deprecated(note = concat!("a", "b"))]`.
err.descr = stmt.kind.descr().to_string();
err.label = Some(stmt.span);
err.span = stmt.span;
if let StmtKind::Expr(expr) = &stmt.kind
&& let ExprKind::Unary(UnOp::Neg, val) = &expr.kind
&& let ExprKind::Lit(_) = val.kind
{
err.remove_neg_sugg = Some(InvalidMetaItemRemoveNegSugg {
negative_sign: expr.span.until(val.span),
});
} else if let StmtKind::Expr(expr) = &stmt.kind
&& let ExprKind::Path(None, Path { segments, .. }) = &expr.kind
&& segments.len() == 1
{
while let token::Ident(..) | token::Literal(_) | token::Dot =
self.parser.token.kind
{
// We've got a word, so we try to consume the rest of a potential sentence.
// We include `.` to correctly handle things like `A sentence here.`.
self.parser.bump();
}
err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg {
before: expr.span.shrink_to_lo(),
after: self.parser.prev_token.span.shrink_to_hi(),
});
}
}
Ok(None) => {}
Err(e) => {
e.cancel();
self.parser.restore_snapshot(snapshot);
}
err.quote_ident_sugg = Some(InvalidMetaItemQuoteIdentSugg {
before,
after: self.parser.prev_token.span.shrink_to_hi(),
});
}

if self.parser.token == token::Minus
&& self
.parser
.look_ahead(1, |t| matches!(t.kind, rustc_ast::token::TokenKind::Literal { .. }))
{
err.remove_neg_sugg =
Some(InvalidMetaItemRemoveNegSugg { negative_sign: self.parser.token.span });
self.parser.bump();
self.parser.bump();
}

self.parser.dcx().create_err(err)
Expand Down
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/session_diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -846,6 +846,8 @@ pub(crate) struct InvalidMetaItem {
pub quote_ident_sugg: Option<InvalidMetaItemQuoteIdentSugg>,
#[subdiagnostic]
pub remove_neg_sugg: Option<InvalidMetaItemRemoveNegSugg>,
#[label]
pub label: Option<Span>,
}

#[derive(Subdiagnostic)]
Expand Down
9 changes: 2 additions & 7 deletions compiler/rustc_attr_parsing/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ pub fn check_attribute_safety(

// - Normal builtin attribute
// - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes
(Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => {
(None | Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => {
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
span: unsafe_span,
name: attr_item.path.clone(),
Expand All @@ -218,15 +218,10 @@ pub fn check_attribute_safety(

// - Normal builtin attribute
// - No explicit `#[unsafe(..)]` written.
(Some(AttributeSafety::Normal), Safety::Default) => {
(None | Some(AttributeSafety::Normal), Safety::Default) => {
// OK
}

// - Non-builtin attribute
(None, Safety::Unsafe(_) | Safety::Default) => {
// OK (not checked here)
}

(
Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None,
Safety::Safe(..),
Expand Down
74 changes: 40 additions & 34 deletions compiler/rustc_builtin_macros/src/cfg_select.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,21 @@
use rustc_ast::tokenstream::TokenStream;
use rustc_attr_parsing as attr;
use rustc_attr_parsing::{
CfgSelectBranches, CfgSelectPredicate, EvalConfigResult, ShouldEmit, parse_cfg_select,
};
use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult};
use rustc_parse::parser::cfg_select::{CfgSelectBranches, CfgSelectPredicate, parse_cfg_select};
use rustc_span::{Ident, Span, sym};

use crate::errors::{CfgSelectNoMatches, CfgSelectUnreachable};

/// Selects the first arm whose predicate evaluates to true.
fn select_arm(ecx: &ExtCtxt<'_>, branches: CfgSelectBranches) -> Option<(TokenStream, Span)> {
for (cfg, tt, arm_span) in branches.reachable {
if attr::cfg_matches(
&cfg,
if let EvalConfigResult::True = attr::eval_config_entry(
&ecx.sess,
&cfg,
ecx.current_expansion.lint_node_id,
Some(ecx.ecfg.features),
ShouldEmit::ErrorsAndLints,
) {
return Some((tt, arm_span));
}
Expand All @@ -27,37 +29,41 @@ pub(super) fn expand_cfg_select<'cx>(
sp: Span,
tts: TokenStream,
) -> MacroExpanderResult<'cx> {
ExpandResult::Ready(match parse_cfg_select(&mut ecx.new_parser_from_tts(tts)) {
Ok(branches) => {
if let Some((underscore, _, _)) = branches.wildcard {
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
for (predicate, _, _) in &branches.unreachable {
let span = match predicate {
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
};
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
ecx.dcx().emit_warn(err);
ExpandResult::Ready(
match parse_cfg_select(
&mut ecx.new_parser_from_tts(tts),
ecx.sess,
Some(ecx.ecfg.features),
ecx.current_expansion.lint_node_id,
) {
Ok(branches) => {
if let Some((underscore, _, _)) = branches.wildcard {
// Warn for every unreachable predicate. We store the fully parsed branch for rustfmt.
for (predicate, _, _) in &branches.unreachable {
let span = match predicate {
CfgSelectPredicate::Wildcard(underscore) => underscore.span,
CfgSelectPredicate::Cfg(cfg) => cfg.span(),
};
let err = CfgSelectUnreachable { span, wildcard_span: underscore.span };
ecx.dcx().emit_warn(err);
}
}
}

if let Some((tts, arm_span)) = select_arm(ecx, branches) {
return ExpandResult::from_tts(
ecx,
tts,
sp,
arm_span,
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
if let Some((tts, arm_span)) = select_arm(ecx, branches) {
return ExpandResult::from_tts(
ecx,
tts,
sp,
arm_span,
Ident::with_dummy_span(sym::cfg_select),
);
} else {
// Emit a compiler error when none of the predicates matched.
let guar = ecx.dcx().emit_err(CfgSelectNoMatches { span: sp });
DummyResult::any(sp, guar)
}
}
}
Err(err) => {
let guar = err.emit();
DummyResult::any(sp, guar)
}
})
Err(guar) => DummyResult::any(sp, guar),
},
)
}
4 changes: 2 additions & 2 deletions compiler/rustc_codegen_cranelift/src/abi/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -916,8 +916,8 @@ pub(crate) fn codegen_call_with_unwind_action(
pub(crate) fn lib_call_arg_param(tcx: TyCtxt<'_>, ty: Type, is_signed: bool) -> AbiParam {
let param = AbiParam::new(ty);
if ty.is_int() && u64::from(ty.bits()) < tcx.data_layout.pointer_size().bits() {
match (&tcx.sess.target.arch, tcx.sess.target.vendor.as_ref()) {
(Arch::X86_64, _) | (Arch::AArch64, "apple") => match (ty, is_signed) {
match (&tcx.sess.target.arch, tcx.sess.target.is_like_darwin) {
(Arch::X86_64, _) | (Arch::AArch64, true) => match (ty, is_signed) {
(types::I8 | types::I16, true) => param.sext(),
(types::I8 | types::I16, false) => param.uext(),
_ => param,
Expand Down
Loading
Loading