Skip to content

Commit 0adf9e0

Browse files
authored
Rollup merge of #104741 - bryangarza:bug-104588-async-track-caller, r=compiler-errors
Switch `#[track_caller]` back to a no-op unless feature gate is enabled This patch fixes a regression, in which `#[track_caller]`, which was previously a no-op, was changed to actually turn on the behavior. This should instead only happen behind the `closure_track_caller` feature gate. Also, add a warning for the user to understand how their code will compile depending on the feature gate being turned on or not. Fixes #104588
2 parents 75f4ee8 + ccbba0a commit 0adf9e0

File tree

8 files changed

+134
-34
lines changed

8 files changed

+134
-34
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+7-11
Original file line numberDiff line numberDiff line change
@@ -656,18 +656,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
656656
hir::ExprKind::Closure(c)
657657
};
658658

659-
let track_caller = self
660-
.attrs
661-
.get(&outer_hir_id.local_id)
662-
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));
663-
664659
let hir_id = self.lower_node_id(closure_node_id);
665-
if track_caller {
666-
let unstable_span = self.mark_span_with_reason(
667-
DesugaringKind::Async,
668-
span,
669-
self.allow_gen_future.clone(),
670-
);
660+
let unstable_span =
661+
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());
662+
663+
if self.tcx.features().closure_track_caller
664+
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
665+
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
666+
{
671667
self.lower_attrs(
672668
hir_id,
673669
&[Attribute {

compiler/rustc_error_messages/locales/en-US/lint.ftl

+3
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,9 @@ lint_builtin_mutable_transmutes =
350350
351351
lint_builtin_unstable_features = unstable feature
352352
353+
lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
354+
.label = this function will not propagate the caller location
355+
353356
lint_builtin_unreachable_pub = unreachable `pub` {$what}
354357
.suggestion = consider restricting its visibility
355358
.help = or consider exporting it for use by other crates

compiler/rustc_lint/src/builtin.rs

+71-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::{
2525
types::{transparent_newtype_field, CItemKind},
2626
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
2727
};
28+
use hir::IsAsync;
2829
use rustc_ast::attr;
2930
use rustc_ast::tokenstream::{TokenStream, TokenTree};
3031
use rustc_ast::visit::{FnCtxt, FnKind};
@@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
4041
use rustc_hir as hir;
4142
use rustc_hir::def::{DefKind, Res};
4243
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+
};
4448
use rustc_index::vec::Idx;
4549
use rustc_middle::lint::in_external_macro;
4650
use 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+
13731443
declare_lint! {
13741444
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
13751445
/// the crate root.

compiler/rustc_lint/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ late_lint_methods!(
219219
// May Depend on constants elsewhere
220220
UnusedBrokenConst: UnusedBrokenConst,
221221
UnstableFeatures: UnstableFeatures,
222+
UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller,
222223
ArrayIntoIter: ArrayIntoIter::default(),
223224
DropTraitConstraints: DropTraitConstraints,
224225
TemporaryCStringAsPtr: TemporaryCStringAsPtr,

src/test/ui/async-await/track-caller/async-closure-gate.rs

-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,5 @@
55
fn main() {
66
let _ = #[track_caller] async || {
77
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
8-
//~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
98
};
109
}

src/test/ui/async-await/track-caller/async-closure-gate.stderr

+1-14
Original file line numberDiff line numberDiff line change
@@ -7,19 +7,6 @@ LL | let _ = #[track_caller] async || {
77
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
88
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
99

10-
error[E0658]: `#[track_caller]` on closures is currently unstable
11-
--> $DIR/async-closure-gate.rs:6:38
12-
|
13-
LL | let _ = #[track_caller] async || {
14-
| ______________________________________^
15-
LL | |
16-
LL | |
17-
LL | | };
18-
| |_____^
19-
|
20-
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
21-
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
22-
23-
error: aborting due to 2 previous errors
10+
error: aborting due to previous error
2411

2512
For more information about this error, try `rustc --explain E0658`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
warning: `#[track_caller]` on async functions is a no-op
2+
--> $DIR/panic-track-caller.rs:50:1
3+
|
4+
LL | #[track_caller]
5+
| ^^^^^^^^^^^^^^^
6+
LL | / async fn bar_track_caller() {
7+
LL | | panic!()
8+
LL | | }
9+
| |_- this function will not propagate the caller location
10+
|
11+
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
12+
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
13+
= note: `#[warn(ungated_async_fn_track_caller)]` on by default
14+
15+
warning: `#[track_caller]` on async functions is a no-op
16+
--> $DIR/panic-track-caller.rs:62:5
17+
|
18+
LL | #[track_caller]
19+
| ^^^^^^^^^^^^^^^
20+
LL | / async fn bar_assoc() {
21+
LL | | panic!();
22+
LL | | }
23+
| |_____- this function will not propagate the caller location
24+
|
25+
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
26+
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
27+
28+
warning: 2 warnings emitted
29+

src/test/ui/async-await/track-caller/panic-track-caller.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
// run-pass
22
// edition:2021
3+
// revisions: feat nofeat
34
// needs-unwind
4-
#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
5+
#![feature(async_closure, stmt_expr_attributes)]
6+
#![cfg_attr(feat, feature(closure_track_caller))]
57

68
use std::future::Future;
79
use std::panic;
@@ -45,7 +47,7 @@ async fn foo() {
4547
bar().await
4648
}
4749

48-
#[track_caller]
50+
#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
4951
async fn bar_track_caller() {
5052
panic!()
5153
}
@@ -57,7 +59,7 @@ async fn foo_track_caller() {
5759
struct Foo;
5860

5961
impl Foo {
60-
#[track_caller]
62+
#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
6163
async fn bar_assoc() {
6264
panic!();
6365
}
@@ -67,6 +69,9 @@ async fn foo_assoc() {
6769
Foo::bar_assoc().await
6870
}
6971

72+
// Since compilation is expected to fail for this fn when using
73+
// `nofeat`, we test that separately in `async-closure-gate.rs`
74+
#[cfg(feat)]
7075
async fn foo_closure() {
7176
let c = #[track_caller] async || {
7277
panic!();
@@ -91,8 +96,18 @@ fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
9196
}
9297

9398
fn main() {
94-
assert_eq!(panicked_at(|| block_on(foo())), 41);
95-
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
96-
assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
97-
assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
99+
assert_eq!(panicked_at(|| block_on(foo())), 43);
100+
101+
#[cfg(feat)]
102+
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56);
103+
#[cfg(nofeat)]
104+
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52);
105+
106+
#[cfg(feat)]
107+
assert_eq!(panicked_at(|| block_on(foo_assoc())), 69);
108+
#[cfg(nofeat)]
109+
assert_eq!(panicked_at(|| block_on(foo_assoc())), 64);
110+
111+
#[cfg(feat)]
112+
assert_eq!(panicked_at(|| block_on(foo_closure())), 79);
98113
}

0 commit comments

Comments
 (0)