Skip to content

Commit 0ecff8c

Browse files
committedJul 19, 2021
Auto merge of #87146 - Aaron1011:better-macro-lint, r=petrochenkov
Compute a better `lint_node_id` during expansion When we need to emit a lint at a macro invocation, we currently use the `NodeId` of its parent definition (e.g. the enclosing function). This means that any `#[allow]` / `#[deny]` attributes placed 'closer' to the macro (e.g. on an enclosing block or statement) will have no effect. This commit computes a better `lint_node_id` in `InvocationCollector`. When we visit/flat_map an AST node, we assign it a `NodeId` (earlier than we normally would), and store than `NodeId` in current `ExpansionData`. When we collect a macro invocation, the current `lint_node_id` gets cloned along with our `ExpansionData`, allowing it to be used if we need to emit a lint later on. This improves the handling of `#[allow]` / `#[deny]` for `SEMICOLON_IN_EXPRESSIONS_FROM_MACROS` and some `asm!`-related lints. The 'legacy derive helpers' lint retains its current behavior (I've inlined the now-removed `lint_node_id` function), since there isn't an `ExpansionData` readily available.
·
1.90.01.55.0
2 parents 10c0b00 + 1c1c794 commit 0ecff8c

File tree

13 files changed

+226
-59
lines changed

13 files changed

+226
-59
lines changed
 

‎compiler/rustc_builtin_macros/src/asm.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -455,15 +455,15 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, args: AsmArgs) -> Option<ast::Inl
455455
ecx.parse_sess().buffer_lint(
456456
lint::builtin::BAD_ASM_STYLE,
457457
find_span(".intel_syntax"),
458-
ecx.resolver.lint_node_id(ecx.current_expansion.id),
458+
ecx.current_expansion.lint_node_id,
459459
"avoid using `.intel_syntax`, Intel syntax is the default",
460460
);
461461
}
462462
if template_str.contains(".att_syntax") {
463463
ecx.parse_sess().buffer_lint(
464464
lint::builtin::BAD_ASM_STYLE,
465465
find_span(".att_syntax"),
466-
ecx.resolver.lint_node_id(ecx.current_expansion.id),
466+
ecx.current_expansion.lint_node_id,
467467
"avoid using `.att_syntax`, prefer using `options(att_syntax)` instead",
468468
);
469469
}

‎compiler/rustc_builtin_macros/src/source_util.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ pub fn expand_include<'cx>(
159159
}
160160
}
161161

162-
Box::new(ExpandResult { p, node_id: cx.resolver.lint_node_id(cx.current_expansion.id) })
162+
Box::new(ExpandResult { p, node_id: cx.current_expansion.lint_node_id })
163163
}
164164

165165
// include_str! : read the given file, insert it as a literal string expr

‎compiler/rustc_expand/src/base.rs‎

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ use std::rc::Rc;
2929

3030
crate use rustc_span::hygiene::MacroKind;
3131

32+
// When adding new variants, make sure to
33+
// adjust the `visit_*` / `flat_map_*` calls in `InvocationCollector`
34+
// to use `assign_id!`
3235
#[derive(Debug, Clone)]
3336
pub enum Annotatable {
3437
Item(P<ast::Item>),
@@ -869,9 +872,6 @@ pub trait ResolverExpand {
869872

870873
fn check_unused_macros(&mut self);
871874

872-
/// Some parent node that is close enough to the given macro call.
873-
fn lint_node_id(&self, expn_id: LocalExpnId) -> NodeId;
874-
875875
// Resolver interfaces for specific built-in macros.
876876
/// Does `#[derive(...)]` attribute with the given `ExpnId` have built-in `Copy` inside it?
877877
fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool;
@@ -926,6 +926,8 @@ pub struct ExpansionData {
926926
pub module: Rc<ModuleData>,
927927
pub dir_ownership: DirOwnership,
928928
pub prior_type_ascription: Option<(Span, bool)>,
929+
/// Some parent node that is close to this macro call
930+
pub lint_node_id: NodeId,
929931
}
930932

931933
type OnExternModLoaded<'a> =
@@ -971,6 +973,7 @@ impl<'a> ExtCtxt<'a> {
971973
module: Default::default(),
972974
dir_ownership: DirOwnership::Owned { relative: None },
973975
prior_type_ascription: None,
976+
lint_node_id: ast::CRATE_NODE_ID,
974977
},
975978
force_mode: false,
976979
expansions: FxHashMap::default(),

‎compiler/rustc_expand/src/expand.rs‎

Lines changed: 83 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use rustc_ast::ptr::P;
1212
use rustc_ast::token;
1313
use rustc_ast::tokenstream::TokenStream;
1414
use rustc_ast::visit::{self, AssocCtxt, Visitor};
15-
use rustc_ast::{AstLike, Block, Inline, ItemKind, MacArgs};
15+
use rustc_ast::{AstLike, Block, Inline, ItemKind, Local, MacArgs};
1616
use rustc_ast::{MacCallStmt, MacStmtStyle, MetaItemKind, ModKind, NestedMetaItem};
1717
use rustc_ast::{NodeId, PatKind, Path, StmtKind, Unsafe};
1818
use rustc_ast_pretty::pprust;
@@ -1098,6 +1098,43 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
10981098
}
10991099
}
11001100

1101+
/// Wraps a call to `noop_visit_*` / `noop_flat_map_*`
1102+
/// for an AST node that supports attributes
1103+
/// (see the `Annotatable` enum)
1104+
/// This method assigns a `NodeId`, and sets that `NodeId`
1105+
/// as our current 'lint node id'. If a macro call is found
1106+
/// inside this AST node, we will use this AST node's `NodeId`
1107+
/// to emit lints associated with that macro (allowing
1108+
/// `#[allow]` / `#[deny]` to be applied close to
1109+
/// the macro invocation).
1110+
///
1111+
/// Do *not* call this for a macro AST node
1112+
/// (e.g. `ExprKind::MacCall`) - we cannot emit lints
1113+
/// at these AST nodes, since they are removed and
1114+
/// replaced with the result of macro expansion.
1115+
///
1116+
/// All other `NodeId`s are assigned by `visit_id`.
1117+
/// * `self` is the 'self' parameter for the current method,
1118+
/// * `id` is a mutable reference to the `NodeId` field
1119+
/// of the current AST node.
1120+
/// * `closure` is a closure that executes the
1121+
/// `noop_visit_*` / `noop_flat_map_*` method
1122+
/// for the current AST node.
1123+
macro_rules! assign_id {
1124+
($self:ident, $id:expr, $closure:expr) => {{
1125+
let old_id = $self.cx.current_expansion.lint_node_id;
1126+
if $self.monotonic {
1127+
debug_assert_eq!(*$id, ast::DUMMY_NODE_ID);
1128+
let new_id = $self.cx.resolver.next_node_id();
1129+
*$id = new_id;
1130+
$self.cx.current_expansion.lint_node_id = new_id;
1131+
}
1132+
let ret = ($closure)();
1133+
$self.cx.current_expansion.lint_node_id = old_id;
1134+
ret
1135+
}};
1136+
}
1137+
11011138
impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11021139
fn visit_expr(&mut self, expr: &mut P<ast::Expr>) {
11031140
self.cfg.configure_expr(expr);
@@ -1118,12 +1155,19 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11181155
self.check_attributes(&expr.attrs);
11191156
self.collect_bang(mac, expr.span, AstFragmentKind::Expr).make_expr().into_inner()
11201157
} else {
1121-
ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1158+
assign_id!(self, &mut expr.id, || {
1159+
ensure_sufficient_stack(|| noop_visit_expr(&mut expr, self));
1160+
});
11221161
expr
11231162
}
11241163
});
11251164
}
11261165

1166+
// This is needed in order to set `lint_node_id` for `let` statements
1167+
fn visit_local(&mut self, local: &mut P<Local>) {
1168+
assign_id!(self, &mut local.id, || noop_visit_local(local, self));
1169+
}
1170+
11271171
fn flat_map_arm(&mut self, arm: ast::Arm) -> SmallVec<[ast::Arm; 1]> {
11281172
let mut arm = configure!(self, arm);
11291173

@@ -1133,7 +1177,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11331177
.make_arms();
11341178
}
11351179

1136-
noop_flat_map_arm(arm, self)
1180+
assign_id!(self, &mut arm.id, || noop_flat_map_arm(arm, self))
11371181
}
11381182

11391183
fn flat_map_expr_field(&mut self, field: ast::ExprField) -> SmallVec<[ast::ExprField; 1]> {
@@ -1145,7 +1189,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11451189
.make_expr_fields();
11461190
}
11471191

1148-
noop_flat_map_expr_field(field, self)
1192+
assign_id!(self, &mut field.id, || noop_flat_map_expr_field(field, self))
11491193
}
11501194

11511195
fn flat_map_pat_field(&mut self, fp: ast::PatField) -> SmallVec<[ast::PatField; 1]> {
@@ -1157,7 +1201,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11571201
.make_pat_fields();
11581202
}
11591203

1160-
noop_flat_map_pat_field(fp, self)
1204+
assign_id!(self, &mut fp.id, || noop_flat_map_pat_field(fp, self))
11611205
}
11621206

11631207
fn flat_map_param(&mut self, p: ast::Param) -> SmallVec<[ast::Param; 1]> {
@@ -1169,7 +1213,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11691213
.make_params();
11701214
}
11711215

1172-
noop_flat_map_param(p, self)
1216+
assign_id!(self, &mut p.id, || noop_flat_map_param(p, self))
11731217
}
11741218

11751219
fn flat_map_field_def(&mut self, sf: ast::FieldDef) -> SmallVec<[ast::FieldDef; 1]> {
@@ -1181,7 +1225,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11811225
.make_field_defs();
11821226
}
11831227

1184-
noop_flat_map_field_def(sf, self)
1228+
assign_id!(self, &mut sf.id, || noop_flat_map_field_def(sf, self))
11851229
}
11861230

11871231
fn flat_map_variant(&mut self, variant: ast::Variant) -> SmallVec<[ast::Variant; 1]> {
@@ -1193,7 +1237,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
11931237
.make_variants();
11941238
}
11951239

1196-
noop_flat_map_variant(variant, self)
1240+
assign_id!(self, &mut variant.id, || noop_flat_map_variant(variant, self))
11971241
}
11981242

11991243
fn filter_map_expr(&mut self, expr: P<ast::Expr>) -> Option<P<ast::Expr>> {
@@ -1214,9 +1258,11 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12141258
.make_opt_expr()
12151259
.map(|expr| expr.into_inner())
12161260
} else {
1217-
Some({
1218-
noop_visit_expr(&mut expr, self);
1219-
expr
1261+
assign_id!(self, &mut expr.id, || {
1262+
Some({
1263+
noop_visit_expr(&mut expr, self);
1264+
expr
1265+
})
12201266
})
12211267
}
12221268
})
@@ -1266,6 +1312,8 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
12661312
}
12671313

12681314
// The placeholder expander gives ids to statements, so we avoid folding the id here.
1315+
// We don't use `assign_id!` - it will be called when we visit statement's contents
1316+
// (e.g. an expression, item, or local)
12691317
let ast::Stmt { id, kind, span } = stmt;
12701318
noop_flat_map_stmt_kind(kind, self)
12711319
.into_iter()
@@ -1377,7 +1425,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13771425
let orig_dir_ownership =
13781426
mem::replace(&mut self.cx.current_expansion.dir_ownership, dir_ownership);
13791427

1380-
let result = noop_flat_map_item(item, self);
1428+
let result = assign_id!(self, &mut item.id, || noop_flat_map_item(item, self));
13811429

13821430
// Restore the module info.
13831431
self.cx.current_expansion.dir_ownership = orig_dir_ownership;
@@ -1387,7 +1435,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
13871435
}
13881436
_ => {
13891437
item.attrs = attrs;
1390-
noop_flat_map_item(item, self)
1438+
// The crate root is special - don't assign an ID to it.
1439+
if !(matches!(item.kind, ast::ItemKind::Mod(..)) && ident == Ident::invalid()) {
1440+
assign_id!(self, &mut item.id, || noop_flat_map_item(item, self))
1441+
} else {
1442+
noop_flat_map_item(item, self)
1443+
}
13911444
}
13921445
}
13931446
}
@@ -1411,7 +1464,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14111464
_ => unreachable!(),
14121465
})
14131466
}
1414-
_ => noop_flat_map_assoc_item(item, self),
1467+
_ => {
1468+
assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1469+
}
14151470
}
14161471
}
14171472

@@ -1434,7 +1489,9 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14341489
_ => unreachable!(),
14351490
})
14361491
}
1437-
_ => noop_flat_map_assoc_item(item, self),
1492+
_ => {
1493+
assign_id!(self, &mut item.id, || noop_flat_map_assoc_item(item, self))
1494+
}
14381495
}
14391496
}
14401497

@@ -1478,7 +1535,12 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14781535
_ => unreachable!(),
14791536
})
14801537
}
1481-
_ => noop_flat_map_foreign_item(foreign_item, self),
1538+
_ => {
1539+
assign_id!(self, &mut foreign_item.id, || noop_flat_map_foreign_item(
1540+
foreign_item,
1541+
self
1542+
))
1543+
}
14821544
}
14831545
}
14841546

@@ -1498,13 +1560,14 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
14981560
.make_generic_params();
14991561
}
15001562

1501-
noop_flat_map_generic_param(param, self)
1563+
assign_id!(self, &mut param.id, || noop_flat_map_generic_param(param, self))
15021564
}
15031565

15041566
fn visit_id(&mut self, id: &mut ast::NodeId) {
1505-
if self.monotonic {
1506-
debug_assert_eq!(*id, ast::DUMMY_NODE_ID);
1507-
*id = self.cx.resolver.next_node_id()
1567+
// We may have already assigned a `NodeId`
1568+
// by calling `assign_id`
1569+
if self.monotonic && *id == ast::DUMMY_NODE_ID {
1570+
*id = self.cx.resolver.next_node_id();
15081571
}
15091572
}
15101573
}

‎compiler/rustc_expand/src/mbe/macro_rules.rs‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -289,7 +289,6 @@ fn generic_extension<'cx>(
289289

290290
let mut p = Parser::new(sess, tts, false, None);
291291
p.last_type_ascription = cx.current_expansion.prior_type_ascription;
292-
let lint_node_id = cx.resolver.lint_node_id(cx.current_expansion.id);
293292

294293
// Let the context choose how to interpret the result.
295294
// Weird, but useful for X-macros.
@@ -301,7 +300,7 @@ fn generic_extension<'cx>(
301300
// macro leaves unparsed tokens.
302301
site_span: sp,
303302
macro_ident: name,
304-
lint_node_id,
303+
lint_node_id: cx.current_expansion.lint_node_id,
305304
arm_span,
306305
});
307306
}

‎compiler/rustc_lint/src/early.rs‎

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
120120
})
121121
}
122122

123+
fn visit_expr_field(&mut self, f: &'a ast::ExprField) {
124+
self.with_lint_attrs(f.id, &f.attrs, |cx| {
125+
ast_visit::walk_expr_field(cx, f);
126+
})
127+
}
128+
123129
fn visit_stmt(&mut self, s: &'a ast::Stmt) {
124130
// Add the statement's lint attributes to our
125131
// current state when checking the statement itself.
@@ -204,8 +210,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T>
204210
}
205211

206212
fn visit_arm(&mut self, a: &'a ast::Arm) {
207-
run_early_pass!(self, check_arm, a);
208-
ast_visit::walk_arm(self, a);
213+
self.with_lint_attrs(a.id, &a.attrs, |cx| {
214+
run_early_pass!(cx, check_arm, a);
215+
ast_visit::walk_arm(cx, a);
216+
})
209217
}
210218

211219
fn visit_expr_post(&mut self, e: &'a ast::Expr) {
@@ -389,9 +397,15 @@ pub fn check_ast_crate<T: EarlyLintPass>(
389397
// All of the buffered lints should have been emitted at this point.
390398
// If not, that means that we somehow buffered a lint for a node id
391399
// that was not lint-checked (perhaps it doesn't exist?). This is a bug.
392-
for (_id, lints) in buffered.map {
400+
for (id, lints) in buffered.map {
393401
for early_lint in lints {
394-
sess.delay_span_bug(early_lint.span, "failed to process buffered lint here");
402+
sess.delay_span_bug(
403+
early_lint.span,
404+
&format!(
405+
"failed to process buffered lint here (dummy = {})",
406+
id == ast::DUMMY_NODE_ID
407+
),
408+
);
395409
}
396410
}
397411
}

‎compiler/rustc_lint_defs/src/lib.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -274,15 +274,15 @@ impl<HCX> ToStableHashKey<HCX> for LintId {
274274
}
275275

276276
// Duplicated from rustc_session::config::ExternDepSpec to avoid cyclic dependency
277-
#[derive(PartialEq)]
277+
#[derive(PartialEq, Debug)]
278278
pub enum ExternDepSpec {
279279
Json(Json),
280280
Raw(String),
281281
}
282282

283283
// This could be a closure, but then implementing derive trait
284284
// becomes hacky (and it gets allocated).
285-
#[derive(PartialEq)]
285+
#[derive(PartialEq, Debug)]
286286
pub enum BuiltinLintDiagnostics {
287287
Normal,
288288
BareTraitObject(Span, /* is_global */ bool),

‎compiler/rustc_resolve/src/macros.rs‎

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,7 @@ impl<'a> ResolverExpand for Resolver<'a> {
281281
// Derives are not included when `invocations` are collected, so we have to add them here.
282282
let parent_scope = &ParentScope { derives, ..parent_scope };
283283
let supports_macro_expansion = invoc.fragment_kind.supports_macro_expansion();
284-
let node_id = self.lint_node_id(eager_expansion_root);
284+
let node_id = invoc.expansion_data.lint_node_id;
285285
let (ext, res) = self.smart_resolve_macro_path(
286286
path,
287287
kind,
@@ -348,14 +348,6 @@ impl<'a> ResolverExpand for Resolver<'a> {
348348
}
349349
}
350350

351-
fn lint_node_id(&self, expn_id: LocalExpnId) -> NodeId {
352-
// FIXME - make this more precise. This currently returns the NodeId of the
353-
// nearest closing item - we should try to return the closest parent of the ExpnId
354-
self.invocation_parents
355-
.get(&expn_id)
356-
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0])
357-
}
358-
359351
fn has_derive_copy(&self, expn_id: LocalExpnId) -> bool {
360352
self.containers_deriving_copy.contains(&expn_id)
361353
}
@@ -1105,9 +1097,13 @@ impl<'a> Resolver<'a> {
11051097
let seg = Segment::from_ident(ident);
11061098
check_consistency(self, &[seg], ident.span, kind, initial_res, res);
11071099
if res == Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat) {
1100+
let node_id = self
1101+
.invocation_parents
1102+
.get(&parent_scope.expansion)
1103+
.map_or(ast::CRATE_NODE_ID, |id| self.def_id_to_node_id[id.0]);
11081104
self.lint_buffer.buffer_lint_with_diagnostic(
11091105
LEGACY_DERIVE_HELPERS,
1110-
self.lint_node_id(parent_scope.expansion),
1106+
node_id,
11111107
ident.span,
11121108
"derive helper attribute is used before it is introduced",
11131109
BuiltinLintDiagnostics::LegacyDeriveHelpers(binding.span),
Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,17 @@
11
// check-pass
22
// edition:2018
3+
#![feature(stmt_expr_attributes)]
34
#![warn(semicolon_in_expressions_from_macros)]
45

56
#[allow(dead_code)]
67
macro_rules! foo {
78
($val:ident) => {
8-
true; //~ WARN trailing
9-
//~| WARN this was previously
10-
//~| WARN trailing
11-
//~| WARN this was previously
9+
true; //~ WARN trailing semicolon in macro
10+
//~| WARN this was previously accepted
11+
//~| WARN trailing semicolon in macro
12+
//~| WARN this was previously accepted
13+
//~| WARN trailing semicolon in macro
14+
//~| WARN this was previously accepted
1215
}
1316
}
1417

@@ -18,17 +21,14 @@ async fn bar() {
1821
}
1922

2023
fn main() {
21-
// This `allow` doesn't work
2224
#[allow(semicolon_in_expressions_from_macros)]
2325
let _ = {
2426
foo!(first)
2527
};
2628

27-
// This 'allow' doesn't work either
2829
#[allow(semicolon_in_expressions_from_macros)]
2930
let _ = foo!(second);
3031

31-
// But this 'allow' does
3232
#[allow(semicolon_in_expressions_from_macros)]
3333
fn inner() {
3434
let _ = foo!(third);
@@ -38,4 +38,14 @@ fn main() {
3838
async {
3939
let _ = foo!(fourth);
4040
};
41+
42+
let _ = {
43+
foo!(warn_in_block)
44+
};
45+
46+
let _ = foo!(warn_in_expr);
47+
48+
// This `#[allow]` does not work, since the attribute gets dropped
49+
// when we expand the macro
50+
let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
4151
}
Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
warning: trailing semicolon in macro used in expression position
2-
--> $DIR/semicolon-in-expressions-from-macros.rs:8:13
2+
--> $DIR/semicolon-in-expressions-from-macros.rs:9:13
33
|
44
LL | true;
55
| ^
66
...
7-
LL | foo!(first)
8-
| ----------- in this macro invocation
7+
LL | foo!(warn_in_block)
8+
| ------------------- in this macro invocation
99
|
1010
note: the lint level is defined here
11-
--> $DIR/semicolon-in-expressions-from-macros.rs:3:9
11+
--> $DIR/semicolon-in-expressions-from-macros.rs:4:9
1212
|
1313
LL | #![warn(semicolon_in_expressions_from_macros)]
1414
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -17,17 +17,30 @@ LL | #![warn(semicolon_in_expressions_from_macros)]
1717
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
1818

1919
warning: trailing semicolon in macro used in expression position
20-
--> $DIR/semicolon-in-expressions-from-macros.rs:8:13
20+
--> $DIR/semicolon-in-expressions-from-macros.rs:9:13
2121
|
2222
LL | true;
2323
| ^
2424
...
25-
LL | let _ = foo!(second);
26-
| ------------ in this macro invocation
25+
LL | let _ = foo!(warn_in_expr);
26+
| ------------------ in this macro invocation
2727
|
2828
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
2929
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
3030
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
3131

32-
warning: 2 warnings emitted
32+
warning: trailing semicolon in macro used in expression position
33+
--> $DIR/semicolon-in-expressions-from-macros.rs:9:13
34+
|
35+
LL | true;
36+
| ^
37+
...
38+
LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
39+
| ------------------------- in this macro invocation
40+
|
41+
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
42+
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
43+
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
44+
45+
warning: 3 warnings emitted
3346

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// force-host
2+
// no-prefer-dynamic
3+
4+
#![crate_type = "proc-macro"]
5+
6+
extern crate proc_macro;
7+
use proc_macro::*;
8+
9+
#[proc_macro_attribute]
10+
#[deprecated(since = "1.0.0", note = "test")]
11+
pub fn attr(_: TokenStream, input: TokenStream) -> TokenStream {
12+
input
13+
}
14+
15+
#[proc_macro_attribute]
16+
#[deprecated(since = "1.0.0", note = "test")]
17+
pub fn attr_remove(_: TokenStream, _: TokenStream) -> TokenStream {
18+
TokenStream::new()
19+
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// check-pass
2+
// aux-build:call-deprecated.rs
3+
4+
extern crate call_deprecated;
5+
6+
// These first two `#[allow(deprecated)]` attributes
7+
// do nothing, since the AST nodes for `First` and `Second`
8+
// haven't been been assigned a `NodeId`.
9+
// See #63221 for a discussion about how we should
10+
// handle the interaction of 'inert' attributes and
11+
// proc-macro attributes.
12+
13+
#[allow(deprecated)]
14+
#[call_deprecated::attr] //~ WARN use of deprecated macro
15+
struct First;
16+
17+
#[allow(deprecated)]
18+
#[call_deprecated::attr_remove] //~ WARN use of deprecated macro
19+
struct Second;
20+
21+
#[allow(deprecated)]
22+
mod bar {
23+
#[allow(deprecated)]
24+
#[call_deprecated::attr]
25+
struct Third;
26+
27+
#[allow(deprecated)]
28+
#[call_deprecated::attr_remove]
29+
struct Fourth;
30+
}
31+
32+
33+
fn main() {
34+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
warning: use of deprecated macro `call_deprecated::attr`: test
2+
--> $DIR/call-deprecated.rs:14:3
3+
|
4+
LL | #[call_deprecated::attr]
5+
| ^^^^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: `#[warn(deprecated)]` on by default
8+
9+
warning: use of deprecated macro `call_deprecated::attr_remove`: test
10+
--> $DIR/call-deprecated.rs:18:3
11+
|
12+
LL | #[call_deprecated::attr_remove]
13+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
14+
15+
warning: 2 warnings emitted
16+

0 commit comments

Comments
 (0)
Please sign in to comment.