Skip to content
Open
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
22 changes: 19 additions & 3 deletions compiler/rustc_expand/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -401,9 +401,25 @@ impl<'a> StripUnconfigured<'a> {
eval_config_entry(self.sess, &cfg)
}

/// If attributes are not allowed on expressions, emit an error for `attr`
/// Whether `expr` is a closure or method call, possibly parenthesized, on which outer
/// attributes are stable.
fn is_outer_attr_stable_on_closure_or_method_call_expr(expr: &ast::Expr) -> bool {
match &expr.kind {
ast::ExprKind::Closure(..) | ast::ExprKind::MethodCall(..) => true,
ast::ExprKind::Paren(inner) => {
Self::is_outer_attr_stable_on_closure_or_method_call_expr(inner)
}
_ => false,
}
}

/// If attributes are not allowed on `expr`, emit an error for `attr`.
#[instrument(level = "trace", skip(self))]
pub(crate) fn maybe_emit_expr_attr_err(&self, attr: &Attribute) {
pub(crate) fn maybe_emit_expr_attr_err(&self, expr: &ast::Expr, attr: &Attribute) {
if Self::is_outer_attr_stable_on_closure_or_method_call_expr(expr) {
return;
}

if self.features.is_some_and(|features| !features.stmt_expr_attributes())
&& !attr.span.allows_unstable(sym::stmt_expr_attributes)
{
Expand All @@ -430,7 +446,7 @@ impl<'a> StripUnconfigured<'a> {
pub fn configure_expr(&self, expr: &mut ast::Expr, method_receiver: bool) {
if !method_receiver {
for attr in expr.attrs.iter() {
self.maybe_emit_expr_attr_err(attr);
self.maybe_emit_expr_attr_err(expr, attr);
}
}

Expand Down
19 changes: 14 additions & 5 deletions compiler/rustc_expand/src/expand.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1252,7 +1252,12 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
fn flatten_outputs(_outputs: impl Iterator<Item = Self::OutputTy>) -> Self::OutputTy {
unreachable!()
}
fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
fn pre_flat_map_node_collect_attr(
_cfg: &StripUnconfigured<'_>,
_node: &Self,
_attr: &ast::Attribute,
) {
}
fn post_flat_map_node_collect_bang(_output: &mut Self::OutputTy, _add_semicolon: AddSemicolon) {
}
fn wrap_flat_map_node_walk_flat_map(
Expand Down Expand Up @@ -1962,8 +1967,12 @@ impl InvocationCollectorNode for AstNodeWrapper<Box<ast::Expr>, OptExprTag> {
_ => unreachable!(),
}
}
fn pre_flat_map_node_collect_attr(cfg: &StripUnconfigured<'_>, attr: &ast::Attribute) {
cfg.maybe_emit_expr_attr_err(attr);
fn pre_flat_map_node_collect_attr(
cfg: &StripUnconfigured<'_>,
node: &Self,
attr: &ast::Attribute,
) {
cfg.maybe_emit_expr_attr_err(&node.wrapped, attr);
}
fn as_target(&self) -> Target {
Target::Expression
Expand Down Expand Up @@ -2333,7 +2342,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
continue;
}
_ => {
Node::pre_flat_map_node_collect_attr(&self.cfg(), &attr);
Node::pre_flat_map_node_collect_attr(&self.cfg(), &node, &attr);
self.collect_attr((attr, pos, derives), node.to_annotatable(), Node::KIND)
.make_ast::<Node>()
}
Expand Down Expand Up @@ -2554,7 +2563,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
fn visit_expr(&mut self, node: &mut ast::Expr) {
// FIXME: Feature gating is performed inconsistently between `Expr` and `OptExpr`.
if let Some(attr) = node.attrs.first() {
self.cfg().maybe_emit_expr_attr_err(attr);
self.cfg().maybe_emit_expr_attr_err(node, attr);
}
ensure_sufficient_stack(|| self.visit_node(node))
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
//@ check-pass

#![feature(cfg_eval)]

struct Value;

impl Value {
fn method(self) -> usize {
0
}
}

fn main() {
let _ = #[cfg_eval] #[inline] || {};
let _ = #[cfg_eval] #[allow(unused)] Value.method();
}
19 changes: 19 additions & 0 deletions tests/ui/attributes/attributes-on-method-calls.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
//@ check-pass

struct Value;

impl Value {
fn first(self) -> Self {
self
}

fn second(self) -> usize {
0
}
}

fn main() {
let _ = #[allow(unused)] Value.first();
let _ = #[allow(unused)] Value.first().second();
let _ = #[allow(unused)] (Value.first().second());
}
2 changes: 1 addition & 1 deletion tests/ui/attributes/inline-attribute-on-closure.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
//! Regression test for https://github.com/rust-lang/rust/issues/49632
//@ run-pass
#![feature(stmt_expr_attributes)]

pub fn main() {
let _x = #[inline(always)] || {};
let _y = #[inline(never)] || {};
let _z = #[inline] || {};
let _cold = #[cold] || {};
}
1 change: 0 additions & 1 deletion tests/ui/attributes/instrument_fn.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,5 +47,4 @@ fn instrument_closure() {
let _x = #[instrument_fn = "on"]
|| {};
//~^^ ERROR attribute cannot be used on
//~^^^ ERROR attributes on expressions are experimental
}
12 changes: 1 addition & 11 deletions tests/ui/attributes/instrument_fn.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,6 @@ LL | #[instrument_fn = "off"]
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error[E0658]: attributes on expressions are experimental
--> $DIR/instrument_fn.rs:47:14
|
LL | let _x = #[instrument_fn = "on"]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: `#[instrument_fn]` attribute cannot be used on crates
--> $DIR/instrument_fn.rs:2:1
|
Expand Down Expand Up @@ -121,7 +111,7 @@ LL | let _x = #[instrument_fn = "on"]
|
= help: `#[instrument_fn]` can be applied to functions and methods

error: aborting due to 13 previous errors
error: aborting due to 12 previous errors

Some errors have detailed explanations: E0539, E0658, E0805.
For more information about an error, try `rustc --explain E0539`.
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@ fn main() {
let mut m = [1, 2, 3, 4, 5];

let mut c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR: First Pass analysis includes:
//~| ERROR: Min Capture analysis includes:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/arrays-completely-captured.rs:8:17
|
LL | let mut c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: First Pass analysis includes:
--> $DIR/arrays-completely-captured.rs:12:5
--> $DIR/arrays-completely-captured.rs:9:5
|
LL | / || {
LL | |
Expand All @@ -20,18 +10,18 @@ LL | | };
| |_____^
|
note: Capturing m[] -> Mutable
--> $DIR/arrays-completely-captured.rs:15:9
--> $DIR/arrays-completely-captured.rs:12:9
|
LL | m[0] += 10;
| ^
note: Capturing m[] -> Mutable
--> $DIR/arrays-completely-captured.rs:18:9
--> $DIR/arrays-completely-captured.rs:15:9
|
LL | m[1] += 40;
| ^

error: Min Capture analysis includes:
--> $DIR/arrays-completely-captured.rs:12:5
--> $DIR/arrays-completely-captured.rs:9:5
|
LL | / || {
LL | |
Expand All @@ -42,11 +32,10 @@ LL | | };
| |_____^
|
note: Min Capture m[] -> Mutable
--> $DIR/arrays-completely-captured.rs:15:9
--> $DIR/arrays-completely-captured.rs:12:9
|
LL | m[0] += 10;
| ^

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

For more information about this error, try `rustc --explain E0658`.
3 changes: 0 additions & 3 deletions tests/ui/closures/2229_closure_analysis/by_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ fn big_box() {
let t = (b, 10);

let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:
Expand Down
25 changes: 7 additions & 18 deletions tests/ui/closures/2229_closure_analysis/by_value.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/by_value.rs:18:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: First Pass analysis includes:
--> $DIR/by_value.rs:22:5
--> $DIR/by_value.rs:19:5
|
LL | / || {
LL | |
Expand All @@ -20,18 +10,18 @@ LL | | };
| |_____^
|
note: Capturing t[(0, 0),Deref,(0, 0)] -> ByValue
--> $DIR/by_value.rs:25:17
--> $DIR/by_value.rs:22:17
|
LL | let p = t.0.0;
| ^^^^^
note: Capturing t[(1, 0)] -> Immutable
--> $DIR/by_value.rs:28:29
--> $DIR/by_value.rs:25:29
|
LL | println!("{} {:?}", t.1, p);
| ^^^

error: Min Capture analysis includes:
--> $DIR/by_value.rs:22:5
--> $DIR/by_value.rs:19:5
|
LL | / || {
LL | |
Expand All @@ -42,16 +32,15 @@ LL | | };
| |_____^
|
note: Min Capture t[(0, 0)] -> ByValue
--> $DIR/by_value.rs:25:17
--> $DIR/by_value.rs:22:17
|
LL | let p = t.0.0;
| ^^^^^
note: Min Capture t[(1, 0)] -> Immutable
--> $DIR/by_value.rs:28:29
--> $DIR/by_value.rs:25:29
|
LL | println!("{} {:?}", t.1, p);
| ^^^

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

For more information about this error, try `rustc --explain E0658`.
3 changes: 0 additions & 3 deletions tests/ui/closures/2229_closure_analysis/capture-analysis-1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@ fn main() {
let q = Point { x: 10, y: 10 };

let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:
Expand Down
29 changes: 9 additions & 20 deletions tests/ui/closures/2229_closure_analysis/capture-analysis-1.stderr
Original file line number Diff line number Diff line change
@@ -1,15 +1,5 @@
error[E0658]: attributes on expressions are experimental
--> $DIR/capture-analysis-1.rs:15:13
|
LL | let c = #[rustc_capture_analysis]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: see issue #15701 <https://github.com/rust-lang/rust/issues/15701> for more information
= help: add `#![feature(stmt_expr_attributes)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: First Pass analysis includes:
--> $DIR/capture-analysis-1.rs:19:5
--> $DIR/capture-analysis-1.rs:16:5
|
LL | / || {
LL | |
Expand All @@ -20,28 +10,28 @@ LL | | };
| |_____^
|
note: Capturing p[] -> Immutable
--> $DIR/capture-analysis-1.rs:22:26
--> $DIR/capture-analysis-1.rs:19:26
|
LL | println!("{:?}", p);
| ^
note: Capturing p[(0, 0)] -> Immutable
--> $DIR/capture-analysis-1.rs:25:26
--> $DIR/capture-analysis-1.rs:22:26
|
LL | println!("{:?}", p.x);
| ^^^
note: Capturing q[(0, 0)] -> Immutable
--> $DIR/capture-analysis-1.rs:28:26
--> $DIR/capture-analysis-1.rs:25:26
|
LL | println!("{:?}", q.x);
| ^^^
note: Capturing q[] -> Immutable
--> $DIR/capture-analysis-1.rs:30:26
--> $DIR/capture-analysis-1.rs:27:26
|
LL | println!("{:?}", q);
| ^

error: Min Capture analysis includes:
--> $DIR/capture-analysis-1.rs:19:5
--> $DIR/capture-analysis-1.rs:16:5
|
LL | / || {
LL | |
Expand All @@ -52,16 +42,15 @@ LL | | };
| |_____^
|
note: Min Capture p[] -> Immutable
--> $DIR/capture-analysis-1.rs:22:26
--> $DIR/capture-analysis-1.rs:19:26
|
LL | println!("{:?}", p);
| ^
note: Min Capture q[] -> Immutable
--> $DIR/capture-analysis-1.rs:30:26
--> $DIR/capture-analysis-1.rs:27:26
|
LL | println!("{:?}", q);
| ^

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

For more information about this error, try `rustc --explain E0658`.
3 changes: 0 additions & 3 deletions tests/ui/closures/2229_closure_analysis/capture-analysis-2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ fn main() {
let mut p = Point { x: String::new(), y: 10 };

let c = #[rustc_capture_analysis]
//~^ ERROR: attributes on expressions are experimental
//~| NOTE: see issue #15701 <https://github.com/rust-lang/rust/issues/15701>
//~| NOTE: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
|| {
//~^ ERROR First Pass analysis includes:
//~| ERROR Min Capture analysis includes:
Expand Down
Loading
Loading