@@ -25,6 +25,7 @@ use crate::{
25
25
types:: { transparent_newtype_field, CItemKind } ,
26
26
EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext ,
27
27
} ;
28
+ use hir:: IsAsync ;
28
29
use rustc_ast:: attr;
29
30
use rustc_ast:: tokenstream:: { TokenStream , TokenTree } ;
30
31
use rustc_ast:: visit:: { FnCtxt , FnKind } ;
@@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
40
41
use rustc_hir as hir;
41
42
use rustc_hir:: def:: { DefKind , Res } ;
42
43
use rustc_hir:: def_id:: { DefId , LocalDefId , LocalDefIdSet , CRATE_DEF_ID } ;
43
- use rustc_hir:: { ForeignItemKind , GenericParamKind , HirId , Node , PatKind , PredicateOrigin } ;
44
+ use rustc_hir:: intravisit:: FnKind as HirFnKind ;
45
+ use rustc_hir:: {
46
+ Body , FnDecl , ForeignItemKind , GenericParamKind , HirId , Node , PatKind , PredicateOrigin ,
47
+ } ;
44
48
use rustc_index:: vec:: Idx ;
45
49
use rustc_middle:: lint:: in_external_macro;
46
50
use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf } ;
@@ -1337,6 +1341,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
1337
1341
}
1338
1342
}
1339
1343
1344
+ declare_lint ! {
1345
+ /// The `ungated_async_fn_track_caller` lint warns when the
1346
+ /// `#[track_caller]` attribute is used on an async function, method, or
1347
+ /// closure, without enabling the corresponding unstable feature flag.
1348
+ ///
1349
+ /// ### Example
1350
+ ///
1351
+ /// ```rust
1352
+ /// #[track_caller]
1353
+ /// async fn foo() {}
1354
+ /// ```
1355
+ ///
1356
+ /// {{produces}}
1357
+ ///
1358
+ /// ### Explanation
1359
+ ///
1360
+ /// The attribute must be used in conjunction with the
1361
+ /// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
1362
+ /// annotation will function as as no-op.
1363
+ ///
1364
+ /// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
1365
+ UNGATED_ASYNC_FN_TRACK_CALLER ,
1366
+ Warn ,
1367
+ "enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled"
1368
+ }
1369
+
1370
+ declare_lint_pass ! (
1371
+ /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
1372
+ /// do anything
1373
+ UngatedAsyncFnTrackCaller => [ UNGATED_ASYNC_FN_TRACK_CALLER ]
1374
+ ) ;
1375
+
1376
+ impl < ' tcx > LateLintPass < ' tcx > for UngatedAsyncFnTrackCaller {
1377
+ fn check_fn (
1378
+ & mut self ,
1379
+ cx : & LateContext < ' _ > ,
1380
+ fn_kind : HirFnKind < ' _ > ,
1381
+ _: & ' tcx FnDecl < ' _ > ,
1382
+ _: & ' tcx Body < ' _ > ,
1383
+ span : Span ,
1384
+ hir_id : HirId ,
1385
+ ) {
1386
+ if fn_kind. asyncness ( ) == IsAsync :: Async
1387
+ && !cx. tcx . features ( ) . closure_track_caller
1388
+ && let attrs = cx. tcx . hir ( ) . attrs ( hir_id)
1389
+ // Now, check if the function has the `#[track_caller]` attribute
1390
+ && let Some ( attr) = attrs. iter ( ) . find ( |attr| attr. has_name ( sym:: track_caller) )
1391
+ {
1392
+ cx. struct_span_lint (
1393
+ UNGATED_ASYNC_FN_TRACK_CALLER ,
1394
+ attr. span ,
1395
+ fluent:: lint_ungated_async_fn_track_caller,
1396
+ |lint| {
1397
+ lint. span_label ( span, fluent:: label) ;
1398
+ rustc_session:: parse:: add_feature_diagnostics (
1399
+ lint,
1400
+ & cx. tcx . sess . parse_sess ,
1401
+ sym:: closure_track_caller,
1402
+ ) ;
1403
+ lint
1404
+ } ,
1405
+ ) ;
1406
+ }
1407
+ }
1408
+ }
1409
+
1340
1410
declare_lint ! {
1341
1411
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
1342
1412
/// the crate root.
0 commit comments