Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
4305769
Tweak handling of "struct like start" where a struct isn't supported
estebank Sep 24, 2025
a4e87e9
Support `#[rustc_align_static]` inside `thread_local!`
Jules-Bertholet Sep 10, 2025
bb48c16
Simplify logic slightly
estebank Sep 24, 2025
4d32b9a
Hoist non-platform-specific code out of `thread_local_inner!`
Jules-Bertholet Sep 27, 2025
86f2d42
indexing: reword help
hkBst Sep 15, 2025
5b809b3
Don't enable shared memory with Wasm atomics
daxpedda Oct 1, 2025
8dfea22
implement `Box::take`
edwloef Oct 1, 2025
6961953
Switch `citool` to 2024 edition
GuillaumeGomez Oct 1, 2025
4baf920
Initialize llvm submodule if not already the case to run citool
GuillaumeGomez Oct 1, 2025
3e8ce2b
Adjust WASI and WALI targets
daxpedda Oct 1, 2025
94f00f4
Fix memory leak in `os` impl
Jules-Bertholet Oct 1, 2025
5991c87
Update books
rustbot Oct 1, 2025
30d57ab
mbe: Rename a local variable to match corresponding field names
joshtriplett Sep 14, 2025
6bff1ab
mbe: Support `unsafe` attribute rules
joshtriplett Sep 14, 2025
05c5b87
mbe: Add parsing tests for `unsafe` macro rules
joshtriplett Sep 14, 2025
ea0e00c
mbe: Add tests for `unsafe` attr invocation
joshtriplett Sep 14, 2025
4fc0a0d
mbe: `expand_invoc`: Add comment about not needing to check safety of…
joshtriplett Sep 28, 2025
59c4dfe
Forbid `//@ compile-flags: -Cincremental=` in tests
Zalathar Oct 1, 2025
a5d124d
Rollup merge of #146281 - Jules-Bertholet:static-align-thread-local, …
matthiaskrgr Oct 2, 2025
800a0d4
Rollup merge of #146535 - joshtriplett:mbe-unsafe-attr, r=petrochenkov
matthiaskrgr Oct 2, 2025
ea5e438
Rollup merge of #146585 - hkBst:indexing-1, r=jdonszelmann
matthiaskrgr Oct 2, 2025
d558654
Rollup merge of #147004 - estebank:ascription-in-pat, r=fee1-dead
matthiaskrgr Oct 2, 2025
be146e1
Rollup merge of #147221 - Zalathar:incremental, r=lqd
matthiaskrgr Oct 2, 2025
8288455
Rollup merge of #147225 - daxpedda:wasm-u-u-atomics-threads, r=alexcr…
matthiaskrgr Oct 2, 2025
3f952f1
Rollup merge of #147227 - edwloef:box_take, r=joboet
matthiaskrgr Oct 2, 2025
79954a8
Rollup merge of #147233 - GuillaumeGomez:citool-submodule-init, r=Kobzol
matthiaskrgr Oct 2, 2025
1530259
Rollup merge of #147236 - rustbot:docs-update, r=ehuss
matthiaskrgr Oct 2, 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
12 changes: 5 additions & 7 deletions compiler/rustc_attr_parsing/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -207,10 +207,9 @@ pub fn check_attribute_safety(
}
}

// - Normal builtin attribute, or any non-builtin attribute
// - All non-builtin attributes are currently considered safe; writing `#[unsafe(..)]` is
// not permitted on non-builtin attributes or normal builtin attributes
(Some(AttributeSafety::Normal) | None, Safety::Unsafe(unsafe_span)) => {
// - Normal builtin attribute
// - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes
(Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => {
psess.dcx().emit_err(errors::InvalidAttrUnsafe {
span: unsafe_span,
name: attr_item.path.clone(),
Expand All @@ -224,9 +223,8 @@ pub fn check_attribute_safety(
}

// - Non-builtin attribute
// - No explicit `#[unsafe(..)]` written.
(None, Safety::Default) => {
// OK
(None, Safety::Unsafe(_) | Safety::Default) => {
// OK (not checked here)
}

(
Expand Down
33 changes: 1 addition & 32 deletions compiler/rustc_codegen_ssa/src/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ use rustc_middle::middle::exported_symbols::{
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
use rustc_span::sym;
use rustc_target::spec::{Cc, LinkOutputKind, LinkerFlavor, Lld};
use tracing::{debug, warn};

Expand Down Expand Up @@ -1324,37 +1323,7 @@ struct WasmLd<'a> {

impl<'a> WasmLd<'a> {
fn new(cmd: Command, sess: &'a Session) -> WasmLd<'a> {
// If the atomics feature is enabled for wasm then we need a whole bunch
// of flags:
//
// * `--shared-memory` - the link won't even succeed without this, flags
// the one linear memory as `shared`
//
// * `--max-memory=1G` - when specifying a shared memory this must also
// be specified. We conservatively choose 1GB but users should be able
// to override this with `-C link-arg`.
//
// * `--import-memory` - it doesn't make much sense for memory to be
// exported in a threaded module because typically you're
// sharing memory and instantiating the module multiple times. As a
// result if it were exported then we'd just have no sharing.
//
// On wasm32-unknown-unknown, we also export symbols for glue code to use:
// * `--export=*tls*` - when `#[thread_local]` symbols are used these
// symbols are how the TLS segments are initialized and configured.
let mut wasm_ld = WasmLd { cmd, sess };
if sess.target_features.contains(&sym::atomics) {
wasm_ld.link_args(&["--shared-memory", "--max-memory=1073741824", "--import-memory"]);
if sess.target.os == "unknown" || sess.target.os == "none" {
wasm_ld.link_args(&[
"--export=__wasm_init_tls",
"--export=__tls_size",
"--export=__tls_align",
"--export=__tls_base",
]);
}
}
wasm_ld
WasmLd { cmd, sess }
}
}

Expand Down
15 changes: 11 additions & 4 deletions compiler/rustc_error_codes/src/error_codes/E0608.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,25 @@
An attempt to use index on a type which doesn't implement the `std::ops::Index`
trait was performed.
Attempted to index a value whose type doesn't implement the
`std::ops::Index` trait.

Erroneous code example:

```compile_fail,E0608
0u8[2]; // error: cannot index into a value of type `u8`
```

To be able to index into a type it needs to implement the `std::ops::Index`
trait. Example:
Only values with types that implement the `std::ops::Index` trait
can be indexed with square brackets. Example:

```
let v: Vec<u8> = vec![0, 1, 2, 3];

// The `Vec` type implements the `Index` trait so you can do:
println!("{}", v[2]);
```

Tuples and structs are indexed with dot (`.`), not with brackets (`[]`),
and tuple element names are their positions:
```ignore(pseudo code)
// this (pseudo code) expression is true for any tuple:
tuple == (tuple.0, tuple.1, ...)
```
17 changes: 16 additions & 1 deletion compiler/rustc_expand/src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use rustc_ast::attr::{AttributeExt, MarkedAttrs};
use rustc_ast::token::MetaVarKind;
use rustc_ast::tokenstream::TokenStream;
use rustc_ast::visit::{AssocCtxt, Visitor};
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind, Safety};
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_data_structures::sync;
use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed, PResult};
Expand Down Expand Up @@ -345,6 +345,21 @@ pub trait AttrProcMacro {
annotation: TokenStream,
annotated: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed>;

// Default implementation for safe attributes; override if the attribute can be unsafe.
fn expand_with_safety<'cx>(
&self,
ecx: &'cx mut ExtCtxt<'_>,
safety: Safety,
span: Span,
annotation: TokenStream,
annotated: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed> {
if let Safety::Unsafe(span) = safety {
ecx.dcx().span_err(span, "unnecessary `unsafe` on safe attribute");
}
self.expand(ecx, span, annotation, annotated)
}
}

impl<F> AttrProcMacro for F
Expand Down
9 changes: 8 additions & 1 deletion compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -812,11 +812,12 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
_ => item.to_tokens(),
};
let attr_item = attr.get_normal_item();
let safety = attr_item.unsafety;
if let AttrArgs::Eq { .. } = attr_item.args {
self.cx.dcx().emit_err(UnsupportedKeyValue { span });
}
let inner_tokens = attr_item.args.inner_tokens();
match expander.expand(self.cx, span, inner_tokens, tokens) {
match expander.expand_with_safety(self.cx, safety, span, inner_tokens, tokens) {
Ok(tok_result) => {
let fragment = self.parse_ast_fragment(
tok_result,
Expand All @@ -840,6 +841,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
Err(guar) => return ExpandResult::Ready(fragment_kind.dummy(span, guar)),
}
} else if let SyntaxExtensionKind::LegacyAttr(expander) = ext {
// `LegacyAttr` is only used for builtin attribute macros, which have their
// safety checked by `check_builtin_meta_item`, so we don't need to check
// `unsafety` here.
match validate_attr::parse_meta(&self.cx.sess.psess, &attr) {
Ok(meta) => {
let item_clone = macro_stats.then(|| item.clone());
Expand Down Expand Up @@ -882,6 +886,9 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
}
}
} else if let SyntaxExtensionKind::NonMacroAttr = ext {
if let ast::Safety::Unsafe(span) = attr.get_normal_item().unsafety {
self.cx.dcx().span_err(span, "unnecessary `unsafe` on safe attribute");
}
// `-Zmacro-stats` ignores these because they don't do any real expansion.
self.cx.expanded_inert_attrs.mark(&attr);
item.visit_attrs(|attrs| attrs.insert(pos, attr));
Expand Down
58 changes: 49 additions & 9 deletions compiler/rustc_expand/src/mbe/macro_rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use rustc_ast::token::NtPatKind::*;
use rustc_ast::token::TokenKind::*;
use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
use rustc_ast::tokenstream::{self, DelimSpan, TokenStream};
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId, Safety};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
Expand Down Expand Up @@ -131,6 +131,7 @@ pub(super) enum MacroRule {
Func { lhs: Vec<MatcherLoc>, lhs_span: Span, rhs: mbe::TokenTree },
/// An attr rule, for use with `#[m]`
Attr {
unsafe_rule: bool,
args: Vec<MatcherLoc>,
args_span: Span,
body: Vec<MatcherLoc>,
Expand Down Expand Up @@ -247,8 +248,19 @@ impl TTMacroExpander for MacroRulesMacroExpander {

impl AttrProcMacro for MacroRulesMacroExpander {
fn expand(
&self,
_cx: &mut ExtCtxt<'_>,
_sp: Span,
_args: TokenStream,
_body: TokenStream,
) -> Result<TokenStream, ErrorGuaranteed> {
unreachable!("`expand` called on `MacroRulesMacroExpander`, expected `expand_with_safety`")
}

fn expand_with_safety(
&self,
cx: &mut ExtCtxt<'_>,
safety: Safety,
sp: Span,
args: TokenStream,
body: TokenStream,
Expand All @@ -260,6 +272,7 @@ impl AttrProcMacro for MacroRulesMacroExpander {
self.node_id,
self.name,
self.transparency,
safety,
args,
body,
&self.rules,
Expand Down Expand Up @@ -408,6 +421,7 @@ fn expand_macro_attr(
node_id: NodeId,
name: Ident,
transparency: Transparency,
safety: Safety,
args: TokenStream,
body: TokenStream,
rules: &[MacroRule],
Expand All @@ -429,13 +443,26 @@ fn expand_macro_attr(
// Track nothing for the best performance.
match try_match_macro_attr(psess, name, &args, &body, rules, &mut NoopTracker) {
Ok((i, rule, named_matches)) => {
let MacroRule::Attr { rhs, .. } = rule else {
let MacroRule::Attr { rhs, unsafe_rule, .. } = rule else {
panic!("try_macro_match_attr returned non-attr rule");
};
let mbe::TokenTree::Delimited(rhs_span, _, rhs) = rhs else {
cx.dcx().span_bug(sp, "malformed macro rhs");
};

match (safety, unsafe_rule) {
(Safety::Default, false) | (Safety::Unsafe(_), true) => {}
(Safety::Default, true) => {
cx.dcx().span_err(sp, "unsafe attribute invocation requires `unsafe`");
}
(Safety::Unsafe(span), false) => {
cx.dcx().span_err(span, "unnecessary `unsafe` on safe attribute invocation");
}
(Safety::Safe(span), _) => {
cx.dcx().span_bug(span, "unexpected `safe` keyword");
}
}

let id = cx.current_expansion.id;
let tts = transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id)
.map_err(|e| e.emit())?;
Expand Down Expand Up @@ -681,6 +708,11 @@ pub fn compile_declarative_macro(
let mut rules = Vec::new();

while p.token != token::Eof {
let unsafe_rule = p.eat_keyword_noexpect(kw::Unsafe);
let unsafe_keyword_span = p.prev_token.span;
if unsafe_rule && let Some(guar) = check_no_eof(sess, &p, "expected `attr`") {
return dummy_syn_ext(guar);
}
let (args, is_derive) = if p.eat_keyword_noexpect(sym::attr) {
kinds |= MacroKinds::ATTR;
if !features.macro_attr() {
Expand All @@ -705,6 +737,10 @@ pub fn compile_declarative_macro(
feature_err(sess, sym::macro_derive, span, "`macro_rules!` derives are unstable")
.emit();
}
if unsafe_rule {
sess.dcx()
.span_err(unsafe_keyword_span, "`unsafe` is only supported on `attr` rules");
}
if let Some(guar) = check_no_eof(sess, &p, "expected `()` after `derive`") {
return dummy_syn_ext(guar);
}
Expand All @@ -730,6 +766,10 @@ pub fn compile_declarative_macro(
(None, true)
} else {
kinds |= MacroKinds::BANG;
if unsafe_rule {
sess.dcx()
.span_err(unsafe_keyword_span, "`unsafe` is only supported on `attr` rules");
}
(None, false)
};
let lhs_tt = p.parse_token_tree();
Expand All @@ -741,10 +781,10 @@ pub fn compile_declarative_macro(
if let Some(guar) = check_no_eof(sess, &p, "expected right-hand side of macro rule") {
return dummy_syn_ext(guar);
}
let rhs_tt = p.parse_token_tree();
let rhs_tt = parse_one_tt(rhs_tt, RulePart::Body, sess, node_id, features, edition);
check_emission(check_rhs(sess, &rhs_tt));
check_emission(check_meta_variables(&sess.psess, node_id, args.as_ref(), &lhs_tt, &rhs_tt));
let rhs = p.parse_token_tree();
let rhs = parse_one_tt(rhs, RulePart::Body, sess, node_id, features, edition);
check_emission(check_rhs(sess, &rhs));
check_emission(check_meta_variables(&sess.psess, node_id, args.as_ref(), &lhs_tt, &rhs));
let lhs_span = lhs_tt.span();
// Convert the lhs into `MatcherLoc` form, which is better for doing the
// actual matching.
Expand All @@ -760,11 +800,11 @@ pub fn compile_declarative_macro(
};
let args = mbe::macro_parser::compute_locs(&delimited.tts);
let body_span = lhs_span;
rules.push(MacroRule::Attr { args, args_span, body: lhs, body_span, rhs: rhs_tt });
rules.push(MacroRule::Attr { unsafe_rule, args, args_span, body: lhs, body_span, rhs });
} else if is_derive {
rules.push(MacroRule::Derive { body: lhs, body_span: lhs_span, rhs: rhs_tt });
rules.push(MacroRule::Derive { body: lhs, body_span: lhs_span, rhs });
} else {
rules.push(MacroRule::Func { lhs, lhs_span, rhs: rhs_tt });
rules.push(MacroRule::Func { lhs, lhs_span, rhs });
}
if p.token == token::Eof {
break;
Expand Down
27 changes: 6 additions & 21 deletions compiler/rustc_hir_typeck/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3551,35 +3551,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
);
// Try to give some advice about indexing tuples.
if let ty::Tuple(types) = base_t.kind() {
let mut needs_note = true;
// If the index is an integer, we can show the actual
// fixed expression:
err.help(
"tuples are indexed with a dot and a literal index: `tuple.0`, `tuple.1`, etc.",
);
// If index is an unsuffixed integer, show the fixed expression:
if let ExprKind::Lit(lit) = idx.kind
&& let ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) = lit.node
&& i.get()
< types
.len()
.try_into()
.expect("expected tuple index to be < usize length")
&& i.get() < types.len().try_into().expect("tuple length fits in u128")
{
err.span_suggestion(
brackets_span,
"to access tuple elements, use",
format!("to access tuple element `{i}`, use"),
format!(".{i}"),
Applicability::MachineApplicable,
);
needs_note = false;
} else if let ExprKind::Path(..) = idx.peel_borrows().kind {
err.span_label(
idx.span,
"cannot access tuple elements at a variable index",
);
}
if needs_note {
err.help(
"to access tuple elements, use tuple indexing \
syntax (e.g., `tuple.0`)",
);
}
}

Expand Down
Loading
Loading