Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch #[track_caller] back to a no-op unless feature gate is enabled #104741

Merged
merged 7 commits into from
Dec 22, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}