diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:24 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:24 +0000 |
commit | 023939b627b7dc93b01471f7d41fb8553ddb4ffa (patch) | |
tree | 60fc59477c605c72b0a1051409062ddecc43f877 /compiler/rustc_builtin_macros/src | |
parent | Adding debian version 1.72.1+dfsg1-1. (diff) | |
download | rustc-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')
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( |