Skip to content

Commit

Permalink
Rollup merge of #104741 - bryangarza:bug-104588-async-track-caller, r…
Browse files Browse the repository at this point in the history
…=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
  • Loading branch information
matthiaskrgr authored Dec 22, 2022
2 parents 75f4ee8 + ccbba0a commit 0adf9e0
Show file tree
Hide file tree
Showing 8 changed files with 134 additions and 34 deletions.
18 changes: 7 additions & 11 deletions compiler/rustc_ast_lowering/src/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -656,18 +656,14 @@ impl<'hir> LoweringContext<'_, 'hir> {
hir::ExprKind::Closure(c)
};

let track_caller = self
.attrs
.get(&outer_hir_id.local_id)
.map_or(false, |attrs| attrs.into_iter().any(|attr| attr.has_name(sym::track_caller)));

let hir_id = self.lower_node_id(closure_node_id);
if track_caller {
let unstable_span = self.mark_span_with_reason(
DesugaringKind::Async,
span,
self.allow_gen_future.clone(),
);
let unstable_span =
self.mark_span_with_reason(DesugaringKind::Async, span, self.allow_gen_future.clone());

if self.tcx.features().closure_track_caller
&& let Some(attrs) = self.attrs.get(&outer_hir_id.local_id)
&& attrs.into_iter().any(|attr| attr.has_name(sym::track_caller))
{
self.lower_attrs(
hir_id,
&[Attribute {
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_error_messages/locales/en-US/lint.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,9 @@ lint_builtin_mutable_transmutes =
lint_builtin_unstable_features = unstable feature
lint_ungated_async_fn_track_caller = `#[track_caller]` on async functions is a no-op
.label = this function will not propagate the caller location
lint_builtin_unreachable_pub = unreachable `pub` {$what}
.suggestion = consider restricting its visibility
.help = or consider exporting it for use by other crates
Expand Down
72 changes: 71 additions & 1 deletion compiler/rustc_lint/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use crate::{
types::{transparent_newtype_field, CItemKind},
EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext,
};
use hir::IsAsync;
use rustc_ast::attr;
use rustc_ast::tokenstream::{TokenStream, TokenTree};
use rustc_ast::visit::{FnCtxt, FnKind};
Expand All @@ -40,7 +41,10 @@ use rustc_feature::{deprecated_attributes, AttributeGate, BuiltinAttribute, Gate
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdSet, CRATE_DEF_ID};
use rustc_hir::{ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin};
use rustc_hir::intravisit::FnKind as HirFnKind;
use rustc_hir::{
Body, FnDecl, ForeignItemKind, GenericParamKind, HirId, Node, PatKind, PredicateOrigin,
};
use rustc_index::vec::Idx;
use rustc_middle::lint::in_external_macro;
use rustc_middle::ty::layout::{LayoutError, LayoutOf};
Expand Down Expand Up @@ -1370,6 +1374,72 @@ impl<'tcx> LateLintPass<'tcx> for UnstableFeatures {
}
}

declare_lint! {
/// The `ungated_async_fn_track_caller` lint warns when the
/// `#[track_caller]` attribute is used on an async function, method, or
/// closure, without enabling the corresponding unstable feature flag.
///
/// ### Example
///
/// ```rust
/// #[track_caller]
/// async fn foo() {}
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The attribute must be used in conjunction with the
/// [`closure_track_caller` feature flag]. Otherwise, the `#[track_caller]`
/// annotation will function as as no-op.
///
/// [`closure_track_caller` feature flag]: https://doc.rust-lang.org/beta/unstable-book/language-features/closure-track-caller.html
UNGATED_ASYNC_FN_TRACK_CALLER,
Warn,
"enabling track_caller on an async fn is a no-op unless the closure_track_caller feature is enabled"
}

declare_lint_pass!(
/// Explains corresponding feature flag must be enabled for the `#[track_caller] attribute to
/// do anything
UngatedAsyncFnTrackCaller => [UNGATED_ASYNC_FN_TRACK_CALLER]
);

impl<'tcx> LateLintPass<'tcx> for UngatedAsyncFnTrackCaller {
fn check_fn(
&mut self,
cx: &LateContext<'_>,
fn_kind: HirFnKind<'_>,
_: &'tcx FnDecl<'_>,
_: &'tcx Body<'_>,
span: Span,
hir_id: HirId,
) {
if fn_kind.asyncness() == IsAsync::Async
&& !cx.tcx.features().closure_track_caller
&& let attrs = cx.tcx.hir().attrs(hir_id)
// Now, check if the function has the `#[track_caller]` attribute
&& let Some(attr) = attrs.iter().find(|attr| attr.has_name(sym::track_caller))
{
cx.struct_span_lint(
UNGATED_ASYNC_FN_TRACK_CALLER,
attr.span,
fluent::lint_ungated_async_fn_track_caller,
|lint| {
lint.span_label(span, fluent::label);
rustc_session::parse::add_feature_diagnostics(
lint,
&cx.tcx.sess.parse_sess,
sym::closure_track_caller,
);
lint
},
);
}
}
}

declare_lint! {
/// The `unreachable_pub` lint triggers for `pub` items not reachable from
/// the crate root.
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_lint/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ late_lint_methods!(
// May Depend on constants elsewhere
UnusedBrokenConst: UnusedBrokenConst,
UnstableFeatures: UnstableFeatures,
UngatedAsyncFnTrackCaller: UngatedAsyncFnTrackCaller,
ArrayIntoIter: ArrayIntoIter::default(),
DropTraitConstraints: DropTraitConstraints,
TemporaryCStringAsPtr: TemporaryCStringAsPtr,
Expand Down
1 change: 0 additions & 1 deletion src/test/ui/async-await/track-caller/async-closure-gate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,5 @@
fn main() {
let _ = #[track_caller] async || {
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
//~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
};
}
15 changes: 1 addition & 14 deletions src/test/ui/async-await/track-caller/async-closure-gate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,6 @@ LL | let _ = #[track_caller] async || {
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable

error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/async-closure-gate.rs:6:38
|
LL | let _ = #[track_caller] async || {
| ______________________________________^
LL | |
LL | |
LL | | };
| |_____^
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable

error: aborting due to 2 previous errors
error: aborting due to previous error

For more information about this error, try `rustc --explain E0658`.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
warning: `#[track_caller]` on async functions is a no-op
--> $DIR/panic-track-caller.rs:50:1
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
LL | / async fn bar_track_caller() {
LL | | panic!()
LL | | }
| |_- this function will not propagate the caller location
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable
= note: `#[warn(ungated_async_fn_track_caller)]` on by default

warning: `#[track_caller]` on async functions is a no-op
--> $DIR/panic-track-caller.rs:62:5
|
LL | #[track_caller]
| ^^^^^^^^^^^^^^^
LL | / async fn bar_assoc() {
LL | | panic!();
LL | | }
| |_____- this function will not propagate the caller location
|
= note: see issue #87417 <https://github.com/rust-lang/rust/issues/87417> for more information
= help: add `#![feature(closure_track_caller)]` to the crate attributes to enable

warning: 2 warnings emitted

29 changes: 22 additions & 7 deletions src/test/ui/async-await/track-caller/panic-track-caller.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
// run-pass
// edition:2021
// revisions: feat nofeat
// needs-unwind
#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
#![feature(async_closure, stmt_expr_attributes)]
#![cfg_attr(feat, feature(closure_track_caller))]

use std::future::Future;
use std::panic;
Expand Down Expand Up @@ -45,7 +47,7 @@ async fn foo() {
bar().await
}

#[track_caller]
#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
async fn bar_track_caller() {
panic!()
}
Expand All @@ -57,7 +59,7 @@ async fn foo_track_caller() {
struct Foo;

impl Foo {
#[track_caller]
#[track_caller] //[nofeat]~ WARN `#[track_caller]` on async functions is a no-op
async fn bar_assoc() {
panic!();
}
Expand All @@ -67,6 +69,9 @@ async fn foo_assoc() {
Foo::bar_assoc().await
}

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

fn main() {
assert_eq!(panicked_at(|| block_on(foo())), 41);
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 54);
assert_eq!(panicked_at(|| block_on(foo_assoc())), 67);
assert_eq!(panicked_at(|| block_on(foo_closure())), 74);
assert_eq!(panicked_at(|| block_on(foo())), 43);

#[cfg(feat)]
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 56);
#[cfg(nofeat)]
assert_eq!(panicked_at(|| block_on(foo_track_caller())), 52);

#[cfg(feat)]
assert_eq!(panicked_at(|| block_on(foo_assoc())), 69);
#[cfg(nofeat)]
assert_eq!(panicked_at(|| block_on(foo_assoc())), 64);

#[cfg(feat)]
assert_eq!(panicked_at(|| block_on(foo_closure())), 79);
}

0 comments on commit 0adf9e0

Please sign in to comment.