@@ -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 } ;
@@ -1370,6 +1374,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
1370
1374
}
1371
1375
}
1372
1376
1377
+ declare_lint ! {
1378
+ /// The `ungated_async_fn_track_caller` lint warns when the
1379
+ /// `#[track_caller]` attribute is used on an async function, method, or
1380
+ /// closure, without enabling the corresponding unstable feature flag.
1381
+ ///
1382
+ /// ### Example
1383
+ ///
1384
+ /// ```rust
1385
+ /// #[track_caller]
1386
+ /// async fn foo() {}
1387
+ /// ```
1388
+ ///
1389
+ /// {{produces}}
1390
+ ///
1391
+ /// ### Explanation
1392
+ ///
1393
+ /// The attribute must be used in conjunction with the
1394
+ /// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
1395
+ /// annotation will function as as no-op.
1396
+ ///
1397
+ /// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
1398
+ UNGATED_ASYNC_FN_TRACK_CALLER ,
1399
+ Warn ,
1400
+ "enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled"
1401
+ }
1402
+
1403
+ declare_lint_pass ! (
1404
+ /// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
1405
+ /// do anything
1406
+ UngatedAsyncFnTrackCaller => [ UNGATED_ASYNC_FN_TRACK_CALLER ]
1407
+ ) ;
1408
+
1409
+ impl < ' tcx > LateLintPass < ' tcx > for UngatedAsyncFnTrackCaller {
1410
+ fn check_fn (
1411
+ & mut self ,
1412
+ cx : & LateContext < ' _ > ,
1413
+ fn_kind : HirFnKind < ' _ > ,
1414
+ _: & ' tcx FnDecl < ' _ > ,
1415
+ _: & ' tcx Body < ' _ > ,
1416
+ span : Span ,
1417
+ hir_id : HirId ,
1418
+ ) {
1419
+ if fn_kind. asyncness ( ) == IsAsync :: Async
1420
+ && !cx. tcx . features ( ) . closure_track_caller
1421
+ && let attrs = cx. tcx . hir ( ) . attrs ( hir_id)
1422
+ // Now, check if the function has the `#[track_caller]` attribute
1423
+ && let Some ( attr) = attrs. iter ( ) . find ( |attr| attr. has_name ( sym:: track_caller) )
1424
+ {
1425
+ cx. struct_span_lint (
1426
+ UNGATED_ASYNC_FN_TRACK_CALLER ,
1427
+ attr. span ,
1428
+ fluent:: lint_ungated_async_fn_track_caller,
1429
+ |lint| {
1430
+ lint. span_label ( span, fluent:: label) ;
1431
+ rustc_session:: parse:: add_feature_diagnostics (
1432
+ lint,
1433
+ & cx. tcx . sess . parse_sess ,
1434
+ sym:: closure_track_caller,
1435
+ ) ;
1436
+ lint
1437
+ } ,
1438
+ ) ;
1439
+ }
1440
+ }
1441
+ }
1442
+
1373
1443
declare_lint ! {
1374
1444
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
1375
1445
/// the crate root.
0 commit comments