diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl index 2a5bc58af3b3d..0f15899031938 100644 --- a/compiler/rustc_builtin_macros/messages.ftl +++ b/compiler/rustc_builtin_macros/messages.ftl @@ -118,6 +118,8 @@ builtin_macros_env_not_unicode = environment variable `{$var}` is not a valid Un builtin_macros_env_takes_args = `env!()` takes 1 or 2 arguments +builtin_macros_expected_comma_in_list = expected token: `,` + builtin_macros_expected_one_cfg_pattern = expected 1 cfg-pattern builtin_macros_expected_register_class_or_explicit_register = expected register class or explicit register @@ -219,12 +221,16 @@ builtin_macros_non_exhaustive_default = default variant must be exhaustive builtin_macros_non_unit_default = the `#[default]` attribute may only be used on unit enum variants .help = consider a manual implementation of `Default` +builtin_macros_only_one_argument = {$name} takes 1 argument + builtin_macros_proc_macro = `proc-macro` crate types currently cannot export any items other than functions tagged with `#[proc_macro]`, `#[proc_macro_derive]`, or `#[proc_macro_attribute]` builtin_macros_requires_cfg_pattern = macro requires a cfg-pattern as an argument .label = cfg-pattern required +builtin_macros_takes_no_arguments = {$name} takes no arguments + builtin_macros_test_bad_fn = {$kind} functions cannot be used for tests .label = `{$kind}` because of this diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs index bc94e0b972b47..064cf7d7f0f8e 100644 --- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs +++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs @@ -9,7 +9,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand( +pub(crate) fn expand( ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 137ac44157924..49b1b8cf99268 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -1,3 +1,5 @@ +use crate::errors; +use crate::util::expr_to_spanned_string; use ast::token::IdentIsRaw; use rustc_ast as ast; use rustc_ast::ptr::P; @@ -16,8 +18,6 @@ use rustc_span::{ErrorGuaranteed, InnerSpan, Span}; use rustc_target::asm::InlineAsmArch; use smallvec::smallvec; -use crate::errors; - pub struct AsmArgs { pub templates: Vec>, pub operands: Vec<(ast::InlineAsmOperand, Span)>, diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index d200179f3a0ae..c75050f270188 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -15,7 +15,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; use thin_vec::thin_vec; -pub fn expand_assert<'cx>( +pub(crate) fn expand_assert<'cx>( cx: &'cx mut ExtCtxt<'_>, span: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index 5dc9bbacd0629..827719d794493 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -11,7 +11,7 @@ use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::Span; -pub fn expand_cfg( +pub(crate) fn expand_cfg( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/compile_error.rs b/compiler/rustc_builtin_macros/src/compile_error.rs index 2f2a87fc9aa00..a08e8b2819b56 100644 --- a/compiler/rustc_builtin_macros/src/compile_error.rs +++ b/compiler/rustc_builtin_macros/src/compile_error.rs @@ -1,11 +1,11 @@ // The compiler code necessary to support the compile_error! extension. +use crate::util::get_single_str_from_tts; use rustc_ast::tokenstream::TokenStream; -use rustc_expand::base::get_single_str_from_tts; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::Span; -pub fn expand_compile_error<'cx>( +pub(crate) fn expand_compile_error<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/concat.rs b/compiler/rustc_builtin_macros/src/concat.rs index 93a7ac05a9bef..15af79ef67d4a 100644 --- a/compiler/rustc_builtin_macros/src/concat.rs +++ b/compiler/rustc_builtin_macros/src/concat.rs @@ -1,13 +1,12 @@ +use crate::errors; +use crate::util::get_exprs_from_tts; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{ExprKind, LitKind, UnOp}; -use rustc_expand::base::get_exprs_from_tts; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::symbol::Symbol; -use crate::errors; - -pub fn expand_concat( +pub(crate) fn expand_concat( cx: &mut ExtCtxt<'_>, sp: rustc_span::Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/concat_bytes.rs b/compiler/rustc_builtin_macros/src/concat_bytes.rs index 45fec2945788b..3130870df4105 100644 --- a/compiler/rustc_builtin_macros/src/concat_bytes.rs +++ b/compiler/rustc_builtin_macros/src/concat_bytes.rs @@ -1,11 +1,10 @@ +use crate::errors; +use crate::util::get_exprs_from_tts; use rustc_ast::{ptr::P, token, tokenstream::TokenStream, ExprKind, LitIntType, LitKind, UintTy}; -use rustc_expand::base::get_exprs_from_tts; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_session::errors::report_lit_error; use rustc_span::{ErrorGuaranteed, Span}; -use crate::errors; - /// Emits errors for literal expressions that are invalid inside and outside of an array. fn invalid_type_err( cx: &ExtCtxt<'_>, @@ -108,7 +107,7 @@ fn handle_array_element( None } -pub fn expand_concat_bytes( +pub(crate) fn expand_concat_bytes( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/concat_idents.rs b/compiler/rustc_builtin_macros/src/concat_idents.rs index 3ddb0ae45b51a..13729a9d250fe 100644 --- a/compiler/rustc_builtin_macros/src/concat_idents.rs +++ b/compiler/rustc_builtin_macros/src/concat_idents.rs @@ -8,7 +8,7 @@ use rustc_span::Span; use crate::errors; -pub fn expand_concat_idents<'cx>( +pub(crate) fn expand_concat_idents<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/derive.rs b/compiler/rustc_builtin_macros/src/derive.rs index 4f412cf79d91f..d14858e5c1db3 100644 --- a/compiler/rustc_builtin_macros/src/derive.rs +++ b/compiler/rustc_builtin_macros/src/derive.rs @@ -3,14 +3,18 @@ use crate::errors; use rustc_ast as ast; use rustc_ast::{GenericParamKind, ItemKind, MetaItemKind, NestedMetaItem, StmtKind}; -use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier}; +use rustc_expand::base::{ + Annotatable, DeriveResolution, ExpandResult, ExtCtxt, Indeterminate, MultiItemModifier, +}; use rustc_feature::AttributeTemplate; use rustc_parse::validate_attr; use rustc_session::Session; use rustc_span::symbol::{sym, Ident}; use rustc_span::{ErrorGuaranteed, Span}; -pub(crate) struct Expander(pub bool); +pub(crate) struct Expander { + pub is_const: bool, +} impl MultiItemModifier for Expander { fn expand( @@ -58,7 +62,12 @@ impl MultiItemModifier for Expander { report_path_args(sess, meta); meta.path.clone() }) - .map(|path| (path, dummy_annotatable(), None, self.0)) + .map(|path| DeriveResolution { + path, + item: dummy_annotatable(), + exts: None, + is_const: self.is_const, + }) .collect() } _ => vec![], @@ -67,15 +76,15 @@ impl MultiItemModifier for Expander { // Do not configure or clone items unless necessary. match &mut resolutions[..] { [] => {} - [(_, first_item, ..), others @ ..] => { - *first_item = cfg_eval( + [first, others @ ..] => { + first.item = cfg_eval( sess, features, item.clone(), ecx.current_expansion.lint_node_id, ); - for (_, item, _, _) in others { - *item = first_item.clone(); + for other in others { + other.item = first.item.clone(); } } } diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs index 26ef3da3a915c..97e2344ff30e5 100644 --- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs +++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs @@ -5,7 +5,7 @@ use rustc_ast::MetaItem; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_span::Span; -pub fn expand_deriving_copy( +pub(crate) fn expand_deriving_copy( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, @@ -28,7 +28,7 @@ pub fn expand_deriving_copy( trait_def.expand(cx, mitem, item, push); } -pub fn expand_deriving_const_param_ty( +pub(crate) fn expand_deriving_const_param_ty( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index cb1c9ef90bde7..abcb402a46f8e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, sym, Ident}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand_deriving_clone( +pub(crate) fn expand_deriving_clone( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs index 45c4467a1097c..53a1513160542 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs @@ -9,7 +9,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand_deriving_eq( +pub(crate) fn expand_deriving_eq( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs index 1d7a69540ab89..8470d466a233c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use thin_vec::thin_vec; -pub fn expand_deriving_ord( +pub(crate) fn expand_deriving_ord( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, @@ -39,7 +39,7 @@ pub fn expand_deriving_ord( trait_def.expand(cx, mitem, item, push) } -pub fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { +pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr { let test_id = Ident::new(sym::cmp, span); let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs index 234918ae42961..dc73caa4ad5be 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use thin_vec::thin_vec; -pub fn expand_deriving_partial_eq( +pub(crate) fn expand_deriving_partial_eq( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, 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 63311c897aba9..006e5a3d268a6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::{sym, Ident}; use rustc_span::Span; use thin_vec::thin_vec; -pub fn expand_deriving_partial_ord( +pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 8b681db967050..57ec0435e3e05 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -8,7 +8,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand_deriving_debug( +pub(crate) fn expand_deriving_debug( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs index 34798ab0a17b0..e9851c87aeaef 100644 --- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs @@ -10,7 +10,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand_deriving_rustc_decodable( +pub(crate) fn expand_deriving_rustc_decodable( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 328770ce10d2c..bf92ddb33701c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -12,7 +12,7 @@ use rustc_span::{ErrorGuaranteed, Span}; use smallvec::SmallVec; use thin_vec::{thin_vec, ThinVec}; -pub fn expand_deriving_default( +pub(crate) fn expand_deriving_default( cx: &ExtCtxt<'_>, span: Span, mitem: &ast::MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs index 2e5f1173825a1..3bd74d8d0198a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs +++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs @@ -94,7 +94,7 @@ use rustc_span::symbol::{sym, Ident, Symbol}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand_deriving_rustc_encodable( +pub(crate) fn expand_deriving_rustc_encodable( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 85d54e9257d8c..52c1ba1757b1e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -174,8 +174,8 @@ //! ) //! ``` -pub use StaticFields::*; -pub use SubstructureFields::*; +pub(crate) use StaticFields::*; +pub(crate) use SubstructureFields::*; use crate::{deriving, errors}; use rustc_ast::ptr::P; @@ -195,9 +195,9 @@ use std::vec; use thin_vec::{thin_vec, ThinVec}; use ty::{Bounds, Path, Ref, Self_, Ty}; -pub mod ty; +pub(crate) mod ty; -pub struct TraitDef<'a> { +pub(crate) struct TraitDef<'a> { /// The span for the current #[derive(Foo)] header. pub span: Span, @@ -224,7 +224,7 @@ pub struct TraitDef<'a> { pub is_const: bool, } -pub struct MethodDef<'a> { +pub(crate) struct MethodDef<'a> { /// name of the method pub name: Symbol, /// List of generics, e.g., `R: rand::Rng` @@ -248,7 +248,7 @@ pub struct MethodDef<'a> { /// How to handle fieldless enum variants. #[derive(PartialEq)] -pub enum FieldlessVariantsStrategy { +pub(crate) enum FieldlessVariantsStrategy { /// Combine fieldless variants into a single match arm. /// This assumes that relevant information has been handled /// by looking at the enum's discriminant. @@ -263,7 +263,7 @@ pub enum FieldlessVariantsStrategy { } /// All the data about the data structure/method being derived upon. -pub struct Substructure<'a> { +pub(crate) struct Substructure<'a> { /// ident of self pub type_ident: Ident, /// Verbatim access to any non-selflike arguments, i.e. arguments that @@ -273,7 +273,7 @@ pub struct Substructure<'a> { } /// Summary of the relevant parts of a struct/enum field. -pub struct FieldInfo { +pub(crate) struct FieldInfo { pub span: Span, /// None for tuple structs/normal enum variants, Some for normal /// structs/struct enum variants. @@ -287,13 +287,13 @@ pub struct FieldInfo { } #[derive(Copy, Clone)] -pub enum IsTuple { +pub(crate) enum IsTuple { No, Yes, } /// Fields for a static method -pub enum StaticFields { +pub(crate) enum StaticFields { /// Tuple and unit structs/enum variants like this. Unnamed(Vec, IsTuple), /// Normal structs/struct variants. @@ -301,7 +301,7 @@ pub enum StaticFields { } /// A summary of the possible sets of fields. -pub enum SubstructureFields<'a> { +pub(crate) enum SubstructureFields<'a> { /// A non-static method where `Self` is a struct. Struct(&'a ast::VariantData, Vec), @@ -329,10 +329,10 @@ pub enum SubstructureFields<'a> { /// Combine the values of all the fields together. The last argument is /// all the fields of all the structures. -pub type CombineSubstructureFunc<'a> = +pub(crate) type CombineSubstructureFunc<'a> = Box, Span, &Substructure<'_>) -> BlockOrExpr + 'a>; -pub fn combine_substructure( +pub(crate) fn combine_substructure( f: CombineSubstructureFunc<'_>, ) -> RefCell> { RefCell::new(f) @@ -349,7 +349,7 @@ struct TypeParameter { /// avoiding the insertion of any unnecessary blocks. /// /// The statements come before the expression. -pub struct BlockOrExpr(ThinVec, Option>); +pub(crate) struct BlockOrExpr(ThinVec, Option>); impl BlockOrExpr { pub fn new_stmts(stmts: ThinVec) -> BlockOrExpr { @@ -1647,7 +1647,7 @@ impl<'a> TraitDef<'a> { /// The function passed to `cs_fold` is called repeatedly with a value of this /// type. It describes one part of the code generation. The result is always an /// expression. -pub enum CsFold<'a> { +pub(crate) enum CsFold<'a> { /// The basic case: a field expression for one or more selflike args. E.g. /// for `PartialEq::eq` this is something like `self.x == other.x`. Single(&'a FieldInfo), @@ -1662,7 +1662,7 @@ pub enum CsFold<'a> { /// Folds over fields, combining the expressions for each field in a sequence. /// Statics may not be folded over. -pub fn cs_fold( +pub(crate) fn cs_fold( use_foldl: bool, cx: &ExtCtxt<'_>, trait_span: Span, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 1888332468326..f01d586033e09 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -1,7 +1,7 @@ //! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use //! when specifying impls to be derived. -pub use Ty::*; +pub(crate) use Ty::*; use rustc_ast::ptr::P; use rustc_ast::{self as ast, Expr, GenericArg, GenericParamKind, Generics, SelfKind}; @@ -14,14 +14,14 @@ use thin_vec::ThinVec; /// A path, e.g., `::std::option::Option::` (global). Has support /// for type parameters. #[derive(Clone)] -pub struct Path { +pub(crate) struct Path { path: Vec, params: Vec>, kind: PathKind, } #[derive(Clone)] -pub enum PathKind { +pub(crate) enum PathKind { Local, Global, Std, @@ -72,7 +72,7 @@ impl Path { /// A type. Supports pointers, Self, and literals. #[derive(Clone)] -pub enum Ty { +pub(crate) enum Ty { Self_, /// A reference. Ref(Box, ast::Mutability), @@ -83,7 +83,7 @@ pub enum Ty { Unit, } -pub fn self_ref() -> Ty { +pub(crate) fn self_ref() -> Ty { Ref(Box::new(Self_), ast::Mutability::Not) } @@ -163,7 +163,7 @@ fn mk_ty_param( /// Bounds on type parameters. #[derive(Clone)] -pub struct Bounds { +pub(crate) struct Bounds { pub bounds: Vec<(Symbol, Vec)>, } @@ -196,7 +196,7 @@ impl Bounds { } } -pub fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P, ast::ExplicitSelf) { +pub(crate) fn get_explicit_self(cx: &ExtCtxt<'_>, span: Span) -> (P, ast::ExplicitSelf) { // This constructs a fresh `self` path. let self_path = cx.expr_self(span); let self_ty = respan(span, SelfKind::Region(None, ast::Mutability::Not)); diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 41e27f6558668..dcd9281986511 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -7,7 +7,7 @@ use rustc_span::symbol::sym; use rustc_span::Span; use thin_vec::thin_vec; -pub fn expand_deriving_hash( +pub(crate) fn expand_deriving_hash( cx: &ExtCtxt<'_>, span: Span, mitem: &MetaItem, diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 9f786d22c932f..d6e2d1d4d07f6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -20,24 +20,24 @@ macro path_std($($x:tt)*) { generic::ty::Path::new( pathvec_std!( $($x)* ) ) } -pub mod bounds; -pub mod clone; -pub mod debug; -pub mod decodable; -pub mod default; -pub mod encodable; -pub mod hash; +pub(crate) mod bounds; +pub(crate) mod clone; +pub(crate) mod debug; +pub(crate) mod decodable; +pub(crate) mod default; +pub(crate) mod encodable; +pub(crate) mod hash; #[path = "cmp/eq.rs"] -pub mod eq; +pub(crate) mod eq; #[path = "cmp/ord.rs"] -pub mod ord; +pub(crate) mod ord; #[path = "cmp/partial_eq.rs"] -pub mod partial_eq; +pub(crate) mod partial_eq; #[path = "cmp/partial_ord.rs"] -pub mod partial_ord; +pub(crate) mod partial_ord; -pub mod generic; +pub(crate) mod generic; pub(crate) type BuiltinDeriveFn = fn(&ExtCtxt<'_>, Span, &MetaItem, &Annotatable, &mut dyn FnMut(Annotatable), bool); diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index bb3c83e8c0e3f..cc385bade4703 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -16,7 +16,7 @@ use rustc_span::Span; /// /// `$crate` will refer to either the `std` or `core` crate depending on which /// one we're expanding from. -pub fn expand_panic<'cx>( +pub(crate) fn expand_panic<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -29,7 +29,7 @@ pub fn expand_panic<'cx>( /// - `$crate::panic::unreachable_2015!(...)` or /// - `$crate::panic::unreachable_2021!(...)` /// depending on the edition. -pub fn expand_unreachable<'cx>( +pub(crate) fn expand_unreachable<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -69,7 +69,7 @@ fn expand<'cx>( )) } -pub fn use_panic_2021(mut span: Span) -> bool { +pub(crate) fn use_panic_2021(mut span: Span) -> bool { // To determine the edition, we check the first span up the expansion // stack that does not have #[allow_internal_unstable(edition_panic)]. // (To avoid using the edition of e.g. the assert!() or debug_assert!() definition.) diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs index 9387304594378..b03e14cf2630d 100644 --- a/compiler/rustc_builtin_macros/src/env.rs +++ b/compiler/rustc_builtin_macros/src/env.rs @@ -3,10 +3,11 @@ // interface. // +use crate::errors; +use crate::util::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts}; use rustc_ast::token::{self, LitKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::{AstDeref, ExprKind, GenericArg, Mutability}; -use rustc_expand::base::{expr_to_string, get_exprs_from_tts, get_single_str_from_tts}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; @@ -14,8 +15,6 @@ use std::env; use std::env::VarError; use thin_vec::thin_vec; -use crate::errors; - fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Result { let var = var.as_str(); if let Some(value) = cx.sess.opts.logical_env.get(var) { @@ -26,7 +25,7 @@ fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Result( +pub(crate) fn expand_option_env<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -66,7 +65,7 @@ pub fn expand_option_env<'cx>( ExpandResult::Ready(MacEager::expr(e)) } -pub fn expand_env<'cx>( +pub(crate) fn expand_env<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 9078dc07a3152..d157703723beb 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -579,7 +579,7 @@ pub(crate) struct FormatUnknownTrait<'a> { style = "tool-only", applicability = "maybe-incorrect" )] -pub struct FormatUnknownTraitSugg { +pub(crate) struct FormatUnknownTraitSugg { #[primary_span] pub span: Span, pub fmt: &'static str, @@ -842,3 +842,26 @@ pub(crate) struct ExpectedRegisterClassOrExplicitRegister { #[primary_span] pub(crate) span: Span, } + +#[derive(Diagnostic)] +#[diag(builtin_macros_expected_comma_in_list)] +pub(crate) struct ExpectedCommaInList { + #[primary_span] + pub span: Span, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_only_one_argument)] +pub(crate) struct OnlyOneArgument<'a> { + #[primary_span] + pub span: Span, + pub name: &'a str, +} + +#[derive(Diagnostic)] +#[diag(builtin_macros_takes_no_arguments)] +pub(crate) struct TakesNoArguments<'a> { + #[primary_span] + pub span: Span, + pub name: &'a str, +} diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index 51d6058a744fc..2c717661a1c43 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -1,3 +1,5 @@ +use crate::errors; +use crate::util::expr_to_spanned_string; use parse::Position::ArgumentNamed; use rustc_ast::ptr::P; use rustc_ast::tokenstream::TokenStream; @@ -10,14 +12,13 @@ use rustc_ast::{ use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Applicability, Diag, MultiSpan, PResult, SingleLabelManySpans}; use rustc_expand::base::*; +use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; +use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId}; use rustc_parse::parser::Recovered; use rustc_parse_format as parse; use rustc_span::symbol::{Ident, Symbol}; use rustc_span::{BytePos, ErrorGuaranteed, InnerSpan, Span}; -use rustc_lint_defs::builtin::NAMED_ARGUMENTS_USED_POSITIONALLY; -use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, LintId}; - // The format_args!() macro is expanded in three steps: // 1. First, `parse_args` will parse the `(literal, arg, arg, name=arg, name=arg)` syntax, // but doesn't parse the template (the literal) itself. @@ -38,8 +39,6 @@ enum PositionUsedAs { } use PositionUsedAs::*; -use crate::errors; - #[derive(Debug)] struct MacroInput { fmtstr: P, @@ -1001,7 +1000,7 @@ fn expand_format_args_impl<'cx>( }) } -pub fn expand_format_args<'cx>( +pub(crate) fn expand_format_args<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -1009,7 +1008,7 @@ pub fn expand_format_args<'cx>( expand_format_args_impl(ecx, sp, tts, false) } -pub fn expand_format_args_nl<'cx>( +pub(crate) fn expand_format_args_nl<'cx>( ecx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index 099defd511b5b..a1630ad1379e4 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -12,7 +12,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::Span; use thin_vec::{thin_vec, ThinVec}; -pub fn expand( +pub(crate) fn expand( ecx: &mut ExtCtxt<'_>, _span: Span, meta_item: &ast::MetaItem, diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 1b4c6041294f4..7c7b9c2d65fb2 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -50,13 +50,13 @@ mod pattern_type; mod source_util; mod test; mod trace_macros; -mod util; pub mod asm; pub mod cmdline_attrs; pub mod proc_macro_harness; pub mod standard_library_imports; pub mod test_harness; +pub mod util; rustc_fluent_macro::fluent_messages! { "../messages.ftl" } @@ -109,8 +109,8 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { bench: test::expand_bench, cfg_accessible: cfg_accessible::Expander, cfg_eval: cfg_eval::expand, - derive: derive::Expander(false), - derive_const: derive::Expander(true), + derive: derive::Expander { is_const: false }, + derive_const: derive::Expander { is_const: true }, global_allocator: global_allocator::expand, test: test::expand_test, test_case: test::expand_test_case, diff --git a/compiler/rustc_builtin_macros/src/log_syntax.rs b/compiler/rustc_builtin_macros/src/log_syntax.rs index 288a475ac241c..205f21ae7c9d3 100644 --- a/compiler/rustc_builtin_macros/src/log_syntax.rs +++ b/compiler/rustc_builtin_macros/src/log_syntax.rs @@ -2,7 +2,7 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; -pub fn expand_log_syntax<'cx>( +pub(crate) fn expand_log_syntax<'cx>( _cx: &'cx mut ExtCtxt<'_>, sp: rustc_span::Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 54039c2c5386b..31f5656df135e 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -3,7 +3,7 @@ use rustc_errors::PResult; use rustc_expand::base::{self, DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult}; use rustc_span::{sym, Span}; -pub fn expand<'cx>( +pub(crate) fn expand<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index c79ae716806cd..47b2ee975ca89 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -1,3 +1,6 @@ +use crate::util::{ + check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr, +}; use rustc_ast as ast; use rustc_ast::ptr::P; use rustc_ast::token; @@ -5,11 +8,8 @@ use rustc_ast::tokenstream::TokenStream; use rustc_ast_pretty::pprust; use rustc_data_structures::sync::Lrc; use rustc_expand::base::{ - check_zero_tts, get_single_str_from_tts, get_single_str_spanned_from_tts, parse_expr, - resolve_path, + resolve_path, DummyResult, ExpandResult, ExtCtxt, MacEager, MacResult, MacroExpanderResult, }; -use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt}; -use rustc_expand::base::{MacEager, MacResult, MacroExpanderResult}; use rustc_expand::module::DirOwnership; use rustc_parse::new_parser_from_file; use rustc_parse::parser::{ForceCollect, Parser}; @@ -26,7 +26,7 @@ use std::rc::Rc; // a given file into the current one. /// line!(): expands to the current line number -pub fn expand_line( +pub(crate) fn expand_line( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -41,7 +41,7 @@ pub fn expand_line( } /* column!(): expands to the current column number */ -pub fn expand_column( +pub(crate) fn expand_column( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -58,7 +58,7 @@ pub fn expand_column( /// file!(): expands to the current filename */ /// The source_file (`loc.file`) contains a bunch more information we could spit /// out if we wanted. -pub fn expand_file( +pub(crate) fn expand_file( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -78,7 +78,7 @@ pub fn expand_file( ))) } -pub fn expand_stringify( +pub(crate) fn expand_stringify( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -88,7 +88,7 @@ pub fn expand_stringify( ExpandResult::Ready(MacEager::expr(cx.expr_str(sp, Symbol::intern(&s)))) } -pub fn expand_mod( +pub(crate) fn expand_mod( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -104,7 +104,7 @@ pub fn expand_mod( /// include! : parse the given file as an expr /// This is generally a bad idea because it's going to behave /// unhygienically. -pub fn expand_include<'cx>( +pub(crate) fn expand_include<'cx>( cx: &'cx mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -181,7 +181,7 @@ pub fn expand_include<'cx>( } /// `include_str!`: read the given file, insert it as a literal string expr -pub fn expand_include_str( +pub(crate) fn expand_include_str( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, @@ -210,7 +210,7 @@ pub fn expand_include_str( }) } -pub fn expand_include_bytes( +pub(crate) fn expand_include_bytes( cx: &mut ExtCtxt<'_>, sp: Span, tts: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index c7568f1461c10..134d5451b9c1c 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -20,7 +20,7 @@ use thin_vec::{thin_vec, ThinVec}; /// /// We mark item with an inert attribute "rustc_test_marker" which the test generation /// logic will pick up on. -pub fn expand_test_case( +pub(crate) fn expand_test_case( ecx: &mut ExtCtxt<'_>, attr_sp: Span, meta_item: &ast::MetaItem, @@ -73,7 +73,7 @@ pub fn expand_test_case( vec![ret] } -pub fn expand_test( +pub(crate) fn expand_test( cx: &mut ExtCtxt<'_>, attr_sp: Span, meta_item: &ast::MetaItem, @@ -84,7 +84,7 @@ pub fn expand_test( expand_test_or_bench(cx, attr_sp, item, false) } -pub fn expand_bench( +pub(crate) fn expand_bench( cx: &mut ExtCtxt<'_>, attr_sp: Span, meta_item: &ast::MetaItem, @@ -95,7 +95,7 @@ pub fn expand_bench( expand_test_or_bench(cx, attr_sp, item, true) } -pub fn expand_test_or_bench( +pub(crate) fn expand_test_or_bench( cx: &ExtCtxt<'_>, attr_sp: Span, item: Annotatable, diff --git a/compiler/rustc_builtin_macros/src/trace_macros.rs b/compiler/rustc_builtin_macros/src/trace_macros.rs index 696d99004ba01..4833ec32f76e1 100644 --- a/compiler/rustc_builtin_macros/src/trace_macros.rs +++ b/compiler/rustc_builtin_macros/src/trace_macros.rs @@ -4,7 +4,7 @@ use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacroExpanderResult use rustc_span::symbol::kw; use rustc_span::Span; -pub fn expand_trace_macros( +pub(crate) fn expand_trace_macros( cx: &mut ExtCtxt<'_>, sp: Span, tt: TokenStream, diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index ad6b09ba57458..8dc7bc14ec3e6 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -1,11 +1,16 @@ -use rustc_ast::{attr, AttrStyle, Attribute, MetaItem}; -use rustc_expand::base::{Annotatable, ExtCtxt}; +use crate::errors; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{self as ast, attr, ptr::P, token, AttrStyle, Attribute, MetaItem}; +use rustc_errors::{Applicability, Diag, ErrorGuaranteed}; +use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt}; +use rustc_expand::expand::AstFragment; use rustc_feature::AttributeTemplate; use rustc_lint_defs::builtin::DUPLICATE_MACRO_ATTRIBUTES; -use rustc_parse::validate_attr; -use rustc_span::Symbol; +use rustc_parse::{parser, validate_attr}; +use rustc_session::errors::report_lit_error; +use rustc_span::{BytePos, Span, Symbol}; -pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { +pub(crate) fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, name: Symbol) { // All the built-in macro attributes are "words" at the moment. let template = AttributeTemplate { word: true, ..Default::default() }; validate_attr::check_builtin_meta_item( @@ -19,7 +24,7 @@ pub fn check_builtin_macro_attribute(ecx: &ExtCtxt<'_>, meta_item: &MetaItem, na /// Emit a warning if the item is annotated with the given attribute. This is used to diagnose when /// an attribute may have been mistakenly duplicated. -pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) { +pub(crate) fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: Symbol) { let attrs: Option<&[Attribute]> = match item { Annotatable::Item(item) => Some(&item.attrs), Annotatable::TraitItem(item) => Some(&item.attrs), @@ -46,3 +51,178 @@ pub fn warn_on_duplicate_attribute(ecx: &ExtCtxt<'_>, item: &Annotatable, name: } } } + +/// `Ok` represents successfully retrieving the string literal at the correct +/// position, e.g., `println("abc")`. +type ExprToSpannedStringResult<'a> = Result<(Symbol, ast::StrStyle, Span), UnexpectedExprKind<'a>>; + +/// - `Ok` is returned when the conversion to a string literal is unsuccessful, +/// but another type of expression is obtained instead. +/// - `Err` is returned when the conversion process fails. +type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>; + +/// Extracts a string literal from the macro expanded version of `expr`, +/// returning a diagnostic error of `err_msg` if `expr` is not a string literal. +/// The returned bool indicates whether an applicable suggestion has already been +/// added to the diagnostic to avoid emitting multiple suggestions. `Err(Err(ErrorGuaranteed))` +/// indicates that an ast error was encountered. +// FIXME(Nilstrieb) Make this function setup translatable +#[allow(rustc::untranslatable_diagnostic)] +pub(crate) fn expr_to_spanned_string<'a>( + cx: &'a mut ExtCtxt<'_>, + expr: P, + err_msg: &'static str, +) -> ExpandResult, ()> { + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } + + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + + ExpandResult::Ready(Err(match expr.kind { + ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { + Ok(ast::LitKind::Str(s, style)) => { + return ExpandResult::Ready(Ok((s, style, expr.span))); + } + Ok(ast::LitKind::ByteStr(..)) => { + let mut err = cx.dcx().struct_span_err(expr.span, err_msg); + let span = expr.span.shrink_to_lo(); + err.span_suggestion( + span.with_hi(span.lo() + BytePos(1)), + "consider removing the leading `b`", + "", + Applicability::MaybeIncorrect, + ); + Ok((err, true)) + } + Ok(ast::LitKind::Err(guar)) => Err(guar), + Err(err) => Err(report_lit_error(&cx.sess.psess, err, token_lit, expr.span)), + _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), + }, + ast::ExprKind::Err(guar) => Err(guar), + ast::ExprKind::Dummy => { + cx.dcx().span_bug(expr.span, "tried to get a string literal from `ExprKind::Dummy`") + } + _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), + })) +} + +/// Extracts a string literal from the macro expanded version of `expr`, +/// emitting `err_msg` if `expr` is not a string literal. This does not stop +/// compilation on error, merely emits a non-fatal error and returns `Err`. +pub(crate) fn expr_to_string( + cx: &mut ExtCtxt<'_>, + expr: P, + err_msg: &'static str, +) -> ExpandResult, ()> { + expr_to_spanned_string(cx, expr, err_msg).map(|res| { + res.map_err(|err| match err { + Ok((err, _)) => err.emit(), + Err(guar) => guar, + }) + .map(|(symbol, style, _)| (symbol, style)) + }) +} + +/// Non-fatally assert that `tts` is empty. Note that this function +/// returns even when `tts` is non-empty, macros that *need* to stop +/// compilation should call `cx.diagnostic().abort_if_errors()` +/// (this should be done as rarely as possible). +pub(crate) fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) { + if !tts.is_empty() { + cx.dcx().emit_err(errors::TakesNoArguments { span, name }); + } +} + +/// Parse an expression. On error, emit it, advancing to `Eof`, and return `Err`. +pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result, ErrorGuaranteed> { + let guar = match p.parse_expr() { + Ok(expr) => return Ok(expr), + Err(err) => err.emit(), + }; + while p.token != token::Eof { + p.bump(); + } + Err(guar) +} + +/// Interpreting `tts` as a comma-separated sequence of expressions, +/// expect exactly one string literal, or emit an error and return `Err`. +pub(crate) fn get_single_str_from_tts( + cx: &mut ExtCtxt<'_>, + span: Span, + tts: TokenStream, + name: &str, +) -> ExpandResult, ()> { + get_single_str_spanned_from_tts(cx, span, tts, name).map(|res| res.map(|(s, _)| s)) +} + +pub(crate) fn get_single_str_spanned_from_tts( + cx: &mut ExtCtxt<'_>, + span: Span, + tts: TokenStream, + name: &str, +) -> ExpandResult, ()> { + let mut p = cx.new_parser_from_tts(tts); + if p.token == token::Eof { + let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); + return ExpandResult::Ready(Err(guar)); + } + let ret = match parse_expr(&mut p) { + Ok(ret) => ret, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; + let _ = p.eat(&token::Comma); + + if p.token != token::Eof { + cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); + } + expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| { + res.map_err(|err| match err { + Ok((err, _)) => err.emit(), + Err(guar) => guar, + }) + .map(|(symbol, _style, span)| (symbol, span)) + }) +} + +/// Extracts comma-separated expressions from `tts`. +/// On error, emit it, and return `Err`. +pub(crate) fn get_exprs_from_tts( + cx: &mut ExtCtxt<'_>, + tts: TokenStream, +) -> ExpandResult>, ErrorGuaranteed>, ()> { + let mut p = cx.new_parser_from_tts(tts); + let mut es = Vec::new(); + while p.token != token::Eof { + let expr = match parse_expr(&mut p) { + Ok(expr) => expr, + Err(guar) => return ExpandResult::Ready(Err(guar)), + }; + if !cx.force_mode + && let ast::ExprKind::MacCall(m) = &expr.kind + && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() + { + return ExpandResult::Retry(()); + } + + // Perform eager expansion on the expression. + // We want to be able to handle e.g., `concat!("foo", "bar")`. + let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); + + es.push(expr); + if p.eat(&token::Comma) { + continue; + } + if p.token != token::Eof { + let guar = cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span }); + return ExpandResult::Ready(Err(guar)); + } + } + ExpandResult::Ready(Ok(es)) +} diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl index fdd1a87cae809..b7aae2af9ef97 100644 --- a/compiler/rustc_expand/messages.ftl +++ b/compiler/rustc_expand/messages.ftl @@ -30,9 +30,6 @@ expand_duplicate_matcher_binding = duplicate matcher binding .label = duplicate binding .label2 = previous binding -expand_expected_comma_in_list = - expected token: `,` - expand_expected_paren_or_brace = expected `(` or `{"{"}`, found `{$token}` @@ -116,9 +113,6 @@ expand_must_repeat_once = expand_not_a_meta_item = not a meta item -expand_only_one_argument = - {$name} takes 1 argument - expand_only_one_word = must only be one word @@ -146,9 +140,6 @@ expand_remove_node_not_supported = expand_resolve_relative_path = cannot resolve relative path in non-file source `{$path}` -expand_takes_no_arguments = - {$name} takes no arguments - expand_trace_macro = trace_macro expand_unsupported_key_value = diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index 3c465709ec7b8..6fe74edbd70a8 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -5,27 +5,26 @@ use crate::module::DirOwnership; use rustc_ast::attr::MarkedAttrs; use rustc_ast::ptr::P; -use rustc_ast::token::{self, Nonterminal}; +use rustc_ast::token::Nonterminal; 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_attr::{self as attr, Deprecation, Stability}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{self, Lrc}; -use rustc_errors::{Applicability, Diag, DiagCtxt, ErrorGuaranteed, PResult}; +use rustc_errors::{DiagCtxt, ErrorGuaranteed, PResult}; use rustc_feature::Features; use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT; use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiag, RegisteredTools}; use rustc_parse::{parser, MACRO_ARGUMENTS}; use rustc_session::config::CollapseMacroDebuginfo; -use rustc_session::errors::report_lit_error; use rustc_session::{parse::ParseSess, Limit, Session}; use rustc_span::def_id::{CrateNum, DefId, LocalDefId}; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{kw, sym, Ident, Symbol}; -use rustc_span::{BytePos, FileName, Span, DUMMY_SP}; +use rustc_span::{FileName, Span, DUMMY_SP}; use smallvec::{smallvec, SmallVec}; use std::default::Default; use std::iter; @@ -963,7 +962,12 @@ impl SyntaxExtension { /// Error type that denotes indeterminacy. pub struct Indeterminate; -pub type DeriveResolutions = Vec<(ast::Path, Annotatable, Option>, bool)>; +pub struct DeriveResolution { + pub path: ast::Path, + pub item: Annotatable, + pub exts: Option>, + pub is_const: bool, +} pub trait ResolverExpand { fn next_node_id(&mut self) -> NodeId; @@ -1006,11 +1010,11 @@ pub trait ResolverExpand { &mut self, expn_id: LocalExpnId, force: bool, - derive_paths: &dyn Fn() -> DeriveResolutions, + derive_paths: &dyn Fn() -> Vec, ) -> Result<(), Indeterminate>; /// Take resolutions for paths inside the `#[derive(...)]` attribute with the given `ExpnId` /// back from resolver. - fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option; + fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option>; /// Path resolution logic for `#[cfg_accessible(path)]`. fn cfg_accessible( &mut self, @@ -1264,181 +1268,6 @@ pub fn resolve_path(sess: &Session, path: impl Into, span: Span) -> PRe } } -/// `Ok` represents successfully retrieving the string literal at the correct -/// position, e.g., `println("abc")`. -type ExprToSpannedStringResult<'a> = Result<(Symbol, ast::StrStyle, Span), UnexpectedExprKind<'a>>; - -/// - `Ok` is returned when the conversion to a string literal is unsuccessful, -/// but another type of expression is obtained instead. -/// - `Err` is returned when the conversion process fails. -type UnexpectedExprKind<'a> = Result<(Diag<'a>, bool /* has_suggestions */), ErrorGuaranteed>; - -/// Extracts a string literal from the macro expanded version of `expr`, -/// returning a diagnostic error of `err_msg` if `expr` is not a string literal. -/// The returned bool indicates whether an applicable suggestion has already been -/// added to the diagnostic to avoid emitting multiple suggestions. `Err(Err(ErrorGuaranteed))` -/// indicates that an ast error was encountered. -// FIXME(Nilstrieb) Make this function setup translatable -#[allow(rustc::untranslatable_diagnostic)] -pub fn expr_to_spanned_string<'a>( - cx: &'a mut ExtCtxt<'_>, - expr: P, - err_msg: &'static str, -) -> ExpandResult, ()> { - if !cx.force_mode - && let ast::ExprKind::MacCall(m) = &expr.kind - && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() - { - return ExpandResult::Retry(()); - } - - // Perform eager expansion on the expression. - // We want to be able to handle e.g., `concat!("foo", "bar")`. - let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); - - ExpandResult::Ready(Err(match expr.kind { - ast::ExprKind::Lit(token_lit) => match ast::LitKind::from_token_lit(token_lit) { - Ok(ast::LitKind::Str(s, style)) => { - return ExpandResult::Ready(Ok((s, style, expr.span))); - } - Ok(ast::LitKind::ByteStr(..)) => { - let mut err = cx.dcx().struct_span_err(expr.span, err_msg); - let span = expr.span.shrink_to_lo(); - err.span_suggestion( - span.with_hi(span.lo() + BytePos(1)), - "consider removing the leading `b`", - "", - Applicability::MaybeIncorrect, - ); - Ok((err, true)) - } - Ok(ast::LitKind::Err(guar)) => Err(guar), - Err(err) => Err(report_lit_error(&cx.sess.psess, err, token_lit, expr.span)), - _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), - }, - ast::ExprKind::Err(guar) => Err(guar), - ast::ExprKind::Dummy => { - cx.dcx().span_bug(expr.span, "tried to get a string literal from `ExprKind::Dummy`") - } - _ => Ok((cx.dcx().struct_span_err(expr.span, err_msg), false)), - })) -} - -/// Extracts a string literal from the macro expanded version of `expr`, -/// emitting `err_msg` if `expr` is not a string literal. This does not stop -/// compilation on error, merely emits a non-fatal error and returns `Err`. -pub fn expr_to_string( - cx: &mut ExtCtxt<'_>, - expr: P, - err_msg: &'static str, -) -> ExpandResult, ()> { - expr_to_spanned_string(cx, expr, err_msg).map(|res| { - res.map_err(|err| match err { - Ok((err, _)) => err.emit(), - Err(guar) => guar, - }) - .map(|(symbol, style, _)| (symbol, style)) - }) -} - -/// Non-fatally assert that `tts` is empty. Note that this function -/// returns even when `tts` is non-empty, macros that *need* to stop -/// compilation should call `cx.diagnostic().abort_if_errors()` -/// (this should be done as rarely as possible). -pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) { - if !tts.is_empty() { - cx.dcx().emit_err(errors::TakesNoArguments { span, name }); - } -} - -/// Parse an expression. On error, emit it, advancing to `Eof`, and return `Err`. -pub fn parse_expr(p: &mut parser::Parser<'_>) -> Result, ErrorGuaranteed> { - let guar = match p.parse_expr() { - Ok(expr) => return Ok(expr), - Err(err) => err.emit(), - }; - while p.token != token::Eof { - p.bump(); - } - Err(guar) -} - -/// Interpreting `tts` as a comma-separated sequence of expressions, -/// expect exactly one string literal, or emit an error and return `Err`. -pub fn get_single_str_from_tts( - cx: &mut ExtCtxt<'_>, - span: Span, - tts: TokenStream, - name: &str, -) -> ExpandResult, ()> { - get_single_str_spanned_from_tts(cx, span, tts, name).map(|res| res.map(|(s, _)| s)) -} - -pub fn get_single_str_spanned_from_tts( - cx: &mut ExtCtxt<'_>, - span: Span, - tts: TokenStream, - name: &str, -) -> ExpandResult, ()> { - let mut p = cx.new_parser_from_tts(tts); - if p.token == token::Eof { - let guar = cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); - return ExpandResult::Ready(Err(guar)); - } - let ret = match parse_expr(&mut p) { - Ok(ret) => ret, - Err(guar) => return ExpandResult::Ready(Err(guar)), - }; - let _ = p.eat(&token::Comma); - - if p.token != token::Eof { - cx.dcx().emit_err(errors::OnlyOneArgument { span, name }); - } - expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| { - res.map_err(|err| match err { - Ok((err, _)) => err.emit(), - Err(guar) => guar, - }) - .map(|(symbol, _style, span)| (symbol, span)) - }) -} - -/// Extracts comma-separated expressions from `tts`. -/// On error, emit it, and return `Err`. -pub fn get_exprs_from_tts( - cx: &mut ExtCtxt<'_>, - tts: TokenStream, -) -> ExpandResult>, ErrorGuaranteed>, ()> { - let mut p = cx.new_parser_from_tts(tts); - let mut es = Vec::new(); - while p.token != token::Eof { - let expr = match parse_expr(&mut p) { - Ok(expr) => expr, - Err(guar) => return ExpandResult::Ready(Err(guar)), - }; - if !cx.force_mode - && let ast::ExprKind::MacCall(m) = &expr.kind - && cx.resolver.macro_accessible(cx.current_expansion.id, &m.path).is_err() - { - return ExpandResult::Retry(()); - } - - // Perform eager expansion on the expression. - // We want to be able to handle e.g., `concat!("foo", "bar")`. - let expr = cx.expander().fully_expand_fragment(AstFragment::Expr(expr)).make_expr(); - - es.push(expr); - if p.eat(&token::Comma) { - continue; - } - if p.token != token::Eof { - let guar = cx.dcx().emit_err(errors::ExpectedCommaInList { span: p.token.span }); - return ExpandResult::Ready(Err(guar)); - } - } - ExpandResult::Ready(Ok(es)) -} - pub fn parse_macro_name_and_helper_attrs( dcx: &rustc_errors::DiagCtxt, attr: &Attribute, diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs index 21ce5e1d81e6e..db8e4ba07e807 100644 --- a/compiler/rustc_expand/src/errors.rs +++ b/compiler/rustc_expand/src/errors.rs @@ -152,29 +152,6 @@ pub(crate) struct HelperAttributeNameInvalid { pub name: Ident, } -#[derive(Diagnostic)] -#[diag(expand_expected_comma_in_list)] -pub(crate) struct ExpectedCommaInList { - #[primary_span] - pub span: Span, -} - -#[derive(Diagnostic)] -#[diag(expand_only_one_argument)] -pub(crate) struct OnlyOneArgument<'a> { - #[primary_span] - pub span: Span, - pub name: &'a str, -} - -#[derive(Diagnostic)] -#[diag(expand_takes_no_arguments)] -pub(crate) struct TakesNoArguments<'a> { - #[primary_span] - pub span: Span, - pub name: &'a str, -} - #[derive(Diagnostic)] #[diag(expand_feature_removed, code = E0557)] pub(crate) struct FeatureRemoved<'a> { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 6029caa965c0b..909197d90b662 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -482,7 +482,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { derive_invocations.reserve(derives.len()); derives .into_iter() - .map(|(path, item, _exts, is_const)| { + .map(|DeriveResolution { path, item, exts: _, is_const }| { // FIXME: Consider using the derive resolutions (`_exts`) // instead of enqueuing the derives to be resolved again later. let expn_id = LocalExpnId::fresh_empty(); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e07c3247d07ae..af0b4792136cf 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -38,7 +38,7 @@ use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, Lrc}; use rustc_errors::{Applicability, Diag, ErrCode}; -use rustc_expand::base::{DeriveResolutions, SyntaxExtension, SyntaxExtensionKind}; +use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::NonMacroAttrKind; @@ -959,7 +959,7 @@ enum BuiltinMacroState { } struct DeriveData { - resolutions: DeriveResolutions, + resolutions: Vec, helper_attrs: Vec<(usize, Ident)>, has_derive_copy: bool, } diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 2a23ed71753fa..82e41b6c31436 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -15,7 +15,7 @@ use rustc_attr::StabilityLevel; use rustc_data_structures::intern::Interned; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, StashKey}; -use rustc_expand::base::{Annotatable, DeriveResolutions, Indeterminate, ResolverExpand}; +use rustc_expand::base::{Annotatable, DeriveResolution, Indeterminate, ResolverExpand}; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{AstFragment, Invocation, InvocationKind, SupportsMacroExpansion}; @@ -344,7 +344,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { &mut self, expn_id: LocalExpnId, force: bool, - derive_paths: &dyn Fn() -> DeriveResolutions, + derive_paths: &dyn Fn() -> Vec, ) -> Result<(), Indeterminate> { // Block expansion of the container until we resolve all derives in it. // This is required for two reasons: @@ -360,11 +360,11 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { has_derive_copy: false, }); let parent_scope = self.invocation_parent_scopes[&expn_id]; - for (i, (path, _, opt_ext, _)) in entry.resolutions.iter_mut().enumerate() { - if opt_ext.is_none() { - *opt_ext = Some( + for (i, resolution) in entry.resolutions.iter_mut().enumerate() { + if resolution.exts.is_none() { + resolution.exts = Some( match self.resolve_macro_path( - path, + &resolution.path, Some(MacroKind::Derive), &parent_scope, true, @@ -372,7 +372,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { ) { Ok((Some(ext), _)) => { if !ext.helper_attrs.is_empty() { - let last_seg = path.segments.last().unwrap(); + let last_seg = resolution.path.segments.last().unwrap(); let span = last_seg.ident.span.normalize_to_macros_2_0(); entry.helper_attrs.extend( ext.helper_attrs @@ -416,7 +416,7 @@ impl<'a, 'tcx> ResolverExpand for Resolver<'a, 'tcx> { Ok(()) } - fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option { + fn take_derive_resolutions(&mut self, expn_id: LocalExpnId) -> Option> { self.derive_data.remove(&expn_id).map(|data| data.resolutions) }