@@ -25,6 +25,7 @@ use crate::{
2525 types:: { transparent_newtype_field, CItemKind } ,
2626 EarlyContext , EarlyLintPass , LateContext , LateLintPass , LintContext ,
2727} ;
28+ use hir:: IsAsync ;
2829use rustc_ast:: attr;
2930use rustc_ast:: tokenstream:: { TokenStream , TokenTree } ;
3031use rustc_ast:: visit:: { FnCtxt , FnKind } ;
@@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
4041use rustc_hir as hir;
4142use rustc_hir:: def:: { DefKind , Res } ;
4243use 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+ } ;
4448use rustc_index:: vec:: Idx ;
4549use rustc_middle:: lint:: in_external_macro;
4650use rustc_middle:: ty:: layout:: { LayoutError , LayoutOf } ;
@@ -1370,6 +1374,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
13701374 }
13711375}
13721376
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+
13731443declare_lint ! {
13741444 /// The `unreachable_pub` lint triggers for `pub` items not reachable from
13751445 /// the crate root.
0 commit comments