summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_builtin_macros/src
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:24 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:24 +0000
commit023939b627b7dc93b01471f7d41fb8553ddb4ffa (patch)
tree60fc59477c605c72b0a1051409062ddecc43f877 /compiler/rustc_builtin_macros/src
parentAdding debian version 1.72.1+dfsg1-1. (diff)
downloadrustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.tar.xz
rustc-023939b627b7dc93b01471f7d41fb8553ddb4ffa.zip
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_builtin_macros/src')
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs21
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/cfg_eval.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs8
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs27
-rw-r--r--compiler/rustc_builtin_macros/src/edition_panic.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs46
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs52
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs46
-rw-r--r--compiler/rustc_builtin_macros/src/format_foreign.rs17
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs53
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs11
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs31
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs35
22 files changed, 223 insertions, 163 deletions
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 6187e4f51..9e66eaf73 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -157,8 +157,7 @@ pub fn parse_asm_args<'a>(
} else if p.eat_keyword(sym::sym) {
let expr = p.parse_expr()?;
let ast::ExprKind::Path(qself, path) = &expr.kind else {
- let err = diag
- .create_err(errors::AsmSymNoPath { span: expr.span });
+ let err = diag.create_err(errors::AsmSymNoPath { span: expr.span });
return Err(err);
};
let sym = ast::InlineAsmSym {
@@ -402,7 +401,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>, args: &mut AsmArgs) -> PResult<'a,
// should have errored above during parsing
[] => unreachable!(),
[(abi, _span)] => args.clobber_abis.push((*abi, full_span)),
- [abis @ ..] => {
+ abis => {
for (abi, span) in abis {
args.clobber_abis.push((*abi, *span));
}
@@ -576,7 +575,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
|| named_pos.contains_key(&idx)
|| args.reg_args.contains(idx)
{
- let msg = format!("invalid reference to argument at index {}", idx);
+ let msg = format!("invalid reference to argument at index {idx}");
let mut err = ecx.struct_span_err(span, msg);
err.span_label(span, "from here");
@@ -589,9 +588,9 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
""
};
let msg = match positional_args {
- 0 => format!("no {}arguments were given", positional),
- 1 => format!("there is 1 {}argument", positional),
- x => format!("there are {} {}arguments", x, positional),
+ 0 => format!("no {positional}arguments were given"),
+ 1 => format!("there is 1 {positional}argument"),
+ x => format!("there are {x} {positional}arguments"),
};
err.note(msg);
@@ -625,7 +624,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
match args.named_args.get(&Symbol::intern(name)) {
Some(&idx) => Some(idx),
None => {
- let msg = format!("there is no argument named `{}`", name);
+ let msg = format!("there is no argument named `{name}`");
let span = arg.position_span;
ecx.struct_span_err(
template_span
@@ -698,8 +697,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
err.span_label(sp, msg);
err.help(format!(
"if this argument is intentionally unused, \
- consider using it in an asm comment: `\"/*{} */\"`",
- help_str
+ consider using it in an asm comment: `\"/*{help_str} */\"`"
));
err.emit();
}
@@ -713,8 +711,7 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
}
err.help(format!(
"if these arguments are intentionally unused, \
- consider using them in an asm comment: `\"/*{} */\"`",
- help_str
+ consider using them in an asm comment: `\"/*{help_str} */\"`"
));
err.emit();
}
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index ab4ea9c8c..9302db104 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -4,8 +4,9 @@ use crate::edition_panic::use_panic_2021;
use crate::errors;
use rustc_ast::ptr::P;
use rustc_ast::token;
+use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
-use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, MacDelimiter, Path, PathSegment, UnOp};
+use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp};
use rustc_ast_pretty::pprust;
use rustc_errors::PResult;
use rustc_expand::base::{DummyResult, ExtCtxt, MacEager, MacResult};
@@ -58,7 +59,7 @@ pub fn expand_assert<'cx>(
path: panic_path(),
args: P(DelimArgs {
dspan: DelimSpan::from_single(call_site_span),
- delim: MacDelimiter::Parenthesis,
+ delim: Delimiter::Parenthesis,
tokens,
}),
})),
@@ -68,7 +69,7 @@ pub fn expand_assert<'cx>(
// If `generic_assert` is enabled, generates rich captured outputs
//
// FIXME(c410-f3r) See https://github.com/rust-lang/rust/issues/96949
- else if let Some(features) = cx.ecfg.features && features.generic_assert {
+ else if cx.ecfg.features.generic_assert {
context::Context::new(cx, call_site_span).build(cond_expr, panic_path())
}
// If `generic_assert` is not enabled, only outputs a literal "assertion failed: ..."
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 902c1e40c..bda473120 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -1,9 +1,10 @@
use rustc_ast::{
ptr::P,
token,
+ token::Delimiter,
tokenstream::{DelimSpan, TokenStream, TokenTree},
- BinOpKind, BorrowKind, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MacDelimiter, MethodCall,
- Mutability, Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
+ BinOpKind, BorrowKind, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MethodCall, Mutability,
+ Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeKind, DUMMY_NODE_ID,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::FxHashSet;
@@ -179,7 +180,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
path: panic_path,
args: P(DelimArgs {
dspan: DelimSpan::from_single(self.span),
- delim: MacDelimiter::Parenthesis,
+ delim: Delimiter::Parenthesis,
tokens: initial.into_iter().chain(captures).collect::<TokenStream>(),
}),
})),
@@ -236,7 +237,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
ExprKind::If(local_expr, _, _) => {
self.manage_cond_expr(local_expr);
}
- ExprKind::Index(prefix, suffix) => {
+ ExprKind::Index(prefix, suffix, _) => {
self.manage_cond_expr(prefix);
self.manage_cond_expr(suffix);
}
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index 1397cee7a..31cac5184 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -24,7 +24,7 @@ pub fn expand_cfg(
&cfg,
&cx.sess.parse_sess,
cx.current_expansion.lint_node_id,
- cx.ecfg.features,
+ Some(cx.ecfg.features),
);
MacEager::expr(cx.expr_bool(sp, matches_cfg))
}
diff --git a/compiler/rustc_builtin_macros/src/cfg_eval.rs b/compiler/rustc_builtin_macros/src/cfg_eval.rs
index 49401e9ca..f826c6e77 100644
--- a/compiler/rustc_builtin_macros/src/cfg_eval.rs
+++ b/compiler/rustc_builtin_macros/src/cfg_eval.rs
@@ -31,10 +31,11 @@ pub(crate) fn expand(
pub(crate) fn cfg_eval(
sess: &Session,
- features: Option<&Features>,
+ features: &Features,
annotatable: Annotatable,
lint_node_id: NodeId,
) -> Annotatable {
+ let features = Some(features);
CfgEval { cfg: &mut StripUnconfigured { sess, features, config_tokens: true, lint_node_id } }
.configure_annotatable(annotatable)
// Since the item itself has already been configured by the `InvocationCollector`,
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 9ba98d0a5..b468abe32 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -144,7 +144,7 @@ fn cs_clone_simple(
}
_ => cx.span_bug(
trait_span,
- format!("unexpected substructure in simple `derive({})`", name),
+ format!("unexpected substructure in simple `derive({name})`"),
),
}
}
@@ -178,10 +178,10 @@ fn cs_clone(
vdata = &variant.data;
}
EnumTag(..) | AllFieldlessEnum(..) => {
- cx.span_bug(trait_span, format!("enum tags in `derive({})`", name,))
+ cx.span_bug(trait_span, format!("enum tags in `derive({name})`",))
}
StaticEnum(..) | StaticStruct(..) => {
- cx.span_bug(trait_span, format!("associated function in `derive({})`", name))
+ cx.span_bug(trait_span, format!("associated function in `derive({name})`"))
}
}
@@ -193,7 +193,7 @@ fn cs_clone(
let Some(ident) = field.name else {
cx.span_bug(
trait_span,
- format!("unnamed field in normal struct in `derive({})`", name,),
+ format!("unnamed field in normal struct in `derive({name})`",),
);
};
let call = subcall(cx, field);
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 4401cf8a9..ea81cee78 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -61,8 +61,8 @@ pub fn cs_cmp(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> Bl
|cx, fold| match fold {
CsFold::Single(field) => {
let [other_expr] = &field.other_selflike_exprs[..] else {
- cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
- };
+ cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
+ };
let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
cx.expr_call_global(field.span, cmp_path.clone(), args)
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 54b6cb7d7..a5b3a504e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -94,8 +94,8 @@ fn cs_partial_cmp(
|cx, fold| match fold {
CsFold::Single(field) => {
let [other_expr] = &field.other_selflike_exprs[..] else {
- cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
- };
+ cx.span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`");
+ };
let args = thin_vec![field.self_expr.clone(), other_expr.clone()];
cx.expr_call_global(field.span, partial_cmp_path.clone(), args)
}
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index 3921533c8..bcf11cb4c 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -204,7 +204,7 @@ where
let fields = fields
.iter()
.enumerate()
- .map(|(i, &span)| getarg(cx, span, Symbol::intern(&format!("_field{}", i)), i))
+ .map(|(i, &span)| getarg(cx, span, Symbol::intern(&format!("_field{i}")), i))
.collect();
cx.expr_call(trait_span, path_expr, fields)
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index a3b11309d..2dc20c324 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -173,7 +173,7 @@ fn encodable_substructure(
for (i, &FieldInfo { name, ref self_expr, span, .. }) in fields.iter().enumerate() {
let name = match name {
Some(id) => id.name,
- None => Symbol::intern(&format!("_field{}", i)),
+ None => Symbol::intern(&format!("_field{i}")),
};
let self_ref = cx.expr_addr_of(span, self_expr.clone());
let enc =
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 4ba09335c..6597ee3cf 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1134,9 +1134,14 @@ impl<'a> MethodDef<'a> {
trait_: &TraitDef<'b>,
enum_def: &'b EnumDef,
type_ident: Ident,
- selflike_args: ThinVec<P<Expr>>,
+ mut selflike_args: ThinVec<P<Expr>>,
nonselflike_args: &[P<Expr>],
) -> BlockOrExpr {
+ assert!(
+ !selflike_args.is_empty(),
+ "static methods must use `expand_static_enum_method_body`",
+ );
+
let span = trait_.span;
let variants = &enum_def.variants;
@@ -1144,10 +1149,15 @@ impl<'a> MethodDef<'a> {
let unify_fieldless_variants =
self.fieldless_variants_strategy == FieldlessVariantsStrategy::Unify;
- // There is no sensible code to be generated for *any* deriving on a
- // zero-variant enum. So we just generate a failing expression.
+ // For zero-variant enum, this function body is unreachable. Generate
+ // `match *self {}`. This produces machine code identical to `unsafe {
+ // core::intrinsics::unreachable() }` while being safe and stable.
if variants.is_empty() {
- return BlockOrExpr(ThinVec::new(), Some(deriving::call_unreachable(cx, span)));
+ selflike_args.truncate(1);
+ let match_arg = cx.expr_deref(span, selflike_args.pop().unwrap());
+ let match_arms = ThinVec::new();
+ let expr = cx.expr_match(span, match_arg, match_arms);
+ return BlockOrExpr(ThinVec::new(), Some(expr));
}
let prefixes = iter::once("__self".to_string())
@@ -1156,7 +1166,7 @@ impl<'a> MethodDef<'a> {
.iter()
.enumerate()
.skip(1)
- .map(|(arg_count, _selflike_arg)| format!("__arg{}", arg_count)),
+ .map(|(arg_count, _selflike_arg)| format!("__arg{arg_count}")),
)
.collect::<Vec<String>>();
@@ -1171,7 +1181,7 @@ impl<'a> MethodDef<'a> {
let get_tag_pieces = |cx: &ExtCtxt<'_>| {
let tag_idents: Vec<_> = prefixes
.iter()
- .map(|name| Ident::from_str_and_span(&format!("{}_tag", name), span))
+ .map(|name| Ident::from_str_and_span(&format!("{name}_tag"), span))
.collect();
let mut tag_exprs: Vec<_> = tag_idents
@@ -1511,7 +1521,7 @@ impl<'a> TraitDef<'a> {
}
fn mk_pattern_ident(&self, prefix: &str, i: usize) -> Ident {
- Ident::from_str_and_span(&format!("{}_{}", prefix, i), self.span)
+ Ident::from_str_and_span(&format!("{prefix}_{i}"), self.span)
}
fn create_struct_pattern_fields(
@@ -1592,8 +1602,7 @@ impl<'a> TraitDef<'a> {
sp,
ast::CRATE_NODE_ID,
format!(
- "{} slice in a packed struct that derives a built-in trait",
- ty
+ "{ty} slice in a packed struct that derives a built-in trait"
),
rustc_lint_defs::BuiltinLintDiagnostics::ByteSliceInPackedStructWithDerive
);
diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs
index ef0db23ff..1e1dadab4 100644
--- a/compiler/rustc_builtin_macros/src/edition_panic.rs
+++ b/compiler/rustc_builtin_macros/src/edition_panic.rs
@@ -1,4 +1,5 @@
use rustc_ast::ptr::P;
+use rustc_ast::token::Delimiter;
use rustc_ast::tokenstream::{DelimSpan, TokenStream};
use rustc_ast::*;
use rustc_expand::base::*;
@@ -60,7 +61,7 @@ fn expand<'cx>(
},
args: P(DelimArgs {
dspan: DelimSpan::from_single(sp),
- delim: MacDelimiter::Parenthesis,
+ delim: Delimiter::Parenthesis,
tokens: tts,
}),
})),
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 8f64e3328..92da0c069 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -4,7 +4,7 @@
//
use rustc_ast::tokenstream::TokenStream;
-use rustc_ast::{self as ast, GenericArg};
+use rustc_ast::{self as ast, AstDeref, GenericArg};
use rustc_expand::base::{self, *};
use rustc_span::symbol::{kw, sym, Ident, Symbol};
use rustc_span::Span;
@@ -76,22 +76,36 @@ pub fn expand_env<'cx>(
},
};
- let sp = cx.with_def_site_ctxt(sp);
+ let span = cx.with_def_site_ctxt(sp);
let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
let e = match value {
None => {
- // Use the string literal in the code in the diagnostic to avoid confusing diagnostics,
- // e.g. when the literal contains escape sequences.
- let ast::ExprKind::Lit(ast::token::Lit { kind: ast::token::LitKind::Str, symbol: original_var, ..}) = &var_expr.kind else {
+ let ast::ExprKind::Lit(ast::token::Lit {
+ kind: ast::token::LitKind::Str | ast::token::LitKind::StrRaw(..),
+ symbol,
+ ..
+ }) = &var_expr.kind
+ else {
unreachable!("`expr_to_string` ensures this is a string lit")
};
- cx.emit_err(errors::EnvNotDefined {
- span: sp,
- msg: custom_msg,
- var: *original_var,
- help: custom_msg.is_none().then(|| help_for_missing_env_var(var.as_str())),
- });
+
+ if let Some(msg_from_user) = custom_msg {
+ cx.emit_err(errors::EnvNotDefinedWithUserMessage { span, msg_from_user });
+ } else if is_cargo_env_var(var.as_str()) {
+ cx.emit_err(errors::EnvNotDefined::CargoEnvVar {
+ span,
+ var: *symbol,
+ var_expr: var_expr.ast_deref(),
+ });
+ } else {
+ cx.emit_err(errors::EnvNotDefined::CustomEnvVar {
+ span,
+ var: *symbol,
+ var_expr: var_expr.ast_deref(),
+ });
+ }
+
return DummyResult::any(sp);
}
Some(value) => cx.expr_str(sp, value),
@@ -99,13 +113,9 @@ pub fn expand_env<'cx>(
MacEager::expr(e)
}
-fn help_for_missing_env_var(var: &str) -> errors::EnvNotDefinedHelp {
- if var.starts_with("CARGO_")
+/// Returns `true` if an environment variable from `env!` is one used by Cargo.
+fn is_cargo_env_var(var: &str) -> bool {
+ var.starts_with("CARGO_")
|| var.starts_with("DEP_")
|| matches!(var, "OUT_DIR" | "OPT_LEVEL" | "PROFILE" | "HOST" | "TARGET")
- {
- errors::EnvNotDefinedHelp::CargoVar
- } else {
- errors::EnvNotDefinedHelp::Other
- }
}
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index 7b2a375a8..fbf0395bb 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -440,43 +440,43 @@ pub(crate) struct EnvTakesArgs {
pub(crate) span: Span,
}
-//#[derive(Diagnostic)]
-//#[diag(builtin_macros_env_not_defined)]
-pub(crate) struct EnvNotDefined {
+pub(crate) struct EnvNotDefinedWithUserMessage {
pub(crate) span: Span,
- pub(crate) msg: Option<Symbol>,
- pub(crate) var: Symbol,
- pub(crate) help: Option<EnvNotDefinedHelp>,
+ pub(crate) msg_from_user: Symbol,
}
-// Hand-written implementation to support custom user messages
-impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefined {
+// Hand-written implementation to support custom user messages.
+impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for EnvNotDefinedWithUserMessage {
#[track_caller]
fn into_diagnostic(self, handler: &'a Handler) -> DiagnosticBuilder<'a, G> {
- let mut diag = if let Some(msg) = self.msg {
- #[expect(
- rustc::untranslatable_diagnostic,
- reason = "cannot translate user-provided messages"
- )]
- handler.struct_diagnostic(msg.to_string())
- } else {
- handler.struct_diagnostic(crate::fluent_generated::builtin_macros_env_not_defined)
- };
- diag.set_arg("var", self.var);
+ #[expect(
+ rustc::untranslatable_diagnostic,
+ reason = "cannot translate user-provided messages"
+ )]
+ let mut diag = handler.struct_diagnostic(self.msg_from_user.to_string());
diag.set_span(self.span);
- if let Some(help) = self.help {
- diag.subdiagnostic(help);
- }
diag
}
}
-#[derive(Subdiagnostic)]
-pub(crate) enum EnvNotDefinedHelp {
+#[derive(Diagnostic)]
+pub(crate) enum EnvNotDefined<'a> {
+ #[diag(builtin_macros_env_not_defined)]
#[help(builtin_macros_cargo)]
- CargoVar,
- #[help(builtin_macros_other)]
- Other,
+ CargoEnvVar {
+ #[primary_span]
+ span: Span,
+ var: Symbol,
+ var_expr: &'a rustc_ast::Expr,
+ },
+ #[diag(builtin_macros_env_not_defined)]
+ #[help(builtin_macros_custom)]
+ CustomEnvVar {
+ #[primary_span]
+ span: Span,
+ var: Symbol,
+ var_expr: &'a rustc_ast::Expr,
+ },
}
#[derive(Diagnostic)]
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 4c878785b..ede95dbf8 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1,6 +1,6 @@
use rustc_ast::ptr::P;
-use rustc_ast::token;
use rustc_ast::tokenstream::TokenStream;
+use rustc_ast::{token, StmtKind};
use rustc_ast::{
Expr, ExprKind, FormatAlignment, FormatArgPosition, FormatArgPositionKind, FormatArgs,
FormatArgsPiece, FormatArgument, FormatArgumentKind, FormatArguments, FormatCount,
@@ -163,7 +163,7 @@ fn make_format_args(
let MacroInput { fmtstr: efmt, mut args, is_direct_literal } = input;
- let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt, msg) {
+ let (fmt_str, fmt_style, fmt_span) = match expr_to_spanned_string(ecx, efmt.clone(), msg) {
Ok(mut fmt) if append_newline => {
fmt.0 = Symbol::intern(&format!("{}\n", fmt.0));
fmt
@@ -171,17 +171,33 @@ fn make_format_args(
Ok(fmt) => fmt,
Err(err) => {
if let Some((mut err, suggested)) = err {
- let sugg_fmt = match args.explicit_args().len() {
- 0 => "{}".to_string(),
- _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
- };
if !suggested {
- err.span_suggestion(
- unexpanded_fmt_span.shrink_to_lo(),
- "you might be missing a string literal to format with",
- format!("\"{}\", ", sugg_fmt),
- Applicability::MaybeIncorrect,
- );
+ if let ExprKind::Block(block, None) = &efmt.kind
+ && block.stmts.len() == 1
+ && let StmtKind::Expr(expr) = &block.stmts[0].kind
+ && let ExprKind::Path(None, path) = &expr.kind
+ && path.is_potential_trivial_const_arg()
+ {
+ err.multipart_suggestion(
+ "quote your inlined format argument to use as string literal",
+ vec![
+ (unexpanded_fmt_span.shrink_to_hi(), "\"".to_string()),
+ (unexpanded_fmt_span.shrink_to_lo(), "\"".to_string()),
+ ],
+ Applicability::MaybeIncorrect,
+ );
+ } else {
+ let sugg_fmt = match args.explicit_args().len() {
+ 0 => "{}".to_string(),
+ _ => format!("{}{{}}", "{} ".repeat(args.explicit_args().len())),
+ };
+ err.span_suggestion(
+ unexpanded_fmt_span.shrink_to_lo(),
+ "you might be missing a string literal to format with",
+ format!("\"{sugg_fmt}\", "),
+ Applicability::MaybeIncorrect,
+ );
+ }
}
err.emit();
}
@@ -668,7 +684,7 @@ fn report_invalid_references(
let num_args_desc = match args.explicit_args().len() {
0 => "no arguments were given".to_string(),
1 => "there is 1 argument".to_string(),
- n => format!("there are {} arguments", n),
+ n => format!("there are {n} arguments"),
};
let mut e;
@@ -780,7 +796,7 @@ fn report_invalid_references(
if num_placeholders == 1 {
"is 1 argument".to_string()
} else {
- format!("are {} arguments", num_placeholders)
+ format!("are {num_placeholders} arguments")
},
),
);
@@ -811,7 +827,7 @@ fn report_invalid_references(
};
e = ecx.struct_span_err(
span,
- format!("invalid reference to positional {} ({})", arg_list, num_args_desc),
+ format!("invalid reference to positional {arg_list} ({num_args_desc})"),
);
e.note("positional arguments are zero-based");
}
diff --git a/compiler/rustc_builtin_macros/src/format_foreign.rs b/compiler/rustc_builtin_macros/src/format_foreign.rs
index bd5356575..2fc8a0763 100644
--- a/compiler/rustc_builtin_macros/src/format_foreign.rs
+++ b/compiler/rustc_builtin_macros/src/format_foreign.rs
@@ -86,10 +86,7 @@ pub(crate) mod printf {
'-' => c_left = true,
'+' => c_plus = true,
_ => {
- return Err(Some(format!(
- "the flag `{}` is unknown or unsupported",
- c
- )));
+ return Err(Some(format!("the flag `{c}` is unknown or unsupported")));
}
}
}
@@ -268,21 +265,21 @@ pub(crate) mod printf {
impl Num {
fn from_str(s: &str, arg: Option<&str>) -> Self {
if let Some(arg) = arg {
- Num::Arg(arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{:?}`", arg)))
+ Num::Arg(arg.parse().unwrap_or_else(|_| panic!("invalid format arg `{arg:?}`")))
} else if s == "*" {
Num::Next
} else {
- Num::Num(s.parse().unwrap_or_else(|_| panic!("invalid format num `{:?}`", s)))
+ Num::Num(s.parse().unwrap_or_else(|_| panic!("invalid format num `{s:?}`")))
}
}
fn translate(&self, s: &mut String) -> std::fmt::Result {
use std::fmt::Write;
match *self {
- Num::Num(n) => write!(s, "{}", n),
+ Num::Num(n) => write!(s, "{n}"),
Num::Arg(n) => {
let n = n.checked_sub(1).ok_or(std::fmt::Error)?;
- write!(s, "{}$", n)
+ write!(s, "{n}$")
}
Num::Next => write!(s, "*"),
}
@@ -626,8 +623,8 @@ pub mod shell {
impl Substitution<'_> {
pub fn as_str(&self) -> String {
match self {
- Substitution::Ordinal(n, _) => format!("${}", n),
- Substitution::Name(n, _) => format!("${}", n),
+ Substitution::Ordinal(n, _) => format!("${n}"),
+ Substitution::Name(n, _) => format!("${n}"),
Substitution::Escape(_) => "$$".into(),
}
}
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 577247193..1bec00add 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -2,7 +2,7 @@ use crate::util::check_builtin_macro_attribute;
use crate::errors;
use rustc_ast::expand::allocator::{
- global_fn_name, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
+ global_fn_name, AllocatorMethod, AllocatorMethodInput, AllocatorTy, ALLOCATOR_METHODS,
};
use rustc_ast::ptr::P;
use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
@@ -70,19 +70,13 @@ struct AllocFnFactory<'a, 'b> {
impl AllocFnFactory<'_, '_> {
fn allocator_fn(&self, method: &AllocatorMethod) -> Stmt {
let mut abi_args = ThinVec::new();
- let mut i = 0;
- let mut mk = || {
- let name = Ident::from_str_and_span(&format!("arg{}", i), self.span);
- i += 1;
- name
- };
- let args = method.inputs.iter().map(|ty| self.arg_ty(ty, &mut abi_args, &mut mk)).collect();
+ let args = method.inputs.iter().map(|input| self.arg_ty(input, &mut abi_args)).collect();
let result = self.call_allocator(method.name, args);
- let (output_ty, output_expr) = self.ret_ty(&method.output, result);
+ let output_ty = self.ret_ty(&method.output);
let decl = self.cx.fn_decl(abi_args, ast::FnRetTy::Ty(output_ty));
let header = FnHeader { unsafety: Unsafe::Yes(self.span), ..FnHeader::default() };
let sig = FnSig { decl, header, span: self.span };
- let body = Some(self.cx.block_expr(output_expr));
+ let body = Some(self.cx.block_expr(result));
let kind = ItemKind::Fn(Box::new(Fn {
defaultness: ast::Defaultness::Final,
sig,
@@ -113,18 +107,19 @@ impl AllocFnFactory<'_, '_> {
thin_vec![self.cx.attr_word(sym::rustc_std_internal_symbol, self.span)]
}
- fn arg_ty(
- &self,
- ty: &AllocatorTy,
- args: &mut ThinVec<Param>,
- ident: &mut dyn FnMut() -> Ident,
- ) -> P<Expr> {
- match *ty {
+ fn arg_ty(&self, input: &AllocatorMethodInput, args: &mut ThinVec<Param>) -> P<Expr> {
+ match input.ty {
AllocatorTy::Layout => {
+ // If an allocator method is ever introduced having multiple
+ // Layout arguments, these argument names need to be
+ // disambiguated somehow. Currently the generated code would
+ // fail to compile with "identifier is bound more than once in
+ // this parameter list".
+ let size = Ident::from_str_and_span("size", self.span);
+ let align = Ident::from_str_and_span("align", self.span);
+
let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span));
let ty_usize = self.cx.ty_path(usize);
- let size = ident();
- let align = ident();
args.push(self.cx.param(self.span, size, ty_usize.clone()));
args.push(self.cx.param(self.span, align, ty_usize));
@@ -138,14 +133,13 @@ impl AllocFnFactory<'_, '_> {
}
AllocatorTy::Ptr => {
- let ident = ident();
+ let ident = Ident::from_str_and_span(input.name, self.span);
args.push(self.cx.param(self.span, ident, self.ptr_u8()));
- let arg = self.cx.expr_ident(self.span, ident);
- self.cx.expr_cast(self.span, arg, self.ptr_u8())
+ self.cx.expr_ident(self.span, ident)
}
AllocatorTy::Usize => {
- let ident = ident();
+ let ident = Ident::from_str_and_span(input.name, self.span);
args.push(self.cx.param(self.span, ident, self.usize()));
self.cx.expr_ident(self.span, ident)
}
@@ -156,18 +150,11 @@ impl AllocFnFactory<'_, '_> {
}
}
- fn ret_ty(&self, ty: &AllocatorTy, expr: P<Expr>) -> (P<Ty>, P<Expr>) {
+ fn ret_ty(&self, ty: &AllocatorTy) -> P<Ty> {
match *ty {
- AllocatorTy::ResultPtr => {
- // We're creating:
- //
- // #expr as *mut u8
-
- let expr = self.cx.expr_cast(self.span, expr, self.ptr_u8());
- (self.ptr_u8(), expr)
- }
+ AllocatorTy::ResultPtr => self.ptr_u8(),
- AllocatorTy::Unit => (self.cx.ty(self.span, TyKind::Tup(ThinVec::new())), expr),
+ AllocatorTy::Unit => self.cx.ty(self.span, TyKind::Tup(ThinVec::new())),
AllocatorTy::Layout | AllocatorTy::Usize | AllocatorTy::Ptr => {
panic!("can't convert `AllocatorTy` to an output")
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index b35a2e2a2..dae1bc5bf 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -5,6 +5,7 @@ use rustc_ast::{self as ast, attr, NodeId};
use rustc_ast_pretty::pprust;
use rustc_expand::base::{parse_macro_name_and_helper_attrs, ExtCtxt, ResolverExpand};
use rustc_expand::expand::{AstFragment, ExpansionConfig};
+use rustc_feature::Features;
use rustc_session::Session;
use rustc_span::hygiene::AstPass;
use rustc_span::source_map::SourceMap;
@@ -46,13 +47,14 @@ struct CollectProcMacros<'a> {
pub fn inject(
krate: &mut ast::Crate,
sess: &Session,
+ features: &Features,
resolver: &mut dyn ResolverExpand,
is_proc_macro_crate: bool,
has_proc_macro_decls: bool,
is_test_crate: bool,
handler: &rustc_errors::Handler,
) {
- let ecfg = ExpansionConfig::default("proc_macro".to_string());
+ let ecfg = ExpansionConfig::default("proc_macro".to_string(), features);
let mut cx = ExtCtxt::new(sess, ecfg, resolver, None);
let mut collect = CollectProcMacros {
@@ -89,7 +91,9 @@ impl<'a> CollectProcMacros<'a> {
}
fn collect_custom_derive(&mut self, item: &'a ast::Item, attr: &'a ast::Attribute) {
- let Some((trait_name, proc_attrs)) = parse_macro_name_and_helper_attrs(self.handler, attr, "derive") else {
+ let Some((trait_name, proc_attrs)) =
+ parse_macro_name_and_helper_attrs(self.handler, attr, "derive")
+ else {
return;
};
@@ -177,8 +181,7 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> {
== prev_item.path.segments[0].ident.name
{
format!(
- "only one `#[{}]` attribute is allowed on any given function",
- path_str,
+ "only one `#[{path_str}]` attribute is allowed on any given function",
)
} else {
format!(
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index e613b904d..433da7423 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -149,7 +149,7 @@ pub fn expand_include<'cx>(
Ok(None) => {
if self.p.token != token::Eof {
let token = pprust::token_to_string(&self.p.token);
- let msg = format!("expected item, found `{}`", token);
+ let msg = format!("expected item, found `{token}`");
self.p.struct_span_err(self.p.token.span, msg).emit();
}
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index 6493c6f13..3ee3112f0 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -1,6 +1,7 @@
use rustc_ast::{self as ast, attr};
use rustc_expand::base::{ExtCtxt, ResolverExpand};
use rustc_expand::expand::ExpansionConfig;
+use rustc_feature::Features;
use rustc_session::Session;
use rustc_span::edition::Edition::*;
use rustc_span::hygiene::AstPass;
@@ -13,6 +14,7 @@ pub fn inject(
pre_configured_attrs: &[ast::Attribute],
resolver: &mut dyn ResolverExpand,
sess: &Session,
+ features: &Features,
) -> usize {
let orig_num_items = krate.items.len();
let edition = sess.parse_sess.edition;
@@ -39,25 +41,34 @@ pub fn inject(
let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
let call_site = DUMMY_SP.with_call_site_ctxt(expn_id.to_expn_id());
- let ecfg = ExpansionConfig::default("std_lib_injection".to_string());
+ let ecfg = ExpansionConfig::default("std_lib_injection".to_string(), features);
let cx = ExtCtxt::new(sess, ecfg, resolver, None);
// .rev() to preserve ordering above in combination with insert(0, ...)
for &name in names.iter().rev() {
- let ident = if edition >= Edition2018 {
- Ident::new(name, span)
+ let ident_span = if edition >= Edition2018 { span } else { call_site };
+ let item = if name == sym::compiler_builtins {
+ // compiler_builtins is a private implementation detail. We only
+ // need to insert it into the crate graph for linking and should not
+ // expose any of its public API.
+ //
+ // FIXME(#113634) We should inject this during post-processing like
+ // we do for the panic runtime, profiler runtime, etc.
+ cx.item(
+ span,
+ Ident::new(kw::Underscore, ident_span),
+ thin_vec![],
+ ast::ItemKind::ExternCrate(Some(name)),
+ )
} else {
- Ident::new(name, call_site)
- };
- krate.items.insert(
- 0,
cx.item(
span,
- ident,
+ Ident::new(name, ident_span),
thin_vec![cx.attr_word(sym::macro_use, span)],
ast::ItemKind::ExternCrate(None),
- ),
- );
+ )
+ };
+ krate.items.insert(0, item);
}
// The crates have been injected, the assumption is that the first one is
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index 6bc4f6fc1..1580a6f6d 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -255,6 +255,7 @@ pub fn expand_test_or_bench(
ast::ItemKind::Const(
ast::ConstItem {
defaultness: ast::Defaultness::Final,
+ generics: ast::Generics::default(),
ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))),
// test::TestDescAndFn {
expr: Some(
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 81b618548..d8846a9f0 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -4,10 +4,12 @@ use rustc_ast as ast;
use rustc_ast::entry::EntryPointType;
use rustc_ast::mut_visit::{ExpectOne, *};
use rustc_ast::ptr::P;
+use rustc_ast::visit::{walk_item, Visitor};
use rustc_ast::{attr, ModKind};
use rustc_expand::base::{ExtCtxt, ResolverExpand};
use rustc_expand::expand::{AstFragment, ExpansionConfig};
use rustc_feature::Features;
+use rustc_session::lint::builtin::UNNAMEABLE_TEST_ITEMS;
use rustc_session::Session;
use rustc_span::hygiene::{AstPass, SyntaxContext, Transparency};
use rustc_span::symbol::{sym, Ident, Symbol};
@@ -39,7 +41,12 @@ struct TestCtxt<'a> {
/// Traverse the crate, collecting all the test functions, eliding any
/// existing main functions, and synthesizing a main test harness
-pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn ResolverExpand) {
+pub fn inject(
+ krate: &mut ast::Crate,
+ sess: &Session,
+ features: &Features,
+ resolver: &mut dyn ResolverExpand,
+) {
let span_diagnostic = sess.diagnostic();
let panic_strategy = sess.panic_strategy();
let platform_panic_strategy = sess.target.panic_strategy;
@@ -74,7 +81,7 @@ pub fn inject(krate: &mut ast::Crate, sess: &Session, resolver: &mut dyn Resolve
resolver,
reexport_test_harness_main,
krate,
- &sess.features_untracked(),
+ features,
panic_strategy,
test_runner,
)
@@ -137,11 +144,31 @@ impl<'a> MutVisitor for TestHarnessGenerator<'a> {
let prev_tests = mem::take(&mut self.tests);
noop_visit_item_kind(&mut item.kind, self);
self.add_test_cases(item.id, span, prev_tests);
+ } else {
+ // But in those cases, we emit a lint to warn the user of these missing tests.
+ walk_item(&mut InnerItemLinter { sess: self.cx.ext_cx.sess }, &item);
}
smallvec![P(item)]
}
}
+struct InnerItemLinter<'a> {
+ sess: &'a Session,
+}
+
+impl<'a> Visitor<'a> for InnerItemLinter<'_> {
+ fn visit_item(&mut self, i: &'a ast::Item) {
+ if let Some(attr) = attr::find_by_name(&i.attrs, sym::rustc_test_marker) {
+ self.sess.parse_sess.buffer_lint(
+ UNNAMEABLE_TEST_ITEMS,
+ attr.span,
+ i.id,
+ crate::fluent_generated::builtin_macros_unnameable_test_items,
+ );
+ }
+ }
+}
+
// Beware, this is duplicated in librustc_passes/entry.rs (with
// `rustc_hir::Item`), so make sure to keep them in sync.
fn entry_point_type(item: &ast::Item, depth: usize) -> EntryPointType {
@@ -221,9 +248,7 @@ fn generate_test_harness(
panic_strategy: PanicStrategy,
test_runner: Option<ast::Path>,
) {
- let mut econfig = ExpansionConfig::default("test".to_string());
- econfig.features = Some(features);
-
+ let econfig = ExpansionConfig::default("test".to_string(), features);
let ext_cx = ExtCtxt::new(sess, econfig, resolver, None);
let expn_id = ext_cx.resolver.expansion_for_ast_pass(