mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 08:13:41 +00:00
Migrate parts of rustc_expand
to session diagnostics
This migrates everything but the `mbe` and `proc_macro` modules. It also contains a few cleanups and drive-by/accidental diagnostic improvements which can be seen in the diff for the UI tests.
This commit is contained in:
parent
a000811405
commit
2f9f097cb8
@ -11,7 +11,7 @@ pub fn expand_concat(
|
|||||||
sp: rustc_span::Span,
|
sp: rustc_span::Span,
|
||||||
tts: TokenStream,
|
tts: TokenStream,
|
||||||
) -> Box<dyn base::MacResult + 'static> {
|
) -> Box<dyn base::MacResult + 'static> {
|
||||||
let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
|
let Some(es) = base::get_exprs_from_tts(cx, tts) else {
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
};
|
};
|
||||||
let mut accumulator = String::new();
|
let mut accumulator = String::new();
|
||||||
|
@ -137,7 +137,7 @@ pub fn expand_concat_bytes(
|
|||||||
sp: rustc_span::Span,
|
sp: rustc_span::Span,
|
||||||
tts: TokenStream,
|
tts: TokenStream,
|
||||||
) -> Box<dyn base::MacResult + 'static> {
|
) -> Box<dyn base::MacResult + 'static> {
|
||||||
let Some(es) = base::get_exprs_from_tts(cx, sp, tts) else {
|
let Some(es) = base::get_exprs_from_tts(cx, tts) else {
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
};
|
};
|
||||||
let mut accumulator = Vec::new();
|
let mut accumulator = Vec::new();
|
||||||
|
@ -52,7 +52,7 @@ pub fn expand_env<'cx>(
|
|||||||
sp: Span,
|
sp: Span,
|
||||||
tts: TokenStream,
|
tts: TokenStream,
|
||||||
) -> Box<dyn base::MacResult + 'cx> {
|
) -> Box<dyn base::MacResult + 'cx> {
|
||||||
let mut exprs = match get_exprs_from_tts(cx, sp, tts) {
|
let mut exprs = match get_exprs_from_tts(cx, tts) {
|
||||||
Some(exprs) if exprs.is_empty() => {
|
Some(exprs) if exprs.is_empty() => {
|
||||||
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
cx.span_err(sp, "env! takes 1 or 2 arguments");
|
||||||
return DummyResult::any(sp);
|
return DummyResult::any(sp);
|
||||||
|
@ -20,3 +20,110 @@ expand_var_still_repeating =
|
|||||||
variable '{$ident}' is still repeating at this depth
|
variable '{$ident}' is still repeating at this depth
|
||||||
|
|
||||||
expand_meta_var_dif_seq_matchers = {$msg}
|
expand_meta_var_dif_seq_matchers = {$msg}
|
||||||
|
|
||||||
|
expand_macro_const_stability =
|
||||||
|
macros cannot have const stability attributes
|
||||||
|
.label = invalid const stability attribute
|
||||||
|
.label2 = const stability attribute affects this macro
|
||||||
|
|
||||||
|
expand_macro_body_stability =
|
||||||
|
macros cannot have body stability attributes
|
||||||
|
.label = invalid body stability attribute
|
||||||
|
.label2 = body stability attribute affects this macro
|
||||||
|
|
||||||
|
expand_resolve_relative_path =
|
||||||
|
cannot resolve relative path in non-file source `{$path}`
|
||||||
|
|
||||||
|
expand_attr_no_arguments =
|
||||||
|
attribute must have either one or two arguments
|
||||||
|
|
||||||
|
expand_not_a_meta_item =
|
||||||
|
not a meta item
|
||||||
|
|
||||||
|
expand_only_one_word =
|
||||||
|
must only be one word
|
||||||
|
|
||||||
|
expand_cannot_be_name_of_macro =
|
||||||
|
`{$trait_ident}` cannot be a name of {$macro_type} macro
|
||||||
|
|
||||||
|
expand_arg_not_attributes =
|
||||||
|
second argument must be `attributes`
|
||||||
|
|
||||||
|
expand_attributes_wrong_form =
|
||||||
|
attribute must be of form: `attributes(foo, bar)`
|
||||||
|
|
||||||
|
expand_attribute_meta_item =
|
||||||
|
attribute must be a meta item, not a literal
|
||||||
|
|
||||||
|
expand_attribute_single_word =
|
||||||
|
attribute must only be a single word
|
||||||
|
|
||||||
|
expand_helper_attribute_name_invalid =
|
||||||
|
`{$name}` cannot be a name of derive helper attribute
|
||||||
|
|
||||||
|
expand_expected_comma_in_list =
|
||||||
|
expected token: `,`
|
||||||
|
|
||||||
|
expand_only_one_argument =
|
||||||
|
{$name} takes 1 argument
|
||||||
|
|
||||||
|
expand_takes_no_arguments =
|
||||||
|
{$name} takes no arguments
|
||||||
|
|
||||||
|
expand_feature_included_in_edition =
|
||||||
|
the feature `{$feature}` is included in the Rust {$edition} edition
|
||||||
|
|
||||||
|
expand_feature_removed =
|
||||||
|
feature has been removed
|
||||||
|
.label = feature has been removed
|
||||||
|
.reason = {$reason}
|
||||||
|
|
||||||
|
expand_feature_not_allowed =
|
||||||
|
the feature `{$name}` is not in the list of allowed features
|
||||||
|
|
||||||
|
expand_recursion_limit_reached =
|
||||||
|
recursion limit reached while expanding `{$descr}`
|
||||||
|
.help = consider increasing the recursion limit by adding a `#![recursion_limit = "{$suggested_limit}"]` attribute to your crate (`{$crate_name}`)
|
||||||
|
|
||||||
|
expand_malformed_feature_attribute =
|
||||||
|
malformed `feature` attribute input
|
||||||
|
.expected = expected just one word
|
||||||
|
|
||||||
|
expand_remove_expr_not_supported =
|
||||||
|
removing an expression is not supported in this position
|
||||||
|
|
||||||
|
expand_invalid_cfg_no_parens = `cfg` is not followed by parentheses
|
||||||
|
expand_invalid_cfg_no_predicate = `cfg` predicate is not specified
|
||||||
|
expand_invalid_cfg_multiple_predicates = multiple `cfg` predicates are specified
|
||||||
|
expand_invalid_cfg_predicate_literal = `cfg` predicate key cannot be a literal
|
||||||
|
expand_invalid_cfg_expected_syntax = expected syntax is
|
||||||
|
|
||||||
|
expand_wrong_fragment_kind =
|
||||||
|
non-{$kind} macro in {$kind} position: {$name}
|
||||||
|
|
||||||
|
expand_unsupported_key_value =
|
||||||
|
key-value macro attributes are not supported
|
||||||
|
|
||||||
|
expand_incomplete_parse =
|
||||||
|
macro expansion ignores token `{$token}` and any following
|
||||||
|
.label = caused by the macro expansion here
|
||||||
|
.note = the usage of `{$macro_path}!` is likely invalid in {$kind_name} context
|
||||||
|
.suggestion_add_semi = you might be missing a semicolon here
|
||||||
|
|
||||||
|
expand_remove_node_not_supported =
|
||||||
|
removing {$descr} is not supported in this position
|
||||||
|
|
||||||
|
expand_module_circular =
|
||||||
|
circular modules: {$modules}
|
||||||
|
|
||||||
|
expand_module_in_block =
|
||||||
|
cannot declare a non-inline module inside a block unless it has a path attribute
|
||||||
|
.note = maybe `use` the module `{$name}` instead of redeclaring it
|
||||||
|
|
||||||
|
expand_module_file_not_found =
|
||||||
|
file not found for module `{$name}`
|
||||||
|
.help = to create the module `{$name}`, create file "{$default_path}" or "{$secondary_path}"
|
||||||
|
|
||||||
|
expand_module_multiple_candidates =
|
||||||
|
file for module `{$name}` found at both "{$default_path}" and "{$secondary_path}"
|
||||||
|
.help = delete or rename one of them to remove the ambiguity
|
||||||
|
@ -152,6 +152,12 @@ impl IntoDiagnosticArg for ast::Path {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl IntoDiagnosticArg for &ast::Path {
|
||||||
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
|
DiagnosticArgValue::Str(Cow::Owned(pprust::path_to_string(self)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl IntoDiagnosticArg for ast::token::Token {
|
impl IntoDiagnosticArg for ast::token::Token {
|
||||||
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
fn into_diagnostic_arg(self) -> DiagnosticArgValue<'static> {
|
||||||
DiagnosticArgValue::Str(pprust::token_to_string(&self))
|
DiagnosticArgValue::Str(pprust::token_to_string(&self))
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
|
|
||||||
|
use crate::errors::{
|
||||||
|
ArgumentNotAttributes, AttrNoArguments, AttributeMetaItem, AttributeSingleWord,
|
||||||
|
AttributesWrongForm, CannotBeNameOfMacro, ExpectedCommaInList, HelperAttributeNameInvalid,
|
||||||
|
MacroBodyStability, MacroConstStability, NotAMetaItem, OnlyOneArgument, OnlyOneWord,
|
||||||
|
ResolveRelativePath, TakesNoArguments,
|
||||||
|
};
|
||||||
use crate::expand::{self, AstFragment, Invocation};
|
use crate::expand::{self, AstFragment, Invocation};
|
||||||
use crate::module::DirOwnership;
|
use crate::module::DirOwnership;
|
||||||
|
|
||||||
@ -789,26 +797,16 @@ impl SyntaxExtension {
|
|||||||
.unwrap_or_else(|| (None, helper_attrs));
|
.unwrap_or_else(|| (None, helper_attrs));
|
||||||
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
|
let (stability, const_stability, body_stability) = attr::find_stability(&sess, attrs, span);
|
||||||
if let Some((_, sp)) = const_stability {
|
if let Some((_, sp)) = const_stability {
|
||||||
sess.parse_sess
|
sess.emit_err(MacroConstStability {
|
||||||
.span_diagnostic
|
span: sp,
|
||||||
.struct_span_err(sp, "macros cannot have const stability attributes")
|
head_span: sess.source_map().guess_head_span(span),
|
||||||
.span_label(sp, "invalid const stability attribute")
|
});
|
||||||
.span_label(
|
|
||||||
sess.source_map().guess_head_span(span),
|
|
||||||
"const stability attribute affects this macro",
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
if let Some((_, sp)) = body_stability {
|
if let Some((_, sp)) = body_stability {
|
||||||
sess.parse_sess
|
sess.emit_err(MacroBodyStability {
|
||||||
.span_diagnostic
|
span: sp,
|
||||||
.struct_span_err(sp, "macros cannot have body stability attributes")
|
head_span: sess.source_map().guess_head_span(span),
|
||||||
.span_label(sp, "invalid body stability attribute")
|
});
|
||||||
.span_label(
|
|
||||||
sess.source_map().guess_head_span(span),
|
|
||||||
"body stability attribute affects this macro",
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SyntaxExtension {
|
SyntaxExtension {
|
||||||
@ -1200,13 +1198,11 @@ pub fn resolve_path(
|
|||||||
.expect("attempting to resolve a file path in an external file"),
|
.expect("attempting to resolve a file path in an external file"),
|
||||||
FileName::DocTest(path, _) => path,
|
FileName::DocTest(path, _) => path,
|
||||||
other => {
|
other => {
|
||||||
return Err(parse_sess.span_diagnostic.struct_span_err(
|
return Err(ResolveRelativePath {
|
||||||
span,
|
span,
|
||||||
&format!(
|
path: parse_sess.source_map().filename_for_diagnostics(&other).to_string(),
|
||||||
"cannot resolve relative path in non-file source `{}`",
|
}
|
||||||
parse_sess.source_map().filename_for_diagnostics(&other)
|
.into_diagnostic(&parse_sess.span_diagnostic));
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
result.pop();
|
result.pop();
|
||||||
@ -1222,6 +1218,8 @@ pub fn resolve_path(
|
|||||||
/// The returned bool indicates whether an applicable suggestion has already been
|
/// The returned bool indicates whether an applicable suggestion has already been
|
||||||
/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
|
/// added to the diagnostic to avoid emitting multiple suggestions. `Err(None)`
|
||||||
/// indicates that an ast error was encountered.
|
/// 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>(
|
pub fn expr_to_spanned_string<'a>(
|
||||||
cx: &'a mut ExtCtxt<'_>,
|
cx: &'a mut ExtCtxt<'_>,
|
||||||
expr: P<ast::Expr>,
|
expr: P<ast::Expr>,
|
||||||
@ -1280,9 +1278,9 @@ pub fn expr_to_string(
|
|||||||
/// compilation should call
|
/// compilation should call
|
||||||
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
|
/// `cx.parse_sess.span_diagnostic.abort_if_errors()` (this should be
|
||||||
/// done as rarely as possible).
|
/// done as rarely as possible).
|
||||||
pub fn check_zero_tts(cx: &ExtCtxt<'_>, sp: Span, tts: TokenStream, name: &str) {
|
pub fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, name: &str) {
|
||||||
if !tts.is_empty() {
|
if !tts.is_empty() {
|
||||||
cx.span_err(sp, &format!("{} takes no arguments", name));
|
cx.emit_err(TakesNoArguments { span, name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1304,31 +1302,27 @@ pub fn parse_expr(p: &mut parser::Parser<'_>) -> Option<P<ast::Expr>> {
|
|||||||
/// expect exactly one string literal, or emit an error and return `None`.
|
/// expect exactly one string literal, or emit an error and return `None`.
|
||||||
pub fn get_single_str_from_tts(
|
pub fn get_single_str_from_tts(
|
||||||
cx: &mut ExtCtxt<'_>,
|
cx: &mut ExtCtxt<'_>,
|
||||||
sp: Span,
|
span: Span,
|
||||||
tts: TokenStream,
|
tts: TokenStream,
|
||||||
name: &str,
|
name: &str,
|
||||||
) -> Option<Symbol> {
|
) -> Option<Symbol> {
|
||||||
let mut p = cx.new_parser_from_tts(tts);
|
let mut p = cx.new_parser_from_tts(tts);
|
||||||
if p.token == token::Eof {
|
if p.token == token::Eof {
|
||||||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
cx.emit_err(OnlyOneArgument { span, name });
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let ret = parse_expr(&mut p)?;
|
let ret = parse_expr(&mut p)?;
|
||||||
let _ = p.eat(&token::Comma);
|
let _ = p.eat(&token::Comma);
|
||||||
|
|
||||||
if p.token != token::Eof {
|
if p.token != token::Eof {
|
||||||
cx.span_err(sp, &format!("{} takes 1 argument", name));
|
cx.emit_err(OnlyOneArgument { span, name });
|
||||||
}
|
}
|
||||||
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
|
expr_to_string(cx, ret, "argument must be a string literal").map(|(s, _)| s)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extracts comma-separated expressions from `tts`.
|
/// Extracts comma-separated expressions from `tts`.
|
||||||
/// On error, emit it, and return `None`.
|
/// On error, emit it, and return `None`.
|
||||||
pub fn get_exprs_from_tts(
|
pub fn get_exprs_from_tts(cx: &mut ExtCtxt<'_>, tts: TokenStream) -> Option<Vec<P<ast::Expr>>> {
|
||||||
cx: &mut ExtCtxt<'_>,
|
|
||||||
sp: Span,
|
|
||||||
tts: TokenStream,
|
|
||||||
) -> Option<Vec<P<ast::Expr>>> {
|
|
||||||
let mut p = cx.new_parser_from_tts(tts);
|
let mut p = cx.new_parser_from_tts(tts);
|
||||||
let mut es = Vec::new();
|
let mut es = Vec::new();
|
||||||
while p.token != token::Eof {
|
while p.token != token::Eof {
|
||||||
@ -1343,7 +1337,7 @@ pub fn get_exprs_from_tts(
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if p.token != token::Eof {
|
if p.token != token::Eof {
|
||||||
cx.span_err(sp, "expected token: `,`");
|
cx.emit_err(ExpectedCommaInList { span: p.token.span });
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1353,64 +1347,58 @@ pub fn get_exprs_from_tts(
|
|||||||
pub fn parse_macro_name_and_helper_attrs(
|
pub fn parse_macro_name_and_helper_attrs(
|
||||||
diag: &rustc_errors::Handler,
|
diag: &rustc_errors::Handler,
|
||||||
attr: &Attribute,
|
attr: &Attribute,
|
||||||
descr: &str,
|
macro_type: &str,
|
||||||
) -> Option<(Symbol, Vec<Symbol>)> {
|
) -> Option<(Symbol, Vec<Symbol>)> {
|
||||||
// Once we've located the `#[proc_macro_derive]` attribute, verify
|
// Once we've located the `#[proc_macro_derive]` attribute, verify
|
||||||
// that it's of the form `#[proc_macro_derive(Foo)]` or
|
// that it's of the form `#[proc_macro_derive(Foo)]` or
|
||||||
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
|
// `#[proc_macro_derive(Foo, attributes(A, ..))]`
|
||||||
let list = attr.meta_item_list()?;
|
let list = attr.meta_item_list()?;
|
||||||
if list.len() != 1 && list.len() != 2 {
|
if list.len() != 1 && list.len() != 2 {
|
||||||
diag.span_err(attr.span, "attribute must have either one or two arguments");
|
diag.emit_err(AttrNoArguments { span: attr.span });
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
let Some(trait_attr) = list[0].meta_item() else {
|
let Some(trait_attr) = list[0].meta_item() else {
|
||||||
diag.span_err(list[0].span(), "not a meta item");
|
diag.emit_err(NotAMetaItem {span: list[0].span()});
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let trait_ident = match trait_attr.ident() {
|
let trait_ident = match trait_attr.ident() {
|
||||||
Some(trait_ident) if trait_attr.is_word() => trait_ident,
|
Some(trait_ident) if trait_attr.is_word() => trait_ident,
|
||||||
_ => {
|
_ => {
|
||||||
diag.span_err(trait_attr.span, "must only be one word");
|
diag.emit_err(OnlyOneWord { span: trait_attr.span });
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if !trait_ident.name.can_be_raw() {
|
if !trait_ident.name.can_be_raw() {
|
||||||
diag.span_err(
|
diag.emit_err(CannotBeNameOfMacro { span: trait_attr.span, trait_ident, macro_type });
|
||||||
trait_attr.span,
|
|
||||||
&format!("`{}` cannot be a name of {} macro", trait_ident, descr),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let attributes_attr = list.get(1);
|
let attributes_attr = list.get(1);
|
||||||
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
|
let proc_attrs: Vec<_> = if let Some(attr) = attributes_attr {
|
||||||
if !attr.has_name(sym::attributes) {
|
if !attr.has_name(sym::attributes) {
|
||||||
diag.span_err(attr.span(), "second argument must be `attributes`");
|
diag.emit_err(ArgumentNotAttributes { span: attr.span() });
|
||||||
}
|
}
|
||||||
attr.meta_item_list()
|
attr.meta_item_list()
|
||||||
.unwrap_or_else(|| {
|
.unwrap_or_else(|| {
|
||||||
diag.span_err(attr.span(), "attribute must be of form: `attributes(foo, bar)`");
|
diag.emit_err(AttributesWrongForm { span: attr.span() });
|
||||||
&[]
|
&[]
|
||||||
})
|
})
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|attr| {
|
.filter_map(|attr| {
|
||||||
let Some(attr) = attr.meta_item() else {
|
let Some(attr) = attr.meta_item() else {
|
||||||
diag.span_err(attr.span(), "not a meta item");
|
diag.emit_err(AttributeMetaItem { span: attr.span() });
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
|
|
||||||
let ident = match attr.ident() {
|
let ident = match attr.ident() {
|
||||||
Some(ident) if attr.is_word() => ident,
|
Some(ident) if attr.is_word() => ident,
|
||||||
_ => {
|
_ => {
|
||||||
diag.span_err(attr.span, "must only be one word");
|
diag.emit_err(AttributeSingleWord { span: attr.span });
|
||||||
return None;
|
return None;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !ident.name.can_be_raw() {
|
if !ident.name.can_be_raw() {
|
||||||
diag.span_err(
|
diag.emit_err(HelperAttributeNameInvalid { span: attr.span, name: ident });
|
||||||
attr.span,
|
|
||||||
&format!("`{}` cannot be a name of derive helper attribute", ident),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Some(ident.name)
|
Some(ident.name)
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
//! Conditional compilation stripping.
|
//! Conditional compilation stripping.
|
||||||
|
|
||||||
|
use crate::errors::{
|
||||||
|
FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg,
|
||||||
|
MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported,
|
||||||
|
};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::token::{Delimiter, Token, TokenKind};
|
use rustc_ast::token::{Delimiter, Token, TokenKind};
|
||||||
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
|
use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
|
||||||
@ -10,7 +14,6 @@ use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem
|
|||||||
use rustc_attr as attr;
|
use rustc_attr as attr;
|
||||||
use rustc_data_structures::fx::FxHashMap;
|
use rustc_data_structures::fx::FxHashMap;
|
||||||
use rustc_data_structures::map_in_place::MapInPlace;
|
use rustc_data_structures::map_in_place::MapInPlace;
|
||||||
use rustc_errors::{error_code, struct_span_err, Applicability, Handler};
|
|
||||||
use rustc_feature::{Feature, Features, State as FeatureState};
|
use rustc_feature::{Feature, Features, State as FeatureState};
|
||||||
use rustc_feature::{
|
use rustc_feature::{
|
||||||
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
|
ACCEPTED_FEATURES, ACTIVE_FEATURES, REMOVED_FEATURES, STABLE_REMOVED_FEATURES,
|
||||||
@ -33,18 +36,12 @@ pub struct StripUnconfigured<'a> {
|
|||||||
pub lint_node_id: NodeId,
|
pub lint_node_id: NodeId,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_features(
|
fn get_features(sess: &Session, krate_attrs: &[ast::Attribute]) -> Features {
|
||||||
sess: &Session,
|
fn feature_removed(sess: &Session, span: Span, reason: Option<&str>) {
|
||||||
span_handler: &Handler,
|
sess.emit_err(FeatureRemoved {
|
||||||
krate_attrs: &[ast::Attribute],
|
span,
|
||||||
) -> Features {
|
reason: reason.map(|reason| FeatureRemovedReason { reason }),
|
||||||
fn feature_removed(span_handler: &Handler, span: Span, reason: Option<&str>) {
|
});
|
||||||
let mut err = struct_span_err!(span_handler, span, E0557, "feature has been removed");
|
|
||||||
err.span_label(span, "feature has been removed");
|
|
||||||
if let Some(reason) = reason {
|
|
||||||
err.note(reason);
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
|
fn active_features_up_to(edition: Edition) -> impl Iterator<Item = &'static Feature> {
|
||||||
@ -117,34 +114,34 @@ fn get_features(
|
|||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
let bad_input = |span| {
|
|
||||||
struct_span_err!(span_handler, span, E0556, "malformed `feature` attribute input")
|
|
||||||
};
|
|
||||||
|
|
||||||
for mi in list {
|
for mi in list {
|
||||||
let name = match mi.ident() {
|
let name = match mi.ident() {
|
||||||
Some(ident) if mi.is_word() => ident.name,
|
Some(ident) if mi.is_word() => ident.name,
|
||||||
Some(ident) => {
|
Some(ident) => {
|
||||||
bad_input(mi.span())
|
sess.emit_err(MalformedFeatureAttribute {
|
||||||
.span_suggestion(
|
span: mi.span(),
|
||||||
mi.span(),
|
help: MalformedFeatureAttributeHelp::Suggestion {
|
||||||
"expected just one word",
|
span: mi.span(),
|
||||||
ident.name,
|
suggestion: ident.name,
|
||||||
Applicability::MaybeIncorrect,
|
},
|
||||||
)
|
});
|
||||||
.emit();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
bad_input(mi.span()).span_label(mi.span(), "expected just one word").emit();
|
sess.emit_err(MalformedFeatureAttribute {
|
||||||
|
span: mi.span(),
|
||||||
|
help: MalformedFeatureAttributeHelp::Label { span: mi.span() },
|
||||||
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if let Some(edition) = edition_enabled_features.get(&name) {
|
if let Some(&edition) = edition_enabled_features.get(&name) {
|
||||||
let msg =
|
sess.emit_warning(FeatureIncludedInEdition {
|
||||||
&format!("the feature `{}` is included in the Rust {} edition", name, edition);
|
span: mi.span(),
|
||||||
span_handler.struct_span_warn_with_code(mi.span(), msg, error_code!(E0705)).emit();
|
feature: name,
|
||||||
|
edition,
|
||||||
|
});
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,7 +156,7 @@ fn get_features(
|
|||||||
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
|
if let FeatureState::Removed { reason } | FeatureState::Stabilized { reason } =
|
||||||
state
|
state
|
||||||
{
|
{
|
||||||
feature_removed(span_handler, mi.span(), *reason);
|
feature_removed(sess, mi.span(), *reason);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -173,14 +170,7 @@ fn get_features(
|
|||||||
|
|
||||||
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
|
if let Some(allowed) = sess.opts.unstable_opts.allow_features.as_ref() {
|
||||||
if allowed.iter().all(|f| name.as_str() != f) {
|
if allowed.iter().all(|f| name.as_str() != f) {
|
||||||
struct_span_err!(
|
sess.emit_err(FeatureNotAllowed { span: mi.span(), name });
|
||||||
span_handler,
|
|
||||||
mi.span(),
|
|
||||||
E0725,
|
|
||||||
"the feature `{}` is not in the list of allowed features",
|
|
||||||
name
|
|
||||||
)
|
|
||||||
.emit();
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -221,7 +211,7 @@ pub fn features(
|
|||||||
}
|
}
|
||||||
Some(attrs) => {
|
Some(attrs) => {
|
||||||
krate.attrs = attrs;
|
krate.attrs = attrs;
|
||||||
let features = get_features(sess, diag, &krate.attrs);
|
let features = get_features(sess, &krate.attrs);
|
||||||
if err_count == diag.err_count() {
|
if err_count == diag.err_count() {
|
||||||
// Avoid reconfiguring malformed `cfg_attr`s.
|
// Avoid reconfiguring malformed `cfg_attr`s.
|
||||||
strip_unconfigured.features = Some(&features);
|
strip_unconfigured.features = Some(&features);
|
||||||
@ -503,8 +493,7 @@ impl<'a> StripUnconfigured<'a> {
|
|||||||
// N.B., this is intentionally not part of the visit_expr() function
|
// N.B., this is intentionally not part of the visit_expr() function
|
||||||
// in order for filter_map_expr() to be able to avoid this check
|
// in order for filter_map_expr() to be able to avoid this check
|
||||||
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
|
if let Some(attr) = expr.attrs().iter().find(|a| is_cfg(*a)) {
|
||||||
let msg = "removing an expression is not supported in this position";
|
self.sess.emit_err(RemoveExprNotSupported { span: attr.span });
|
||||||
self.sess.parse_sess.span_diagnostic.span_err(attr.span, msg);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.process_cfg_attrs(expr);
|
self.process_cfg_attrs(expr);
|
||||||
@ -513,27 +502,26 @@ impl<'a> StripUnconfigured<'a> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
|
pub fn parse_cfg<'a>(meta_item: &'a MetaItem, sess: &Session) -> Option<&'a MetaItem> {
|
||||||
let error = |span, msg, suggestion: &str| {
|
|
||||||
let mut err = sess.parse_sess.span_diagnostic.struct_span_err(span, msg);
|
|
||||||
if !suggestion.is_empty() {
|
|
||||||
err.span_suggestion(
|
|
||||||
span,
|
|
||||||
"expected syntax is",
|
|
||||||
suggestion,
|
|
||||||
Applicability::HasPlaceholders,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
err.emit();
|
|
||||||
None
|
|
||||||
};
|
|
||||||
let span = meta_item.span;
|
let span = meta_item.span;
|
||||||
match meta_item.meta_item_list() {
|
match meta_item.meta_item_list() {
|
||||||
None => error(span, "`cfg` is not followed by parentheses", "cfg(/* predicate */)"),
|
None => {
|
||||||
Some([]) => error(span, "`cfg` predicate is not specified", ""),
|
sess.emit_err(InvalidCfg::NotFollowedByParens { span });
|
||||||
Some([_, .., l]) => error(l.span(), "multiple `cfg` predicates are specified", ""),
|
None
|
||||||
|
}
|
||||||
|
Some([]) => {
|
||||||
|
sess.emit_err(InvalidCfg::NoPredicate { span });
|
||||||
|
None
|
||||||
|
}
|
||||||
|
Some([_, .., l]) => {
|
||||||
|
sess.emit_err(InvalidCfg::MultiplePredicates { span: l.span() });
|
||||||
|
None
|
||||||
|
}
|
||||||
Some([single]) => match single.meta_item() {
|
Some([single]) => match single.meta_item() {
|
||||||
Some(meta_item) => Some(meta_item),
|
Some(meta_item) => Some(meta_item),
|
||||||
None => error(single.span(), "`cfg` predicate key cannot be a literal", ""),
|
None => {
|
||||||
|
sess.emit_err(InvalidCfg::PredicateLiteral { span: single.span() });
|
||||||
|
None
|
||||||
|
}
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
|
use rustc_ast::ast;
|
||||||
use rustc_macros::Diagnostic;
|
use rustc_macros::Diagnostic;
|
||||||
use rustc_span::symbol::MacroRulesNormalizedIdent;
|
use rustc_session::Limit;
|
||||||
use rustc_span::Span;
|
use rustc_span::edition::Edition;
|
||||||
|
use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
|
||||||
|
use rustc_span::{Span, Symbol};
|
||||||
|
use std::borrow::Cow;
|
||||||
|
|
||||||
#[derive(Diagnostic)]
|
#[derive(Diagnostic)]
|
||||||
#[diag(expand_expr_repeat_no_syntax_vars)]
|
#[diag(expand_expr_repeat_no_syntax_vars)]
|
||||||
@ -46,3 +50,321 @@ pub(crate) struct MetaVarsDifSeqMatchers {
|
|||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub msg: String,
|
pub msg: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_resolve_relative_path)]
|
||||||
|
pub(crate) struct ResolveRelativePath {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_macro_const_stability)]
|
||||||
|
pub(crate) struct MacroConstStability {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[label(label2)]
|
||||||
|
pub head_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_macro_body_stability)]
|
||||||
|
pub(crate) struct MacroBodyStability {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[label(label2)]
|
||||||
|
pub head_span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_attr_no_arguments)]
|
||||||
|
pub(crate) struct AttrNoArguments {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_not_a_meta_item)]
|
||||||
|
pub(crate) struct NotAMetaItem {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_only_one_word)]
|
||||||
|
pub(crate) struct OnlyOneWord {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_cannot_be_name_of_macro)]
|
||||||
|
pub(crate) struct CannotBeNameOfMacro<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub trait_ident: Ident,
|
||||||
|
pub macro_type: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_arg_not_attributes)]
|
||||||
|
pub(crate) struct ArgumentNotAttributes {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_attributes_wrong_form)]
|
||||||
|
pub(crate) struct AttributesWrongForm {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_attribute_meta_item)]
|
||||||
|
pub(crate) struct AttributeMetaItem {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_attribute_single_word)]
|
||||||
|
pub(crate) struct AttributeSingleWord {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_helper_attribute_name_invalid)]
|
||||||
|
pub(crate) struct HelperAttributeNameInvalid {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
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_included_in_edition, code = "E0705")]
|
||||||
|
pub(crate) struct FeatureIncludedInEdition {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub feature: Symbol,
|
||||||
|
pub edition: Edition,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_feature_removed, code = "E0557")]
|
||||||
|
pub(crate) struct FeatureRemoved<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
#[label]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub reason: Option<FeatureRemovedReason<'a>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(reason)]
|
||||||
|
pub(crate) struct FeatureRemovedReason<'a> {
|
||||||
|
pub reason: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_feature_not_allowed, code = "E0725")]
|
||||||
|
pub(crate) struct FeatureNotAllowed {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: Symbol,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_recursion_limit_reached)]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct RecursionLimitReached<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub descr: String,
|
||||||
|
pub suggested_limit: Limit,
|
||||||
|
pub crate_name: &'a str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_malformed_feature_attribute, code = "E0556")]
|
||||||
|
pub(crate) struct MalformedFeatureAttribute {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub help: MalformedFeatureAttributeHelp,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
pub(crate) enum MalformedFeatureAttributeHelp {
|
||||||
|
#[label(expected)]
|
||||||
|
Label {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[suggestion(expected, code = "{suggestion}", applicability = "maybe-incorrect")]
|
||||||
|
Suggestion {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
suggestion: Symbol,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_remove_expr_not_supported)]
|
||||||
|
pub(crate) struct RemoveExprNotSupported {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
pub(crate) enum InvalidCfg {
|
||||||
|
#[diag(expand_invalid_cfg_no_parens)]
|
||||||
|
NotFollowedByParens {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(
|
||||||
|
expand_invalid_cfg_expected_syntax,
|
||||||
|
code = "cfg(/* predicate */)",
|
||||||
|
applicability = "has-placeholders"
|
||||||
|
)]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[diag(expand_invalid_cfg_no_predicate)]
|
||||||
|
NoPredicate {
|
||||||
|
#[primary_span]
|
||||||
|
#[suggestion(
|
||||||
|
expand_invalid_cfg_expected_syntax,
|
||||||
|
code = "cfg(/* predicate */)",
|
||||||
|
applicability = "has-placeholders"
|
||||||
|
)]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[diag(expand_invalid_cfg_multiple_predicates)]
|
||||||
|
MultiplePredicates {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
#[diag(expand_invalid_cfg_predicate_literal)]
|
||||||
|
PredicateLiteral {
|
||||||
|
#[primary_span]
|
||||||
|
span: Span,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_wrong_fragment_kind)]
|
||||||
|
pub(crate) struct WrongFragmentKind<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub kind: &'a str,
|
||||||
|
pub name: &'a ast::Path,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_unsupported_key_value)]
|
||||||
|
pub(crate) struct UnsupportedKeyValue {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_incomplete_parse)]
|
||||||
|
#[note]
|
||||||
|
pub(crate) struct IncompleteParse<'a> {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub token: Cow<'a, str>,
|
||||||
|
#[label]
|
||||||
|
pub label_span: Span,
|
||||||
|
pub macro_path: &'a ast::Path,
|
||||||
|
pub kind_name: &'a str,
|
||||||
|
|
||||||
|
#[suggestion(
|
||||||
|
suggestion_add_semi,
|
||||||
|
style = "verbose",
|
||||||
|
code = ";",
|
||||||
|
applicability = "maybe-incorrect"
|
||||||
|
)]
|
||||||
|
pub add_semicolon: Option<Span>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_remove_node_not_supported)]
|
||||||
|
pub(crate) struct RemoveNodeNotSupported {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub descr: &'static str,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_module_circular)]
|
||||||
|
pub(crate) struct ModuleCircular {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub modules: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_module_in_block)]
|
||||||
|
pub(crate) struct ModuleInBlock {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
#[subdiagnostic]
|
||||||
|
pub name: Option<ModuleInBlockName>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subdiagnostic)]
|
||||||
|
#[note(note)]
|
||||||
|
pub(crate) struct ModuleInBlockName {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: Ident,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_module_file_not_found, code = "E0583")]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct ModuleFileNotFound {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: Ident,
|
||||||
|
pub default_path: String,
|
||||||
|
pub secondary_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Diagnostic)]
|
||||||
|
#[diag(expand_module_multiple_candidates, code = "E0761")]
|
||||||
|
#[help]
|
||||||
|
pub(crate) struct ModuleMultipleCandidates {
|
||||||
|
#[primary_span]
|
||||||
|
pub span: Span,
|
||||||
|
pub name: Ident,
|
||||||
|
pub default_path: String,
|
||||||
|
pub secondary_path: String,
|
||||||
|
}
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
use crate::base::*;
|
use crate::base::*;
|
||||||
use crate::config::StripUnconfigured;
|
use crate::config::StripUnconfigured;
|
||||||
|
use crate::errors::{
|
||||||
|
IncompleteParse, RecursionLimitReached, RemoveExprNotSupported, RemoveNodeNotSupported,
|
||||||
|
UnsupportedKeyValue, WrongFragmentKind,
|
||||||
|
};
|
||||||
use crate::hygiene::SyntaxContext;
|
use crate::hygiene::SyntaxContext;
|
||||||
use crate::mbe::diagnostics::annotate_err_with_kind;
|
use crate::mbe::diagnostics::annotate_err_with_kind;
|
||||||
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
|
use crate::module::{mod_dir_path, parse_external_mod, DirOwnership, ParsedExternalMod};
|
||||||
@ -18,7 +22,7 @@ use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
|
|||||||
use rustc_ast_pretty::pprust;
|
use rustc_ast_pretty::pprust;
|
||||||
use rustc_data_structures::map_in_place::MapInPlace;
|
use rustc_data_structures::map_in_place::MapInPlace;
|
||||||
use rustc_data_structures::sync::Lrc;
|
use rustc_data_structures::sync::Lrc;
|
||||||
use rustc_errors::{Applicability, PResult};
|
use rustc_errors::PResult;
|
||||||
use rustc_feature::Features;
|
use rustc_feature::Features;
|
||||||
use rustc_parse::parser::{
|
use rustc_parse::parser::{
|
||||||
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
|
AttemptLocalParseRecovery, CommaRecoveryMode, ForceCollect, Parser, RecoverColon, RecoverComma,
|
||||||
@ -606,29 +610,22 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
Limit(0) => Limit(2),
|
Limit(0) => Limit(2),
|
||||||
limit => limit * 2,
|
limit => limit * 2,
|
||||||
};
|
};
|
||||||
self.cx
|
|
||||||
.struct_span_err(
|
self.cx.emit_err(RecursionLimitReached {
|
||||||
expn_data.call_site,
|
span: expn_data.call_site,
|
||||||
&format!("recursion limit reached while expanding `{}`", expn_data.kind.descr()),
|
descr: expn_data.kind.descr(),
|
||||||
)
|
suggested_limit,
|
||||||
.help(&format!(
|
crate_name: &self.cx.ecfg.crate_name,
|
||||||
"consider increasing the recursion limit by adding a \
|
});
|
||||||
`#![recursion_limit = \"{}\"]` attribute to your crate (`{}`)",
|
|
||||||
suggested_limit, self.cx.ecfg.crate_name,
|
|
||||||
))
|
|
||||||
.emit();
|
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A macro's expansion does not fit in this fragment kind.
|
/// A macro's expansion does not fit in this fragment kind.
|
||||||
/// For example, a non-type macro in a type position.
|
/// For example, a non-type macro in a type position.
|
||||||
fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
|
fn error_wrong_fragment_kind(&mut self, kind: AstFragmentKind, mac: &ast::MacCall, span: Span) {
|
||||||
let msg = format!(
|
self.cx.emit_err(WrongFragmentKind { span, kind: kind.name(), name: &mac.path });
|
||||||
"non-{kind} macro in {kind} position: {path}",
|
|
||||||
kind = kind.name(),
|
|
||||||
path = pprust::path_to_string(&mac.path),
|
|
||||||
);
|
|
||||||
self.cx.span_err(span, &msg);
|
|
||||||
self.cx.trace_macros_diag();
|
self.cx.trace_macros_diag();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -707,7 +704,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
};
|
};
|
||||||
let attr_item = attr.unwrap_normal_item();
|
let attr_item = attr.unwrap_normal_item();
|
||||||
if let AttrArgs::Eq(..) = attr_item.args {
|
if let AttrArgs::Eq(..) = attr_item.args {
|
||||||
self.cx.span_err(span, "key-value macro attributes are not supported");
|
self.cx.emit_err(UnsupportedKeyValue { span });
|
||||||
}
|
}
|
||||||
let inner_tokens = attr_item.args.inner_tokens();
|
let inner_tokens = attr_item.args.inner_tokens();
|
||||||
let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else {
|
let Ok(tok_result) = expander.expand(self.cx, span, inner_tokens, tokens) else {
|
||||||
@ -729,9 +726,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
|
if fragment_kind == AstFragmentKind::Expr && items.is_empty() {
|
||||||
let msg =
|
self.cx.emit_err(RemoveExprNotSupported { span });
|
||||||
"removing an expression is not supported in this position";
|
|
||||||
self.cx.span_err(span, msg);
|
|
||||||
fragment_kind.dummy(span)
|
fragment_kind.dummy(span)
|
||||||
} else {
|
} else {
|
||||||
fragment_kind.expect_from_annotatables(items)
|
fragment_kind.expect_from_annotatables(items)
|
||||||
@ -939,38 +934,32 @@ pub fn parse_ast_fragment<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub fn ensure_complete_parse<'a>(
|
pub fn ensure_complete_parse<'a>(
|
||||||
this: &mut Parser<'a>,
|
parser: &mut Parser<'a>,
|
||||||
macro_path: &ast::Path,
|
macro_path: &ast::Path,
|
||||||
kind_name: &str,
|
kind_name: &str,
|
||||||
span: Span,
|
span: Span,
|
||||||
) {
|
) {
|
||||||
if this.token != token::Eof {
|
if parser.token != token::Eof {
|
||||||
let token = pprust::token_to_string(&this.token);
|
let token = pprust::token_to_string(&parser.token);
|
||||||
let msg = format!("macro expansion ignores token `{}` and any following", token);
|
|
||||||
// Avoid emitting backtrace info twice.
|
// Avoid emitting backtrace info twice.
|
||||||
let def_site_span = this.token.span.with_ctxt(SyntaxContext::root());
|
let def_site_span = parser.token.span.with_ctxt(SyntaxContext::root());
|
||||||
let mut err = this.struct_span_err(def_site_span, &msg);
|
|
||||||
err.span_label(span, "caused by the macro expansion here");
|
|
||||||
let msg = format!(
|
|
||||||
"the usage of `{}!` is likely invalid in {} context",
|
|
||||||
pprust::path_to_string(macro_path),
|
|
||||||
kind_name,
|
|
||||||
);
|
|
||||||
err.note(&msg);
|
|
||||||
|
|
||||||
let semi_span = this.sess.source_map().next_point(span);
|
let semi_span = parser.sess.source_map().next_point(span);
|
||||||
match this.sess.source_map().span_to_snippet(semi_span) {
|
let add_semicolon = match parser.sess.source_map().span_to_snippet(semi_span) {
|
||||||
Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
|
Ok(ref snippet) if &snippet[..] != ";" && kind_name == "expression" => {
|
||||||
err.span_suggestion(
|
Some(span.shrink_to_hi())
|
||||||
span.shrink_to_hi(),
|
|
||||||
"you might be missing a semicolon here",
|
|
||||||
";",
|
|
||||||
Applicability::MaybeIncorrect,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => None,
|
||||||
}
|
};
|
||||||
err.emit();
|
|
||||||
|
parser.sess.emit_err(IncompleteParse {
|
||||||
|
span: def_site_span,
|
||||||
|
token,
|
||||||
|
label_span: span,
|
||||||
|
macro_path,
|
||||||
|
kind_name,
|
||||||
|
add_semicolon,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1766,9 +1755,8 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
|
|||||||
if self.expand_cfg_true(node, attr, pos) {
|
if self.expand_cfg_true(node, attr, pos) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
let msg =
|
|
||||||
format!("removing {} is not supported in this position", Node::descr());
|
self.cx.emit_err(RemoveNodeNotSupported { span, descr: Node::descr() });
|
||||||
self.cx.span_err(span, &msg);
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
sym::cfg_attr => {
|
sym::cfg_attr => {
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#![feature(rustc_attrs)]
|
#![feature(rustc_attrs)]
|
||||||
#![feature(try_blocks)]
|
#![feature(try_blocks)]
|
||||||
#![recursion_limit = "256"]
|
#![recursion_limit = "256"]
|
||||||
|
#![deny(rustc::untranslatable_diagnostic)]
|
||||||
|
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate rustc_macros;
|
extern crate rustc_macros;
|
||||||
@ -31,8 +32,13 @@ pub mod config;
|
|||||||
pub mod errors;
|
pub mod errors;
|
||||||
pub mod expand;
|
pub mod expand;
|
||||||
pub mod module;
|
pub mod module;
|
||||||
|
|
||||||
|
// FIXME(Nilstrieb) Translate proc_macro diagnostics
|
||||||
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
pub mod proc_macro;
|
pub mod proc_macro;
|
||||||
|
|
||||||
|
// FIXME(Nilstrieb) Translate macro_rules diagnostics
|
||||||
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
pub(crate) mod mbe;
|
pub(crate) mod mbe;
|
||||||
|
|
||||||
// HACK(Centril, #64197): These shouldn't really be here.
|
// HACK(Centril, #64197): These shouldn't really be here.
|
||||||
|
@ -1,13 +1,17 @@
|
|||||||
use crate::base::ModuleData;
|
use crate::base::ModuleData;
|
||||||
|
use crate::errors::{
|
||||||
|
ModuleCircular, ModuleFileNotFound, ModuleInBlock, ModuleInBlockName, ModuleMultipleCandidates,
|
||||||
|
};
|
||||||
use rustc_ast::ptr::P;
|
use rustc_ast::ptr::P;
|
||||||
use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
|
use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
|
||||||
use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
|
use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
|
||||||
use rustc_parse::new_parser_from_file;
|
use rustc_parse::new_parser_from_file;
|
||||||
use rustc_parse::validate_attr;
|
use rustc_parse::validate_attr;
|
||||||
use rustc_session::parse::ParseSess;
|
use rustc_session::parse::ParseSess;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use rustc_span::symbol::{sym, Ident};
|
use rustc_span::symbol::{sym, Ident};
|
||||||
use rustc_span::Span;
|
use rustc_span::Span;
|
||||||
|
use std::iter::once;
|
||||||
|
|
||||||
use std::path::{self, Path, PathBuf};
|
use std::path::{self, Path, PathBuf};
|
||||||
|
|
||||||
@ -242,57 +246,41 @@ pub fn default_submod_path<'a>(
|
|||||||
|
|
||||||
impl ModError<'_> {
|
impl ModError<'_> {
|
||||||
fn report(self, sess: &Session, span: Span) -> ErrorGuaranteed {
|
fn report(self, sess: &Session, span: Span) -> ErrorGuaranteed {
|
||||||
let diag = &sess.parse_sess.span_diagnostic;
|
|
||||||
match self {
|
match self {
|
||||||
ModError::CircularInclusion(file_paths) => {
|
ModError::CircularInclusion(file_paths) => {
|
||||||
let mut msg = String::from("circular modules: ");
|
let path_to_string = |path: &PathBuf| path.display().to_string();
|
||||||
for file_path in &file_paths {
|
|
||||||
msg.push_str(&file_path.display().to_string());
|
let paths = file_paths
|
||||||
msg.push_str(" -> ");
|
.iter()
|
||||||
}
|
.map(path_to_string)
|
||||||
msg.push_str(&file_paths[0].display().to_string());
|
.chain(once(path_to_string(&file_paths[0])))
|
||||||
diag.struct_span_err(span, &msg)
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let modules = paths.join(" -> ");
|
||||||
|
|
||||||
|
sess.emit_err(ModuleCircular { span, modules })
|
||||||
}
|
}
|
||||||
ModError::ModInBlock(ident) => {
|
ModError::ModInBlock(ident) => sess.emit_err(ModuleInBlock {
|
||||||
let msg = "cannot declare a non-inline module inside a block unless it has a path attribute";
|
span,
|
||||||
let mut err = diag.struct_span_err(span, msg);
|
name: ident.map(|name| ModuleInBlockName { span, name }),
|
||||||
if let Some(ident) = ident {
|
}),
|
||||||
let note =
|
ModError::FileNotFound(name, default_path, secondary_path) => {
|
||||||
format!("maybe `use` the module `{}` instead of redeclaring it", ident);
|
sess.emit_err(ModuleFileNotFound {
|
||||||
err.span_note(span, ¬e);
|
|
||||||
}
|
|
||||||
err
|
|
||||||
}
|
|
||||||
ModError::FileNotFound(ident, default_path, secondary_path) => {
|
|
||||||
let mut err = struct_span_err!(
|
|
||||||
diag,
|
|
||||||
span,
|
span,
|
||||||
E0583,
|
name,
|
||||||
"file not found for module `{}`",
|
default_path: default_path.display().to_string(),
|
||||||
ident,
|
secondary_path: secondary_path.display().to_string(),
|
||||||
);
|
})
|
||||||
err.help(&format!(
|
|
||||||
"to create the module `{}`, create file \"{}\" or \"{}\"",
|
|
||||||
ident,
|
|
||||||
default_path.display(),
|
|
||||||
secondary_path.display(),
|
|
||||||
));
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
ModError::MultipleCandidates(ident, default_path, secondary_path) => {
|
ModError::MultipleCandidates(name, default_path, secondary_path) => {
|
||||||
let mut err = struct_span_err!(
|
sess.emit_err(ModuleMultipleCandidates {
|
||||||
diag,
|
|
||||||
span,
|
span,
|
||||||
E0761,
|
name,
|
||||||
"file for module `{}` found at both \"{}\" and \"{}\"",
|
default_path: default_path.display().to_string(),
|
||||||
ident,
|
secondary_path: secondary_path.display().to_string(),
|
||||||
default_path.display(),
|
})
|
||||||
secondary_path.display(),
|
|
||||||
);
|
|
||||||
err.help("delete or rename one of them to remove the ambiguity");
|
|
||||||
err
|
|
||||||
}
|
}
|
||||||
ModError::ParserError(err) => err,
|
ModError::ParserError(mut err) => err.emit(),
|
||||||
}.emit()
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -154,6 +154,7 @@ fn test_harness(file_text: &str, span_labels: Vec<SpanLabel>, expected_output: &
|
|||||||
false,
|
false,
|
||||||
);
|
);
|
||||||
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
let handler = Handler::with_emitter(true, None, Box::new(emitter));
|
||||||
|
#[allow(rustc::untranslatable_diagnostic)]
|
||||||
handler.span_err(msp, "foo");
|
handler.span_err(msp, "foo");
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
|
@ -2,7 +2,7 @@ error: `cfg` predicate is not specified
|
|||||||
--> $DIR/doc-cfg.rs:3:7
|
--> $DIR/doc-cfg.rs:3:7
|
||||||
|
|
|
|
||||||
LL | #[doc(cfg(), cfg(foo, bar))]
|
LL | #[doc(cfg(), cfg(foo, bar))]
|
||||||
| ^^^^^
|
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||||
|
|
||||||
error: multiple `cfg` predicates are specified
|
error: multiple `cfg` predicates are specified
|
||||||
--> $DIR/doc-cfg.rs:3:23
|
--> $DIR/doc-cfg.rs:3:23
|
||||||
@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
|
|||||||
--> $DIR/doc-cfg.rs:7:7
|
--> $DIR/doc-cfg.rs:7:7
|
||||||
|
|
|
|
||||||
LL | #[doc(cfg())]
|
LL | #[doc(cfg())]
|
||||||
| ^^^^^
|
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||||
|
|
||||||
error: multiple `cfg` predicates are specified
|
error: multiple `cfg` predicates are specified
|
||||||
--> $DIR/doc-cfg.rs:8:16
|
--> $DIR/doc-cfg.rs:8:16
|
||||||
|
@ -14,7 +14,7 @@ error: `cfg` predicate is not specified
|
|||||||
--> $DIR/cfg-attr-syntax-validation.rs:7:1
|
--> $DIR/cfg-attr-syntax-validation.rs:7:1
|
||||||
|
|
|
|
||||||
LL | #[cfg()]
|
LL | #[cfg()]
|
||||||
| ^^^^^^^^
|
| ^^^^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||||
|
|
||||||
error: multiple `cfg` predicates are specified
|
error: multiple `cfg` predicates are specified
|
||||||
--> $DIR/cfg-attr-syntax-validation.rs:10:10
|
--> $DIR/cfg-attr-syntax-validation.rs:10:10
|
||||||
|
@ -5,11 +5,13 @@ LL | assert_eq!("B", "B");
|
|||||||
| ^^^^^^^^^
|
| ^^^^^^^^^
|
||||||
...
|
...
|
||||||
LL | foo!()
|
LL | foo!()
|
||||||
| ------- help: you might be missing a semicolon here: `;`
|
| ------ caused by the macro expansion here
|
||||||
| |
|
|
||||||
| caused by the macro expansion here
|
|
||||||
|
|
|
|
||||||
= note: the usage of `foo!` is likely invalid in expression context
|
= note: the usage of `foo!` is likely invalid in expression context
|
||||||
|
help: you might be missing a semicolon here
|
||||||
|
|
|
||||||
|
LL | foo!();
|
||||||
|
| +
|
||||||
|
|
||||||
warning: trailing semicolon in macro used in expression position
|
warning: trailing semicolon in macro used in expression position
|
||||||
--> $DIR/macro-in-expression-context.rs:5:29
|
--> $DIR/macro-in-expression-context.rs:5:29
|
||||||
|
@ -8,21 +8,25 @@ error: macro expansion ignores token `,` and any following
|
|||||||
--> $DIR/attr-invalid-exprs.rs:15:13
|
--> $DIR/attr-invalid-exprs.rs:15:13
|
||||||
|
|
|
|
||||||
LL | let _ = #[duplicate] "Hello, world!";
|
LL | let _ = #[duplicate] "Hello, world!";
|
||||||
| ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
|
| ^^^^^^^^^^^^ caused by the macro expansion here
|
||||||
| |
|
|
||||||
| caused by the macro expansion here
|
|
||||||
|
|
|
|
||||||
= note: the usage of `duplicate!` is likely invalid in expression context
|
= note: the usage of `duplicate!` is likely invalid in expression context
|
||||||
|
help: you might be missing a semicolon here
|
||||||
|
|
|
||||||
|
LL | let _ = #[duplicate]; "Hello, world!";
|
||||||
|
| +
|
||||||
|
|
||||||
error: macro expansion ignores token `,` and any following
|
error: macro expansion ignores token `,` and any following
|
||||||
--> $DIR/attr-invalid-exprs.rs:24:9
|
--> $DIR/attr-invalid-exprs.rs:24:9
|
||||||
|
|
|
|
||||||
LL | #[duplicate]
|
LL | #[duplicate]
|
||||||
| ^^^^^^^^^^^^- help: you might be missing a semicolon here: `;`
|
| ^^^^^^^^^^^^ caused by the macro expansion here
|
||||||
| |
|
|
||||||
| caused by the macro expansion here
|
|
||||||
|
|
|
|
||||||
= note: the usage of `duplicate!` is likely invalid in expression context
|
= note: the usage of `duplicate!` is likely invalid in expression context
|
||||||
|
help: you might be missing a semicolon here
|
||||||
|
|
|
||||||
|
LL | #[duplicate];
|
||||||
|
| +
|
||||||
|
|
||||||
error: aborting due to 3 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
|
@ -53,19 +53,19 @@ pub fn foo11(input: TokenStream) -> TokenStream { input }
|
|||||||
pub fn foo12(input: TokenStream) -> TokenStream { input }
|
pub fn foo12(input: TokenStream) -> TokenStream { input }
|
||||||
|
|
||||||
#[proc_macro_derive(d13, attributes("a"))]
|
#[proc_macro_derive(d13, attributes("a"))]
|
||||||
//~^ ERROR: not a meta item
|
//~^ ERROR: attribute must be a meta item, not a literal
|
||||||
pub fn foo13(input: TokenStream) -> TokenStream { input }
|
pub fn foo13(input: TokenStream) -> TokenStream { input }
|
||||||
|
|
||||||
#[proc_macro_derive(d14, attributes(a = ""))]
|
#[proc_macro_derive(d14, attributes(a = ""))]
|
||||||
//~^ ERROR: must only be one word
|
//~^ ERROR: attribute must only be a single word
|
||||||
pub fn foo14(input: TokenStream) -> TokenStream { input }
|
pub fn foo14(input: TokenStream) -> TokenStream { input }
|
||||||
|
|
||||||
#[proc_macro_derive(d15, attributes(m::a))]
|
#[proc_macro_derive(d15, attributes(m::a))]
|
||||||
//~^ ERROR: must only be one word
|
//~^ ERROR: attribute must only be a single word
|
||||||
pub fn foo15(input: TokenStream) -> TokenStream { input }
|
pub fn foo15(input: TokenStream) -> TokenStream { input }
|
||||||
|
|
||||||
#[proc_macro_derive(d16, attributes(a(b)))]
|
#[proc_macro_derive(d16, attributes(a(b)))]
|
||||||
//~^ ERROR: must only be one word
|
//~^ ERROR: attribute must only be a single word
|
||||||
pub fn foo16(input: TokenStream) -> TokenStream { input }
|
pub fn foo16(input: TokenStream) -> TokenStream { input }
|
||||||
|
|
||||||
#[proc_macro_derive(d17, attributes(self))]
|
#[proc_macro_derive(d17, attributes(self))]
|
||||||
|
@ -70,25 +70,25 @@ error: attribute must be of form: `attributes(foo, bar)`
|
|||||||
LL | #[proc_macro_derive(d12, attributes)]
|
LL | #[proc_macro_derive(d12, attributes)]
|
||||||
| ^^^^^^^^^^
|
| ^^^^^^^^^^
|
||||||
|
|
||||||
error: not a meta item
|
error: attribute must be a meta item, not a literal
|
||||||
--> $DIR/attribute.rs:55:37
|
--> $DIR/attribute.rs:55:37
|
||||||
|
|
|
|
||||||
LL | #[proc_macro_derive(d13, attributes("a"))]
|
LL | #[proc_macro_derive(d13, attributes("a"))]
|
||||||
| ^^^
|
| ^^^
|
||||||
|
|
||||||
error: must only be one word
|
error: attribute must only be a single word
|
||||||
--> $DIR/attribute.rs:59:37
|
--> $DIR/attribute.rs:59:37
|
||||||
|
|
|
|
||||||
LL | #[proc_macro_derive(d14, attributes(a = ""))]
|
LL | #[proc_macro_derive(d14, attributes(a = ""))]
|
||||||
| ^^^^^^
|
| ^^^^^^
|
||||||
|
|
||||||
error: must only be one word
|
error: attribute must only be a single word
|
||||||
--> $DIR/attribute.rs:63:37
|
--> $DIR/attribute.rs:63:37
|
||||||
|
|
|
|
||||||
LL | #[proc_macro_derive(d15, attributes(m::a))]
|
LL | #[proc_macro_derive(d15, attributes(m::a))]
|
||||||
| ^^^^
|
| ^^^^
|
||||||
|
|
||||||
error: must only be one word
|
error: attribute must only be a single word
|
||||||
--> $DIR/attribute.rs:67:37
|
--> $DIR/attribute.rs:67:37
|
||||||
|
|
|
|
||||||
LL | #[proc_macro_derive(d16, attributes(a(b)))]
|
LL | #[proc_macro_derive(d16, attributes(a(b)))]
|
||||||
|
@ -26,21 +26,25 @@ error: macro expansion ignores token `hello` and any following
|
|||||||
--> $DIR/expand-expr.rs:115:47
|
--> $DIR/expand-expr.rs:115:47
|
||||||
|
|
|
|
||||||
LL | expand_expr_is!("string", echo_tts!("string"; hello));
|
LL | expand_expr_is!("string", echo_tts!("string"; hello));
|
||||||
| --------------------^^^^^-- help: you might be missing a semicolon here: `;`
|
| --------------------^^^^^- caused by the macro expansion here
|
||||||
| |
|
|
||||||
| caused by the macro expansion here
|
|
||||||
|
|
|
|
||||||
= note: the usage of `echo_tts!` is likely invalid in expression context
|
= note: the usage of `echo_tts!` is likely invalid in expression context
|
||||||
|
help: you might be missing a semicolon here
|
||||||
|
|
|
||||||
|
LL | expand_expr_is!("string", echo_tts!("string"; hello););
|
||||||
|
| +
|
||||||
|
|
||||||
error: macro expansion ignores token `;` and any following
|
error: macro expansion ignores token `;` and any following
|
||||||
--> $DIR/expand-expr.rs:116:44
|
--> $DIR/expand-expr.rs:116:44
|
||||||
|
|
|
|
||||||
LL | expand_expr_is!("string", echo_pm!("string"; hello));
|
LL | expand_expr_is!("string", echo_pm!("string"; hello));
|
||||||
| -----------------^-------- help: you might be missing a semicolon here: `;`
|
| -----------------^------- caused by the macro expansion here
|
||||||
| |
|
|
||||||
| caused by the macro expansion here
|
|
||||||
|
|
|
|
||||||
= note: the usage of `echo_pm!` is likely invalid in expression context
|
= note: the usage of `echo_pm!` is likely invalid in expression context
|
||||||
|
help: you might be missing a semicolon here
|
||||||
|
|
|
||||||
|
LL | expand_expr_is!("string", echo_pm!("string"; hello););
|
||||||
|
| +
|
||||||
|
|
||||||
error: recursion limit reached while expanding `recursive_expand!`
|
error: recursion limit reached while expanding `recursive_expand!`
|
||||||
--> $DIR/expand-expr.rs:124:16
|
--> $DIR/expand-expr.rs:124:16
|
||||||
|
Loading…
Reference in New Issue
Block a user