Rollup merge of #105464 - nbdd0121:hir, r=compiler-errors
Support #[track_caller] on async closures Follow up on #105180 r? ```@compiler-errors``` cc ```@cjgillot```
This commit is contained in:
commit
5e38e702aa
|
@ -31,6 +31,44 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
pub(super) fn lower_expr_mut(&mut self, e: &Expr) -> hir::Expr<'hir> {
|
||||
ensure_sufficient_stack(|| {
|
||||
match &e.kind {
|
||||
// Paranthesis expression does not have a HirId and is handled specially.
|
||||
ExprKind::Paren(ex) => {
|
||||
let mut ex = self.lower_expr_mut(ex);
|
||||
// Include parens in span, but only if it is a super-span.
|
||||
if e.span.contains(ex.span) {
|
||||
ex.span = self.lower_span(e.span);
|
||||
}
|
||||
// Merge attributes into the inner expression.
|
||||
if !e.attrs.is_empty() {
|
||||
let old_attrs =
|
||||
self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
|
||||
self.attrs.insert(
|
||||
ex.hir_id.local_id,
|
||||
&*self.arena.alloc_from_iter(
|
||||
e.attrs
|
||||
.iter()
|
||||
.map(|a| self.lower_attr(a))
|
||||
.chain(old_attrs.iter().cloned()),
|
||||
),
|
||||
);
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
// Desugar `ExprForLoop`
|
||||
// from: `[opt_ident]: for <pat> in <head> <body>`
|
||||
//
|
||||
// This also needs special handling because the HirId of the returned `hir::Expr` will not
|
||||
// correspond to the `e.id`, so `lower_expr_for` handles attribute lowering itself.
|
||||
ExprKind::ForLoop(pat, head, body, opt_label) => {
|
||||
return self.lower_expr_for(e, pat, head, body, *opt_label);
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
|
||||
let hir_id = self.lower_node_id(e.id);
|
||||
self.lower_attrs(hir_id, &e.attrs);
|
||||
|
||||
let kind = match &e.kind {
|
||||
ExprKind::Box(inner) => hir::ExprKind::Box(self.lower_expr(inner)),
|
||||
ExprKind::Array(exprs) => hir::ExprKind::Array(self.lower_exprs(exprs)),
|
||||
|
@ -48,7 +86,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
if e.attrs.get(0).map_or(false, |a| a.has_name(sym::rustc_box)) {
|
||||
if let [inner] = &args[..] && e.attrs.len() == 1 {
|
||||
let kind = hir::ExprKind::Box(self.lower_expr(&inner));
|
||||
let hir_id = self.lower_node_id(e.id);
|
||||
return hir::Expr { hir_id, kind, span: self.lower_span(e.span) };
|
||||
} else {
|
||||
self.tcx.sess.emit_err(RustcBoxAttributeError { span: e.span });
|
||||
|
@ -147,7 +184,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
),
|
||||
ExprKind::Async(capture_clause, closure_node_id, block) => self.make_async_expr(
|
||||
*capture_clause,
|
||||
None,
|
||||
hir_id,
|
||||
*closure_node_id,
|
||||
None,
|
||||
e.span,
|
||||
|
@ -184,6 +221,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
binder,
|
||||
*capture_clause,
|
||||
e.id,
|
||||
hir_id,
|
||||
*closure_id,
|
||||
fn_decl,
|
||||
body,
|
||||
|
@ -279,39 +317,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
ExprKind::Yield(opt_expr) => self.lower_expr_yield(e.span, opt_expr.as_deref()),
|
||||
ExprKind::Err => hir::ExprKind::Err,
|
||||
ExprKind::Try(sub_expr) => self.lower_expr_try(e.span, sub_expr),
|
||||
ExprKind::Paren(ex) => {
|
||||
let mut ex = self.lower_expr_mut(ex);
|
||||
// Include parens in span, but only if it is a super-span.
|
||||
if e.span.contains(ex.span) {
|
||||
ex.span = self.lower_span(e.span);
|
||||
}
|
||||
// Merge attributes into the inner expression.
|
||||
if !e.attrs.is_empty() {
|
||||
let old_attrs =
|
||||
self.attrs.get(&ex.hir_id.local_id).map(|la| *la).unwrap_or(&[]);
|
||||
self.attrs.insert(
|
||||
ex.hir_id.local_id,
|
||||
&*self.arena.alloc_from_iter(
|
||||
e.attrs
|
||||
.iter()
|
||||
.map(|a| self.lower_attr(a))
|
||||
.chain(old_attrs.iter().cloned()),
|
||||
),
|
||||
);
|
||||
}
|
||||
return ex;
|
||||
}
|
||||
|
||||
// Desugar `ExprForLoop`
|
||||
// from: `[opt_ident]: for <pat> in <head> <body>`
|
||||
ExprKind::ForLoop(pat, head, body, opt_label) => {
|
||||
return self.lower_expr_for(e, pat, head, body, *opt_label);
|
||||
}
|
||||
ExprKind::Paren(_) | ExprKind::ForLoop(..) => unreachable!("already handled"),
|
||||
|
||||
ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span),
|
||||
};
|
||||
|
||||
let hir_id = self.lower_node_id(e.id);
|
||||
self.lower_attrs(hir_id, &e.attrs);
|
||||
hir::Expr { hir_id, kind, span: self.lower_span(e.span) }
|
||||
})
|
||||
}
|
||||
|
@ -576,7 +587,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
pub(super) fn make_async_expr(
|
||||
&mut self,
|
||||
capture_clause: CaptureBy,
|
||||
outer_hir_id: Option<hir::HirId>,
|
||||
outer_hir_id: hir::HirId,
|
||||
closure_node_id: NodeId,
|
||||
ret_ty: Option<hir::FnRetTy<'hir>>,
|
||||
span: Span,
|
||||
|
@ -669,8 +680,9 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
hir::ExprKind::Closure(c)
|
||||
};
|
||||
|
||||
let track_caller = outer_hir_id
|
||||
.and_then(|id| self.attrs.get(&id.local_id))
|
||||
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);
|
||||
|
@ -985,6 +997,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
binder: &ClosureBinder,
|
||||
capture_clause: CaptureBy,
|
||||
closure_id: NodeId,
|
||||
closure_hir_id: hir::HirId,
|
||||
inner_closure_id: NodeId,
|
||||
decl: &FnDecl,
|
||||
body: &Expr,
|
||||
|
@ -1018,9 +1031,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let async_body = this.make_async_expr(
|
||||
capture_clause,
|
||||
// FIXME(nbdd0121): This should also use a proper HIR id so `#[track_caller]`
|
||||
// can be applied on async closures as well.
|
||||
None,
|
||||
closure_hir_id,
|
||||
inner_closure_id,
|
||||
async_ret_ty,
|
||||
body.span,
|
||||
|
|
|
@ -1139,7 +1139,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
|||
|
||||
let async_expr = this.make_async_expr(
|
||||
CaptureBy::Value,
|
||||
Some(fn_id),
|
||||
fn_id,
|
||||
closure_id,
|
||||
None,
|
||||
body.span,
|
||||
|
|
|
@ -187,9 +187,9 @@ pub fn change_continue_label() {
|
|||
}
|
||||
|
||||
#[cfg(not(any(cfail1,cfail4)))]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes, typeck")]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
|
||||
#[rustc_clean(cfg="cfail3")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, typeck, optimized_mir")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes, optimized_mir")]
|
||||
#[rustc_clean(cfg="cfail6")]
|
||||
pub fn change_continue_label() {
|
||||
let mut _x = 0;
|
||||
|
|
|
@ -158,9 +158,9 @@ pub fn change_break_label() {
|
|||
}
|
||||
|
||||
#[cfg(not(any(cfail1,cfail4)))]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
|
||||
#[rustc_clean(cfg="cfail3")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
|
||||
#[rustc_clean(cfg="cfail6")]
|
||||
pub fn change_break_label() {
|
||||
let mut _x = 0;
|
||||
|
@ -210,9 +210,9 @@ pub fn change_continue_label() {
|
|||
}
|
||||
|
||||
#[cfg(not(any(cfail1,cfail4)))]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
|
||||
#[rustc_clean(cfg="cfail3")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes")]
|
||||
#[rustc_clean(cfg="cfail6")]
|
||||
pub fn change_continue_label() {
|
||||
let mut _x = 0;
|
||||
|
|
|
@ -158,9 +158,9 @@ pub fn change_break_label() {
|
|||
}
|
||||
|
||||
#[cfg(not(any(cfail1,cfail4)))]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir,typeck")]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,optimized_mir")]
|
||||
#[rustc_clean(cfg="cfail3")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir,typeck")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
|
||||
#[rustc_clean(cfg="cfail6")]
|
||||
pub fn change_break_label() {
|
||||
let mut _x = 0;
|
||||
|
@ -212,9 +212,9 @@ pub fn change_continue_label() {
|
|||
}
|
||||
|
||||
#[cfg(not(any(cfail1,cfail4)))]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes,typeck")]
|
||||
#[rustc_clean(cfg="cfail2", except="hir_owner_nodes")]
|
||||
#[rustc_clean(cfg="cfail3")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,typeck,optimized_mir")]
|
||||
#[rustc_clean(cfg="cfail5", except="hir_owner_nodes,optimized_mir")]
|
||||
#[rustc_clean(cfg="cfail6")]
|
||||
pub fn change_continue_label() {
|
||||
let mut _x = 0;
|
||||
|
|
9
src/test/ui/async-await/track-caller/async-block.rs
Normal file
9
src/test/ui/async-await/track-caller/async-block.rs
Normal file
|
@ -0,0 +1,9 @@
|
|||
// edition:2021
|
||||
|
||||
#![feature(closure_track_caller, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let _ = #[track_caller] async {
|
||||
//~^ ERROR attribute should be applied to a function definition [E0739]
|
||||
};
|
||||
}
|
12
src/test/ui/async-await/track-caller/async-block.stderr
Normal file
12
src/test/ui/async-await/track-caller/async-block.stderr
Normal file
|
@ -0,0 +1,12 @@
|
|||
error[E0739]: attribute should be applied to a function definition
|
||||
--> $DIR/async-block.rs:6:13
|
||||
|
|
||||
LL | let _ = #[track_caller] async {
|
||||
| _____________^^^^^^^^^^^^^^^_-
|
||||
LL | |
|
||||
LL | | };
|
||||
| |_____- not a function definition
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0739`.
|
10
src/test/ui/async-await/track-caller/async-closure-gate.rs
Normal file
10
src/test/ui/async-await/track-caller/async-closure-gate.rs
Normal file
|
@ -0,0 +1,10 @@
|
|||
// edition:2021
|
||||
|
||||
#![feature(async_closure, stmt_expr_attributes)]
|
||||
|
||||
fn main() {
|
||||
let _ = #[track_caller] async || {
|
||||
//~^ ERROR `#[track_caller]` on closures is currently unstable [E0658]
|
||||
//~| ERROR `#[track_caller]` on closures is currently unstable [E0658]
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
error[E0658]: `#[track_caller]` on closures is currently unstable
|
||||
--> $DIR/async-closure-gate.rs:6:13
|
||||
|
|
||||
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
|
||||
|
||||
For more information about this error, try `rustc --explain E0658`.
|
|
@ -1,7 +1,7 @@
|
|||
// run-pass
|
||||
// edition:2021
|
||||
// needs-unwind
|
||||
#![feature(closure_track_caller)]
|
||||
#![feature(closure_track_caller, async_closure, stmt_expr_attributes)]
|
||||
|
||||
use std::future::Future;
|
||||
use std::panic;
|
||||
|
@ -67,6 +67,13 @@ async fn foo_assoc() {
|
|||
Foo::bar_assoc().await
|
||||
}
|
||||
|
||||
async fn foo_closure() {
|
||||
let c = #[track_caller] async || {
|
||||
panic!();
|
||||
};
|
||||
c().await
|
||||
}
|
||||
|
||||
fn panicked_at(f: impl FnOnce() + panic::UnwindSafe) -> u32 {
|
||||
let loc = Arc::new(Mutex::new(None));
|
||||
|
||||
|
@ -87,4 +94,5 @@ 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);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue