From ffe1dba2fb6e6caa5d556e36a56c26461285a334 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman Date: Sun, 17 May 2026 21:06:00 +0200 Subject: [PATCH 01/26] Fix unused_parens for pinned reference patterns --- compiler/rustc_lint/src/unused.rs | 35 ++++-- ...ns-pinned-reference-patterns-no-feature.rs | 9 ++ ...inned-reference-patterns-no-feature.stderr | 23 ++++ ...sed-parens-pinned-reference-patterns.fixed | 56 +++++++++ ...unused-parens-pinned-reference-patterns.rs | 56 +++++++++ ...ed-parens-pinned-reference-patterns.stderr | 114 ++++++++++++++++++ 6 files changed, 286 insertions(+), 7 deletions(-) create mode 100644 tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.rs create mode 100644 tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.stderr create mode 100644 tests/ui/lint/unused-parens-pinned-reference-patterns.fixed create mode 100644 tests/ui/lint/unused-parens-pinned-reference-patterns.rs create mode 100644 tests/ui/lint/unused-parens-pinned-reference-patterns.stderr diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index ed7afa1c711de..0ff31eba28c6a 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -636,7 +636,7 @@ impl UnusedParens { avoid_mut: bool, keep_space: (bool, bool), ) { - use ast::{BindingMode, PatKind}; + use ast::{BindingMode, ByRef, Mutability, PatKind, Pinnedness}; if let PatKind::Paren(inner) = &value.kind { match inner.kind { @@ -649,8 +649,16 @@ impl UnusedParens { PatKind::Guard(..) => return, // Avoid `p0 | .. | pn` if we should. PatKind::Or(..) if avoid_or => return, - // Avoid `mut x` and `mut x @ p` if we should: - PatKind::Ident(BindingMode::MUT, ..) if avoid_mut => { + // Avoid bindings that start with `mut`, like `mut x`, `mut x @ p`, + // and `mut ref pin const x`, if we should. + PatKind::Ident(BindingMode(_, Mutability::Mut), ..) if avoid_mut => { + return; + } + PatKind::Ref(_, Pinnedness::Pinned, _) + | PatKind::Ident(BindingMode(ByRef::Yes(Pinnedness::Pinned, _), _), ..) + // FIXME(pin_ergonomics): Remove this gate once pinned patterns are stable. + if !cx.builder.features().pin_ergonomics() => + { return; } // Otherwise proceed with linting. @@ -756,8 +764,8 @@ impl EarlyLintPass for UnusedParens { } fn check_pat(&mut self, cx: &EarlyContext<'_>, p: &ast::Pat) { - use ast::Mutability; use ast::PatKind::*; + use ast::{Mutability, Pinnedness}; let keep_space = (false, false); match &p.kind { // Do not lint on `(..)` as that will result in the other arms being useless. @@ -789,11 +797,24 @@ impl EarlyLintPass for UnusedParens { self.check_unused_parens_pat(cx, p, true, false, keep_space) } // Avoid linting on `&(mut x)` as `&mut x` has a different meaning, #55342. + // This only applies to plain shared reference patterns. In `&pin const (mut x)`, + // `pin const` is consumed before parsing the subpattern, so removing the + // parentheses preserves `mut x` as a binding pattern. // Also avoid linting on `& mut? (p0 | .. | pn)`, #64106. - // FIXME(pin_ergonomics): check pinned patterns - Ref(p, _, m) => { - self.check_unused_parens_pat(cx, p, true, *m == Mutability::Not, keep_space) + Ref(p, pinned, m) + if *pinned != Pinnedness::Pinned + // FIXME(pin_ergonomics): Remove this gate once pinned patterns are stable. + || cx.builder.features().pin_ergonomics() => + { + self.check_unused_parens_pat( + cx, + p, + true, + *pinned == Pinnedness::Not && *m == Mutability::Not, + keep_space, + ); } + Ref(..) => {} } } diff --git a/tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.rs b/tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.rs new file mode 100644 index 0000000000000..92ef85429aa7a --- /dev/null +++ b/tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.rs @@ -0,0 +1,9 @@ +#![feature(mut_ref)] +#![warn(unused_parens)] + +fn main() { + let pin_const: &pin const i32 = todo!(); + //~^ ERROR pinned reference syntax is experimental + let &pin const (_x) = pin_const; + //~^ ERROR pinned reference syntax is experimental +} diff --git a/tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.stderr b/tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.stderr new file mode 100644 index 0000000000000..92c8d99d6e0f1 --- /dev/null +++ b/tests/ui/lint/unused-parens-pinned-reference-patterns-no-feature.stderr @@ -0,0 +1,23 @@ +error[E0658]: pinned reference syntax is experimental + --> $DIR/unused-parens-pinned-reference-patterns-no-feature.rs:5:21 + | +LL | let pin_const: &pin const i32 = todo!(); + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` 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]: pinned reference syntax is experimental + --> $DIR/unused-parens-pinned-reference-patterns-no-feature.rs:7:10 + | +LL | let &pin const (_x) = pin_const; + | ^^^ + | + = note: see issue #130494 for more information + = help: add `#![feature(pin_ergonomics)]` 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: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/lint/unused-parens-pinned-reference-patterns.fixed b/tests/ui/lint/unused-parens-pinned-reference-patterns.fixed new file mode 100644 index 0000000000000..88c30d4696736 --- /dev/null +++ b/tests/ui/lint/unused-parens-pinned-reference-patterns.fixed @@ -0,0 +1,56 @@ +//@ run-rustfix +//@ check-pass +//@ normalize-stderr: "warning: 9 warnings emitted\n\n" -> "warning: 9 warnings emitted\n" +#![feature(pin_ergonomics, mut_ref)] +#![allow(dead_code)] +#![warn(unused_parens)] + +fn pinned_reference_patterns( + pin_const: &pin const i32, + pin_mut: &pin mut i32, + nested_pin_const: &pin const &pin const i32, +) { + let &pin const _x = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin const mut _x = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin const mut _x @ _ = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin mut mut _x = pin_mut; + //~^ WARN unnecessary parentheses around pattern + + let &pin const &pin const _x = nested_pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin const ref pin const _x = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin mut ref pin mut _x = pin_mut; + //~^ WARN unnecessary parentheses around pattern + + let &pin const mut ref pin const _x = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin mut mut ref pin mut _x = pin_mut; + //~^ WARN unnecessary parentheses around pattern +} + +fn pinned_or_patterns_are_still_ambiguous(pin_const: &pin const i32) { + match pin_const { + &pin const (0 | 1) => {} + _ => {} + } +} + +fn plain_shared_reference_patterns_still_need_parens(shared: &i32) { + let &(mut _x) = shared; + + let &(mut ref _x) = shared; + + let &(mut ref pin const _x) = shared; +} + +fn main() {} diff --git a/tests/ui/lint/unused-parens-pinned-reference-patterns.rs b/tests/ui/lint/unused-parens-pinned-reference-patterns.rs new file mode 100644 index 0000000000000..040ba3e45bf45 --- /dev/null +++ b/tests/ui/lint/unused-parens-pinned-reference-patterns.rs @@ -0,0 +1,56 @@ +//@ run-rustfix +//@ check-pass +//@ normalize-stderr: "warning: 9 warnings emitted\n\n" -> "warning: 9 warnings emitted\n" +#![feature(pin_ergonomics, mut_ref)] +#![allow(dead_code)] +#![warn(unused_parens)] + +fn pinned_reference_patterns( + pin_const: &pin const i32, + pin_mut: &pin mut i32, + nested_pin_const: &pin const &pin const i32, +) { + let &pin const (_x) = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin const (mut _x) = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin const (mut _x @ _) = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin mut (mut _x) = pin_mut; + //~^ WARN unnecessary parentheses around pattern + + let &pin const (&pin const _x) = nested_pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin const (ref pin const _x) = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin mut (ref pin mut _x) = pin_mut; + //~^ WARN unnecessary parentheses around pattern + + let &pin const (mut ref pin const _x) = pin_const; + //~^ WARN unnecessary parentheses around pattern + + let &pin mut (mut ref pin mut _x) = pin_mut; + //~^ WARN unnecessary parentheses around pattern +} + +fn pinned_or_patterns_are_still_ambiguous(pin_const: &pin const i32) { + match pin_const { + &pin const (0 | 1) => {} + _ => {} + } +} + +fn plain_shared_reference_patterns_still_need_parens(shared: &i32) { + let &(mut _x) = shared; + + let &(mut ref _x) = shared; + + let &(mut ref pin const _x) = shared; +} + +fn main() {} diff --git a/tests/ui/lint/unused-parens-pinned-reference-patterns.stderr b/tests/ui/lint/unused-parens-pinned-reference-patterns.stderr new file mode 100644 index 0000000000000..15921b6864d7d --- /dev/null +++ b/tests/ui/lint/unused-parens-pinned-reference-patterns.stderr @@ -0,0 +1,114 @@ +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:13:20 + | +LL | let &pin const (_x) = pin_const; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-pinned-reference-patterns.rs:6:9 + | +LL | #![warn(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let &pin const (_x) = pin_const; +LL + let &pin const _x = pin_const; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:16:20 + | +LL | let &pin const (mut _x) = pin_const; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin const (mut _x) = pin_const; +LL + let &pin const mut _x = pin_const; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:19:20 + | +LL | let &pin const (mut _x @ _) = pin_const; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin const (mut _x @ _) = pin_const; +LL + let &pin const mut _x @ _ = pin_const; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:22:18 + | +LL | let &pin mut (mut _x) = pin_mut; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin mut (mut _x) = pin_mut; +LL + let &pin mut mut _x = pin_mut; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:25:20 + | +LL | let &pin const (&pin const _x) = nested_pin_const; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin const (&pin const _x) = nested_pin_const; +LL + let &pin const &pin const _x = nested_pin_const; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:28:20 + | +LL | let &pin const (ref pin const _x) = pin_const; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin const (ref pin const _x) = pin_const; +LL + let &pin const ref pin const _x = pin_const; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:31:18 + | +LL | let &pin mut (ref pin mut _x) = pin_mut; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin mut (ref pin mut _x) = pin_mut; +LL + let &pin mut ref pin mut _x = pin_mut; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:34:20 + | +LL | let &pin const (mut ref pin const _x) = pin_const; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin const (mut ref pin const _x) = pin_const; +LL + let &pin const mut ref pin const _x = pin_const; + | + +warning: unnecessary parentheses around pattern + --> $DIR/unused-parens-pinned-reference-patterns.rs:37:18 + | +LL | let &pin mut (mut ref pin mut _x) = pin_mut; + | ^ ^ + | +help: remove these parentheses + | +LL - let &pin mut (mut ref pin mut _x) = pin_mut; +LL + let &pin mut mut ref pin mut _x = pin_mut; + | + +warning: 9 warnings emitted From 9849fa836a03e131ecc53ef5b762a8011dee49a9 Mon Sep 17 00:00:00 2001 From: Pieter-Louis Schoeman <127837395+P8L1@users.noreply.github.com> Date: Sun, 31 May 2026 16:15:33 +0200 Subject: [PATCH 02/26] Adress concerns --- compiler/rustc_lint/src/unused.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 0ff31eba28c6a..7c934b2d16751 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -649,8 +649,8 @@ impl UnusedParens { PatKind::Guard(..) => return, // Avoid `p0 | .. | pn` if we should. PatKind::Or(..) if avoid_or => return, - // Avoid bindings that start with `mut`, like `mut x`, `mut x @ p`, - // and `mut ref pin const x`, if we should. + // Avoid bindings whose own binding mutability is `mut`, like `mut x`, + // `mut x @ p`, and `mut ref pin const x`, if we should. PatKind::Ident(BindingMode(_, Mutability::Mut), ..) if avoid_mut => { return; } From 3c6c901f6b0b8926ccb28e3e8aba26548a5842ac Mon Sep 17 00:00:00 2001 From: zedddie Date: Mon, 1 Jun 2026 06:07:03 +0200 Subject: [PATCH 03/26] move batch --- .../issue-17959.rs => dropck/drop-impl-sized-bound-mismatch.rs} | 0 .../drop-impl-sized-bound-mismatch.stderr} | 0 .../impl-generic-struct-with-concrete-types.rs} | 0 .../issue-18183.rs => generics/type-param-self-reference.rs} | 0 .../type-param-self-reference.stderr} | 0 .../issue-18107.rs => impl-trait/bare-trait-object-return.rs} | 0 .../bare-trait-object-return.stderr} | 0 .../elided-lifetime-mismatch-in-self-type.rs} | 0 .../elided-lifetime-mismatch-in-self-type.stderr} | 0 .../issue-18232.rs => lifetimes/trait-method-lifetime-bounds.rs} | 0 .../issue-17999.rs => lint/unused/unused-variables-in-loop.rs} | 0 .../unused/unused-variables-in-loop.stderr} | 0 .../issue-18446.rs => methods/call-ambig-trait-object-method.rs} | 0 .../call-ambig-trait-object-method.stderr} | 0 .../inherent-method-on-dyn-with-default.rs} | 0 .../issue-18173.rs => traits/bound/implicit-assoc-type.rs} | 0 16 files changed, 0 insertions(+), 0 deletions(-) rename tests/ui/{issues/issue-17959.rs => dropck/drop-impl-sized-bound-mismatch.rs} (100%) rename tests/ui/{issues/issue-17959.stderr => dropck/drop-impl-sized-bound-mismatch.stderr} (100%) rename tests/ui/{issues/issue-17905.rs => generics/impl-generic-struct-with-concrete-types.rs} (100%) rename tests/ui/{issues/issue-18183.rs => generics/type-param-self-reference.rs} (100%) rename tests/ui/{issues/issue-18183.stderr => generics/type-param-self-reference.stderr} (100%) rename tests/ui/{issues/issue-18107.rs => impl-trait/bare-trait-object-return.rs} (100%) rename tests/ui/{issues/issue-18107.stderr => impl-trait/bare-trait-object-return.stderr} (100%) rename tests/ui/{issues/issue-17905-2.rs => lifetimes/elided-lifetime-mismatch-in-self-type.rs} (100%) rename tests/ui/{issues/issue-17905-2.stderr => lifetimes/elided-lifetime-mismatch-in-self-type.stderr} (100%) rename tests/ui/{issues/issue-18232.rs => lifetimes/trait-method-lifetime-bounds.rs} (100%) rename tests/ui/{issues/issue-17999.rs => lint/unused/unused-variables-in-loop.rs} (100%) rename tests/ui/{issues/issue-17999.stderr => lint/unused/unused-variables-in-loop.stderr} (100%) rename tests/ui/{issues/issue-18446.rs => methods/call-ambig-trait-object-method.rs} (100%) rename tests/ui/{issues/issue-18446.stderr => methods/call-ambig-trait-object-method.stderr} (100%) rename tests/ui/{issues/issue-18446-2.rs => methods/inherent-method-on-dyn-with-default.rs} (100%) rename tests/ui/{issues/issue-18173.rs => traits/bound/implicit-assoc-type.rs} (100%) diff --git a/tests/ui/issues/issue-17959.rs b/tests/ui/dropck/drop-impl-sized-bound-mismatch.rs similarity index 100% rename from tests/ui/issues/issue-17959.rs rename to tests/ui/dropck/drop-impl-sized-bound-mismatch.rs diff --git a/tests/ui/issues/issue-17959.stderr b/tests/ui/dropck/drop-impl-sized-bound-mismatch.stderr similarity index 100% rename from tests/ui/issues/issue-17959.stderr rename to tests/ui/dropck/drop-impl-sized-bound-mismatch.stderr diff --git a/tests/ui/issues/issue-17905.rs b/tests/ui/generics/impl-generic-struct-with-concrete-types.rs similarity index 100% rename from tests/ui/issues/issue-17905.rs rename to tests/ui/generics/impl-generic-struct-with-concrete-types.rs diff --git a/tests/ui/issues/issue-18183.rs b/tests/ui/generics/type-param-self-reference.rs similarity index 100% rename from tests/ui/issues/issue-18183.rs rename to tests/ui/generics/type-param-self-reference.rs diff --git a/tests/ui/issues/issue-18183.stderr b/tests/ui/generics/type-param-self-reference.stderr similarity index 100% rename from tests/ui/issues/issue-18183.stderr rename to tests/ui/generics/type-param-self-reference.stderr diff --git a/tests/ui/issues/issue-18107.rs b/tests/ui/impl-trait/bare-trait-object-return.rs similarity index 100% rename from tests/ui/issues/issue-18107.rs rename to tests/ui/impl-trait/bare-trait-object-return.rs diff --git a/tests/ui/issues/issue-18107.stderr b/tests/ui/impl-trait/bare-trait-object-return.stderr similarity index 100% rename from tests/ui/issues/issue-18107.stderr rename to tests/ui/impl-trait/bare-trait-object-return.stderr diff --git a/tests/ui/issues/issue-17905-2.rs b/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.rs similarity index 100% rename from tests/ui/issues/issue-17905-2.rs rename to tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.rs diff --git a/tests/ui/issues/issue-17905-2.stderr b/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.stderr similarity index 100% rename from tests/ui/issues/issue-17905-2.stderr rename to tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.stderr diff --git a/tests/ui/issues/issue-18232.rs b/tests/ui/lifetimes/trait-method-lifetime-bounds.rs similarity index 100% rename from tests/ui/issues/issue-18232.rs rename to tests/ui/lifetimes/trait-method-lifetime-bounds.rs diff --git a/tests/ui/issues/issue-17999.rs b/tests/ui/lint/unused/unused-variables-in-loop.rs similarity index 100% rename from tests/ui/issues/issue-17999.rs rename to tests/ui/lint/unused/unused-variables-in-loop.rs diff --git a/tests/ui/issues/issue-17999.stderr b/tests/ui/lint/unused/unused-variables-in-loop.stderr similarity index 100% rename from tests/ui/issues/issue-17999.stderr rename to tests/ui/lint/unused/unused-variables-in-loop.stderr diff --git a/tests/ui/issues/issue-18446.rs b/tests/ui/methods/call-ambig-trait-object-method.rs similarity index 100% rename from tests/ui/issues/issue-18446.rs rename to tests/ui/methods/call-ambig-trait-object-method.rs diff --git a/tests/ui/issues/issue-18446.stderr b/tests/ui/methods/call-ambig-trait-object-method.stderr similarity index 100% rename from tests/ui/issues/issue-18446.stderr rename to tests/ui/methods/call-ambig-trait-object-method.stderr diff --git a/tests/ui/issues/issue-18446-2.rs b/tests/ui/methods/inherent-method-on-dyn-with-default.rs similarity index 100% rename from tests/ui/issues/issue-18446-2.rs rename to tests/ui/methods/inherent-method-on-dyn-with-default.rs diff --git a/tests/ui/issues/issue-18173.rs b/tests/ui/traits/bound/implicit-assoc-type.rs similarity index 100% rename from tests/ui/issues/issue-18173.rs rename to tests/ui/traits/bound/implicit-assoc-type.rs From 01f5cc80731a968550ab858d28904948f4780fe6 Mon Sep 17 00:00:00 2001 From: zedddie Date: Mon, 1 Jun 2026 06:35:38 +0200 Subject: [PATCH 04/26] bless batch --- tests/ui/dropck/drop-impl-sized-bound-mismatch.rs | 2 ++ .../ui/dropck/drop-impl-sized-bound-mismatch.stderr | 4 ++-- .../impl-generic-struct-with-concrete-types.rs | 2 ++ tests/ui/generics/type-param-self-reference.rs | 2 ++ tests/ui/generics/type-param-self-reference.stderr | 2 +- tests/ui/impl-trait/bare-trait-object-return.rs | 2 ++ tests/ui/impl-trait/bare-trait-object-return.stderr | 2 +- .../elided-lifetime-mismatch-in-self-type.rs | 2 ++ .../elided-lifetime-mismatch-in-self-type.stderr | 12 ++++++------ tests/ui/lifetimes/trait-method-lifetime-bounds.rs | 2 ++ tests/ui/lint/unused/unused-variables-in-loop.rs | 2 ++ tests/ui/lint/unused/unused-variables-in-loop.stderr | 6 +++--- tests/ui/methods/call-ambig-trait-object-method.rs | 5 +++-- .../ui/methods/call-ambig-trait-object-method.stderr | 6 +++--- .../methods/inherent-method-on-dyn-with-default.rs | 5 ++++- tests/ui/traits/bound/implicit-assoc-type.rs | 2 ++ 16 files changed, 39 insertions(+), 19 deletions(-) diff --git a/tests/ui/dropck/drop-impl-sized-bound-mismatch.rs b/tests/ui/dropck/drop-impl-sized-bound-mismatch.rs index 8bf9e623605ca..c5a0e256d7b7f 100644 --- a/tests/ui/dropck/drop-impl-sized-bound-mismatch.rs +++ b/tests/ui/dropck/drop-impl-sized-bound-mismatch.rs @@ -1,3 +1,5 @@ +//! Regression test for . + extern crate core; use core::ops::Drop; diff --git a/tests/ui/dropck/drop-impl-sized-bound-mismatch.stderr b/tests/ui/dropck/drop-impl-sized-bound-mismatch.stderr index 604413c4b6d19..b21cc26245ed8 100644 --- a/tests/ui/dropck/drop-impl-sized-bound-mismatch.stderr +++ b/tests/ui/dropck/drop-impl-sized-bound-mismatch.stderr @@ -1,11 +1,11 @@ error[E0367]: `Drop` impl requires `T: Sized` but the struct it is implemented for does not - --> $DIR/issue-17959.rs:11:6 + --> $DIR/drop-impl-sized-bound-mismatch.rs:13:6 | LL | impl Drop for G { | ^ | note: the implementor must specify the same requirement - --> $DIR/issue-17959.rs:7:1 + --> $DIR/drop-impl-sized-bound-mismatch.rs:9:1 | LL | struct G { | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/generics/impl-generic-struct-with-concrete-types.rs b/tests/ui/generics/impl-generic-struct-with-concrete-types.rs index 6238379b5a04b..68a7db69a2bb1 100644 --- a/tests/ui/generics/impl-generic-struct-with-concrete-types.rs +++ b/tests/ui/generics/impl-generic-struct-with-concrete-types.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ run-pass #[derive(Debug)] diff --git a/tests/ui/generics/type-param-self-reference.rs b/tests/ui/generics/type-param-self-reference.rs index 64476d1c10999..dd8fead948916 100644 --- a/tests/ui/generics/type-param-self-reference.rs +++ b/tests/ui/generics/type-param-self-reference.rs @@ -1,3 +1,5 @@ +//! Regression test for . + pub struct Foo(Bar); //~ ERROR E0128 pub struct Baz(Foo); fn main() {} diff --git a/tests/ui/generics/type-param-self-reference.stderr b/tests/ui/generics/type-param-self-reference.stderr index 07fa4cdc7535c..b24f0ee8b67e0 100644 --- a/tests/ui/generics/type-param-self-reference.stderr +++ b/tests/ui/generics/type-param-self-reference.stderr @@ -1,5 +1,5 @@ error[E0128]: generic parameter defaults cannot reference parameters before they are declared - --> $DIR/issue-18183.rs:1:20 + --> $DIR/type-param-self-reference.rs:3:20 | LL | pub struct Foo(Bar); | ^^^ cannot reference `Bar` before it is declared diff --git a/tests/ui/impl-trait/bare-trait-object-return.rs b/tests/ui/impl-trait/bare-trait-object-return.rs index b1b6ff4f7ad26..18cafddd6a911 100644 --- a/tests/ui/impl-trait/bare-trait-object-return.rs +++ b/tests/ui/impl-trait/bare-trait-object-return.rs @@ -1,3 +1,5 @@ +//! Regression test for . + pub trait AbstractRenderer {} fn _create_render(_: &()) -> diff --git a/tests/ui/impl-trait/bare-trait-object-return.stderr b/tests/ui/impl-trait/bare-trait-object-return.stderr index 177ef2f1c33f7..0445926e4d4a3 100644 --- a/tests/ui/impl-trait/bare-trait-object-return.stderr +++ b/tests/ui/impl-trait/bare-trait-object-return.stderr @@ -1,5 +1,5 @@ error[E0746]: return type cannot be a trait object without pointer indirection - --> $DIR/issue-18107.rs:4:5 + --> $DIR/bare-trait-object-return.rs:6:5 | LL | dyn AbstractRenderer | ^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time diff --git a/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.rs b/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.rs index 44279cc867b46..fa634c8447a79 100644 --- a/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.rs +++ b/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.rs @@ -1,3 +1,5 @@ +//! Regression test for . + #[derive(Debug)] struct Pair (T, V); diff --git a/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.stderr b/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.stderr index c66cb2224897d..920fe850f0ec7 100644 --- a/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.stderr +++ b/tests/ui/lifetimes/elided-lifetime-mismatch-in-self-type.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched `self` parameter type - --> $DIR/issue-17905-2.rs:8:18 + --> $DIR/elided-lifetime-mismatch-in-self-type.rs:10:18 | LL | fn say(self: &Pair<&str, isize>) { | ^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -7,18 +7,18 @@ LL | fn say(self: &Pair<&str, isize>) { = note: expected struct `Pair<&_, _>` found struct `Pair<&_, _>` note: the anonymous lifetime defined here... - --> $DIR/issue-17905-2.rs:8:24 + --> $DIR/elided-lifetime-mismatch-in-self-type.rs:10:24 | LL | fn say(self: &Pair<&str, isize>) { | ^^^^ note: ...does not necessarily outlive the anonymous lifetime as defined here - --> $DIR/issue-17905-2.rs:5:5 + --> $DIR/elided-lifetime-mismatch-in-self-type.rs:7:5 | LL | &str, | ^ error[E0308]: mismatched `self` parameter type - --> $DIR/issue-17905-2.rs:8:18 + --> $DIR/elided-lifetime-mismatch-in-self-type.rs:10:18 | LL | fn say(self: &Pair<&str, isize>) { | ^^^^^^^^^^^^^^^^^^ lifetime mismatch @@ -26,12 +26,12 @@ LL | fn say(self: &Pair<&str, isize>) { = note: expected struct `Pair<&_, _>` found struct `Pair<&_, _>` note: the anonymous lifetime as defined here... - --> $DIR/issue-17905-2.rs:5:5 + --> $DIR/elided-lifetime-mismatch-in-self-type.rs:7:5 | LL | &str, | ^ note: ...does not necessarily outlive the anonymous lifetime defined here - --> $DIR/issue-17905-2.rs:8:24 + --> $DIR/elided-lifetime-mismatch-in-self-type.rs:10:24 | LL | fn say(self: &Pair<&str, isize>) { | ^^^^ diff --git a/tests/ui/lifetimes/trait-method-lifetime-bounds.rs b/tests/ui/lifetimes/trait-method-lifetime-bounds.rs index d526a67950cf6..eebdce5b49286 100644 --- a/tests/ui/lifetimes/trait-method-lifetime-bounds.rs +++ b/tests/ui/lifetimes/trait-method-lifetime-bounds.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ run-pass struct Cursor<'a>(::std::marker::PhantomData<&'a ()>); diff --git a/tests/ui/lint/unused/unused-variables-in-loop.rs b/tests/ui/lint/unused/unused-variables-in-loop.rs index 941f1e7755afe..c96d2ac5f3fe5 100644 --- a/tests/ui/lint/unused/unused-variables-in-loop.rs +++ b/tests/ui/lint/unused/unused-variables-in-loop.rs @@ -1,3 +1,5 @@ +//! Regression test for . + #![deny(unused_variables)] fn main() { diff --git a/tests/ui/lint/unused/unused-variables-in-loop.stderr b/tests/ui/lint/unused/unused-variables-in-loop.stderr index 4a1ef7350b8cb..6c311f03ce508 100644 --- a/tests/ui/lint/unused/unused-variables-in-loop.stderr +++ b/tests/ui/lint/unused/unused-variables-in-loop.stderr @@ -1,17 +1,17 @@ error: unused variable: `x` - --> $DIR/issue-17999.rs:5:13 + --> $DIR/unused-variables-in-loop.rs:7:13 | LL | let x = (); | ^ help: if this is intentional, prefix it with an underscore: `_x` | note: the lint level is defined here - --> $DIR/issue-17999.rs:1:9 + --> $DIR/unused-variables-in-loop.rs:3:9 | LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ error: unused variable: `a` - --> $DIR/issue-17999.rs:7:13 + --> $DIR/unused-variables-in-loop.rs:9:13 | LL | a => {} | ^ help: if this is intentional, prefix it with an underscore: `_a` diff --git a/tests/ui/methods/call-ambig-trait-object-method.rs b/tests/ui/methods/call-ambig-trait-object-method.rs index a2e238da03a3e..9e2f5c5aebe8b 100644 --- a/tests/ui/methods/call-ambig-trait-object-method.rs +++ b/tests/ui/methods/call-ambig-trait-object-method.rs @@ -1,5 +1,6 @@ -// Test that name clashes between the method in an impl for the type -// and the method in the trait when both are in the same scope. +//! Regression test for . +//! Test that name clashes between the method in an impl for the type +//! and the method in the trait when both are in the same scope. trait T { fn foo(&self); diff --git a/tests/ui/methods/call-ambig-trait-object-method.stderr b/tests/ui/methods/call-ambig-trait-object-method.stderr index 25ae303e902b5..b76f107160011 100644 --- a/tests/ui/methods/call-ambig-trait-object-method.stderr +++ b/tests/ui/methods/call-ambig-trait-object-method.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/issue-18446.rs:18:7 + --> $DIR/call-ambig-trait-object-method.rs:19:7 | LL | x.foo(); | ^^^ multiple `foo` found | note: candidate #1 is defined in the trait `T` - --> $DIR/issue-18446.rs:5:5 + --> $DIR/call-ambig-trait-object-method.rs:6:5 | LL | fn foo(&self); | ^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `(dyn T + 'a)` - --> $DIR/issue-18446.rs:9:5 + --> $DIR/call-ambig-trait-object-method.rs:10:5 | LL | fn foo(&self) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/methods/inherent-method-on-dyn-with-default.rs b/tests/ui/methods/inherent-method-on-dyn-with-default.rs index d403487c001fb..cb84da56defad 100644 --- a/tests/ui/methods/inherent-method-on-dyn-with-default.rs +++ b/tests/ui/methods/inherent-method-on-dyn-with-default.rs @@ -1,6 +1,9 @@ +//! Regression test for . +//! Tests that an inherent method on a trait object with existing default method +//! doesn't emit a duplicate definition error. + //@ check-pass #![allow(dead_code)] -// Test that methods in trait impls should override default methods. trait T { fn foo(&self) -> i32 { 0 } diff --git a/tests/ui/traits/bound/implicit-assoc-type.rs b/tests/ui/traits/bound/implicit-assoc-type.rs index a9f20e827fbe3..491516ac6bfae 100644 --- a/tests/ui/traits/bound/implicit-assoc-type.rs +++ b/tests/ui/traits/bound/implicit-assoc-type.rs @@ -1,3 +1,5 @@ +//! Regression test for . + //@ check-pass trait Foo { type T; From 7ec390aaca3d568854582bc461ba67b8b471f51d Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 29 May 2026 09:30:15 +0200 Subject: [PATCH 05/26] remove unnecessary roundtrips through kind_from_def_id --- .../src/solve/normalizes_to/mod.rs | 26 +++++++------------ compiler/rustc_type_ir/src/const_kind.rs | 1 - 2 files changed, 10 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index afec80e4b873a..a1757290d2ae3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -417,7 +417,9 @@ where ty::AliasTermKind::ProjectionConst { .. } => { let uv = ty::UnevaluatedConst::new( cx, - ty::UnevaluatedConstKind::new_from_def_id(cx, target_item_def_id.into()), + ty::UnevaluatedConstKind::Projection { + def_id: target_item_def_id.into().try_into().unwrap(), + }, target_args, ); return ecx.evaluate_const_and_instantiate_normalizes_to_term(goal, uv); @@ -501,7 +503,7 @@ where let pred = ty::ProjectionPredicate { projection_term: ty::AliasTerm::new( cx, - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), + goal.predicate.alias.kind, [goal.predicate.self_ty(), inputs], ), term: output.into(), @@ -558,7 +560,7 @@ where ( ty::AliasTerm::new( cx, - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), + goal.predicate.alias.kind, [goal.predicate.self_ty(), tupled_inputs_ty], ), output_coroutine_ty.into(), @@ -567,7 +569,7 @@ where ( ty::AliasTerm::new( cx, - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), + goal.predicate.alias.kind, [ I::GenericArg::from(goal.predicate.self_ty()), tupled_inputs_ty.into(), @@ -580,7 +582,7 @@ where ( ty::AliasTerm::new( cx, - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), + goal.predicate.alias.kind, [goal.predicate.self_ty(), tupled_inputs_ty], ), coroutine_return_ty.into(), @@ -784,11 +786,7 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new( - ecx.cx(), - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), - [self_ty], - ), + projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.alias.kind, [self_ty]), term, } .upcast(cx), @@ -820,11 +818,7 @@ where CandidateSource::BuiltinImpl(BuiltinImplSource::Misc), goal, ty::ProjectionPredicate { - projection_term: ty::AliasTerm::new( - ecx.cx(), - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), - [self_ty], - ), + projection_term: ty::AliasTerm::new(ecx.cx(), goal.predicate.alias.kind, [self_ty]), term, } .upcast(cx), @@ -912,7 +906,7 @@ where ty::ProjectionPredicate { projection_term: ty::AliasTerm::new( ecx.cx(), - cx.alias_term_kind_from_def_id(goal.predicate.def_id()), + goal.predicate.alias.kind, [self_ty, coroutine.resume_ty()], ), term, diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index 0a13dd5e173a6..37824447fc893 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -130,7 +130,6 @@ impl UnevaluatedConstKind { UnevaluatedConstKind::Inherent { def_id } => def_id.into(), UnevaluatedConstKind::Free { def_id } => def_id.into(), UnevaluatedConstKind::Anon { def_id } => def_id.into(), - //UnevaluatedConstKind::Expr { def_id } => def_id.into(), } } } From 09bb5bbb71cca71a30be5070a0171220f76b26c0 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Tue, 2 Jun 2026 08:24:04 +0200 Subject: [PATCH 06/26] remove AliasTerm::kind() method --- .../src/hir_ty_lowering/bounds.rs | 2 +- compiler/rustc_infer/src/infer/projection.rs | 2 +- .../src/infer/relate/generalize.rs | 4 ++-- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../src/solve/normalizes_to/anon_const.rs | 2 +- .../src/solve/normalizes_to/free_alias.rs | 4 ++-- .../src/solve/normalizes_to/inherent.rs | 2 +- .../src/solve/normalizes_to/mod.rs | 4 ++-- .../traits/fulfillment_errors.rs | 4 ++-- .../src/error_reporting/traits/overflow.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 2 +- .../src/solve/fulfill/derive_errors.rs | 5 ++--- .../src/traits/auto_trait.rs | 2 +- .../src/traits/normalize.rs | 2 +- .../src/traits/project.rs | 12 ++++++------ .../src/traits/query/normalize.rs | 4 ++-- .../src/normalize_projection_ty.rs | 2 +- compiler/rustc_type_ir/src/predicate.rs | 19 +++++++------------ compiler/rustc_type_ir/src/relate.rs | 2 +- .../src/needless_borrows_for_generic_args.rs | 2 +- 20 files changed, 37 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 6e2c7a82af3b1..770ccc7dff51f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -636,7 +636,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { | PredicateFilter::SelfAndAssociatedTypeBounds | PredicateFilter::ConstIfConst => { let projection_ty = projection_term - .map_bound(|projection_term| projection_term.expect_ty(self.tcx())); + .map_bound(|projection_term| projection_term.expect_ty()); // Calling `skip_binder` is okay, because `lower_bounds` expects the `param_ty` // parameter to have a skipped binder. let param_ty = Ty::new_alias(tcx, projection_ty.skip_binder()); diff --git a/compiler/rustc_infer/src/infer/projection.rs b/compiler/rustc_infer/src/infer/projection.rs index 81bb5b42401b2..c3a5a8a5d818d 100644 --- a/compiler/rustc_infer/src/infer/projection.rs +++ b/compiler/rustc_infer/src/infer/projection.rs @@ -23,7 +23,7 @@ impl<'tcx> InferCtxt<'tcx> { debug_assert!(!self.next_trait_solver()); let span = self.tcx.def_span(alias_term.def_id()); - let infer_var = if alias_term.kind(self.tcx).is_type() { + let infer_var = if alias_term.kind.is_type() { self.next_ty_var(span).into() } else { self.next_const_var(span).into() diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 9b928e8fc9e99..8c296289fef0c 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -187,7 +187,7 @@ impl<'tcx> InferCtxt<'tcx> { let Some(source_alias) = source_term.to_alias_term() else { bug!("generalized `{source_term:?} to infer, not an alias"); }; - match source_alias.kind(self.tcx) { + match source_alias.kind { ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => { // FIXME: This does not handle subtyping correctly, we could @@ -426,7 +426,7 @@ impl<'tcx> Generalizer<'_, 'tcx> { /// Create a new type variable in the universe of the target when /// generalizing an alias. fn next_var_for_alias_of_kind(&self, alias: ty::AliasTerm<'tcx>) -> ty::Term<'tcx> { - if alias.kind(self.cx()).is_type() { + if alias.kind.is_type() { self.infcx.next_ty_var_in_universe(self.span, self.for_universe).into() } else { self.infcx.next_const_var_in_universe(self.span, self.for_universe).into() diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 46dfcff0a2add..fc7e8fd768c9b 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -3156,7 +3156,7 @@ define_print! { } ty::AliasTerm<'tcx> { - match self.kind(p.tcx()) { + match self.kind { ty::AliasTermKind::InherentTy {..} | ty::AliasTermKind::InherentConst {..} => p.pretty_print_inherent_projection(*self)?, ty::AliasTermKind::ProjectionTy { def_id } => { if !(p.should_print_verbose() || with_reduced_queries()) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs index b76f38b46a3df..38197c8c72de2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/anon_const.rs @@ -16,7 +16,7 @@ where goal: Goal>, def_id: I::UnevaluatedConstId, ) -> QueryResultOrRerunNonErased { - let uv = goal.predicate.alias.expect_ct(self.cx()); + let uv = goal.predicate.alias.expect_ct(); self.evaluate_const_and_instantiate_normalizes_to_term(goal, uv) } } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs index d68c7dd11d1d9..ad050b69425c5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/free_alias.rs @@ -31,7 +31,7 @@ where .map(|pred| goal.with(cx, pred)), ); - let actual = match free_alias.kind(cx) { + let actual = match free_alias.kind { ty::AliasTermKind::FreeTy { def_id } => { cx.type_of(def_id.into()).instantiate(cx, free_alias.args).skip_norm_wip().into() } @@ -43,7 +43,7 @@ where ty::AliasTermKind::FreeConst { .. } => { return self.evaluate_const_and_instantiate_normalizes_to_term( goal, - free_alias.expect_ct(cx), + free_alias.expect_ct(), ); } kind => panic!("expected free alias, found {kind:?}"), diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs index 2f44cc42a5d71..16a86cc44ccf9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/inherent.rs @@ -54,7 +54,7 @@ where .map(|pred| goal.with(cx, pred)), ); - let normalized = match inherent.kind(cx) { + let normalized = match inherent.kind { ty::AliasTermKind::InherentTy { def_id } => { cx.type_of(def_id.into()).instantiate(cx, inherent_args).skip_norm_wip().into() } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index a1757290d2ae3..381bcca6b97c9 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -287,7 +287,7 @@ where ); let error_response = |ecx: &mut EvalCtxt<'_, D>, guar| { - let error_term = match goal.predicate.alias.kind(cx) { + let error_term = match goal.predicate.alias.kind { ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(), ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(), kind => panic!("expected projection, found {kind:?}"), @@ -400,7 +400,7 @@ where } // Finally we construct the actual value of the associated type. - let term = match goal.predicate.alias.kind(cx) { + let term = match goal.predicate.alias.kind { ty::AliasTermKind::ProjectionTy { .. } => cx .type_of(target_item_def_id.into()) .instantiate(cx, target_args) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 9f0e9f47e4a6f..f78bc3e8b4884 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1666,7 +1666,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if let Some(lhs) = lhs.to_alias_term() && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind(self.tcx) + | ty::AliasTermKind::ProjectionConst { .. } = lhs.kind && let Some((better_type_err, expected_term)) = derive_better_type_error(lhs, rhs) { @@ -1676,7 +1676,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) } else if let Some(rhs) = rhs.to_alias_term() && let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind(self.tcx) + | ty::AliasTermKind::ProjectionConst { .. } = rhs.kind && let Some((better_type_err, expected_term)) = derive_better_type_error(rhs, lhs) { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index 0e45df45049b0..df7f89266012e 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -78,7 +78,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let mut err = match cause { OverflowCause::DeeplyNormalize(alias_term) => { let alias_term = self.resolve_vars_if_possible(alias_term); - let kind = alias_term.kind(self.tcx).descr(); + let kind = alias_term.kind.descr(); let alias_str = with_short_path(self.tcx, alias_term); struct_span_code_err!( self.dcx(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ef454f5e8f6df..6cc3c797391fe 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4876,7 +4876,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected: where_pred .skip_binder() .projection_term - .expect_ty(self.tcx) + .expect_ty() .to_ty(self.tcx), found, })]; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 1aa9af417ae50..8ea17c776ea31 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -395,7 +395,6 @@ impl<'tcx> BestObligation<'tcx> { &mut self, goal: &inspect::InspectGoal<'_, 'tcx>, ) -> ControlFlow> { - let tcx = goal.infcx().tcx; let pred_kind = goal.goal().predicate.kind(); match pred_kind.no_bound_vars() { @@ -404,7 +403,7 @@ impl<'tcx> BestObligation<'tcx> { } Some(ty::PredicateKind::NormalizesTo(pred)) if let ty::AliasTermKind::ProjectionTy { .. } - | ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind(tcx) => + | ty::AliasTermKind::ProjectionConst { .. } = pred.alias.kind => { self.detect_error_in_self_ty_normalization(goal, pred.alias.self_ty())?; self.detect_non_well_formed_assoc_item(goal, pred.alias)?; @@ -471,7 +470,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { } ty::PredicateKind::NormalizesTo(normalizes_to) if matches!( - normalizes_to.alias.kind(tcx), + normalizes_to.alias.kind, ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } ) => diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs index 3da4e84e89837..e080687ad4b56 100644 --- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs +++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs @@ -561,7 +561,7 @@ impl<'tcx> AutoTraitFinder<'tcx> { fn is_self_referential_projection(&self, p: ty::PolyProjectionPredicate<'tcx>) -> bool { if let Some(ty) = p.term().skip_binder().as_type() { - matches!(ty.kind(), ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) if proj == &p.skip_binder().projection_term.expect_ty(self.tcx)) + matches!(ty.kind(), ty::Alias(proj @ ty::AliasTy { kind: ty::Projection { .. }, .. }) if proj == &p.skip_binder().projection_term.expect_ty()) } else { false } diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index fa2cfdab13b17..ef69d0fe06c15 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -339,7 +339,7 @@ impl<'a, 'b, 'tcx> AssocTypeNormalizer<'a, 'b, 'tcx> { }), ); self.depth += 1; - let res = if free.kind(infcx.tcx).is_type() { + let res = if free.kind.is_type() { infcx .tcx .type_of(free.def_id()) diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 46c1c8e60a329..9be10dfeb250e 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -462,7 +462,7 @@ fn normalize_to_error<'a, 'tcx>( depth: usize, ) -> NormalizedTerm<'tcx> { let trait_ref = ty::Binder::dummy(projection_term.trait_ref(selcx.tcx())); - let new_value = match projection_term.kind(selcx.tcx()) { + let new_value = match projection_term.kind { ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::InherentTy { .. } | ty::AliasTermKind::OpaqueTy { .. } @@ -545,7 +545,7 @@ pub fn normalize_inherent_projection<'a, 'b, 'tcx>( )); } - let term: Term<'tcx> = if alias_term.kind(tcx).is_type() { + let term: Term<'tcx> = if alias_term.kind.is_type() { tcx.type_of(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() } else { tcx.const_of_item(alias_term.def_id()).instantiate(tcx, args).skip_norm_wip().into() @@ -629,7 +629,7 @@ impl<'tcx> Progress<'tcx> { alias_term: ty::AliasTerm<'tcx>, guar: ErrorGuaranteed, ) -> Self { - let err_term = if alias_term.kind(tcx).is_type() { + let err_term = if alias_term.kind.is_type() { Ty::new_error(tcx, guar).into() } else { ty::Const::new_error(tcx, guar).into() @@ -2010,7 +2010,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( return Ok(Projected::NoProgress(obligation.predicate.to_term(tcx))); } else { return Ok(Projected::Progress(Progress { - term: if obligation.predicate.kind(tcx).is_type() { + term: if obligation.predicate.kind.is_type() { Ty::new_misc_error(tcx).into() } else { ty::Const::new_misc_error(tcx).into() @@ -2029,7 +2029,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let args = obligation.predicate.args.rebase_onto(tcx, trait_def_id, args); let args = translate_args(selcx.infcx, param_env, impl_def_id, args, assoc_term.defining_node); - let term = if obligation.predicate.kind(tcx).is_type() { + let term = if obligation.predicate.kind.is_type() { tcx.type_of(assoc_term.item.def_id).map_bound(|ty| ty.into()) } else { tcx.const_of_item(assoc_term.item.def_id).map_bound(|ct| ct.into()) @@ -2038,7 +2038,7 @@ fn confirm_impl_candidate<'cx, 'tcx>( let progress = if !tcx.check_args_compatible(assoc_term.item.def_id, args) { let msg = "impl item and trait item have different parameters"; let span = obligation.cause.span; - let err = if obligation.predicate.kind(tcx).is_type() { + let err = if obligation.predicate.kind.is_type() { Ty::new_error_with_message(tcx, span, msg).into() } else { ty::Const::new_error_with_message(tcx, span, msg).into() diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 5b1f2e3a267a9..5f5b88df64278 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -327,7 +327,7 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { let c_term = infcx.canonicalize_query(self.param_env.and(term), &mut orig_values); debug!("QueryNormalizer: c_term = {:#?}", c_term); debug!("QueryNormalizer: orig_values = {:#?}", orig_values); - let result = match term.kind(tcx) { + let result = match term.kind { ty::AliasTermKind::ProjectionTy { .. } | ty::AliasTermKind::ProjectionConst { .. } => { tcx.normalize_canonicalized_projection(c_term) } @@ -380,7 +380,7 @@ impl<'a, 'tcx> QueryNormalizer<'a, 'tcx> { if res != term.to_term(tcx) && (res.has_type_flags(ty::TypeFlags::HAS_CT_PROJECTION) || matches!( - term.kind(tcx), + term.kind, ty::AliasTermKind::FreeTy { .. } | ty::AliasTermKind::FreeConst { .. } )) { diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index 16d5c20c87fe2..96586713aed6f 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -86,7 +86,7 @@ fn normalize_canonicalized_free_alias<'tcx>( }, ); ocx.register_obligations(obligations); - let normalized_term = if goal.kind(tcx).is_type() { + let normalized_term = if goal.kind.is_type() { tcx.type_of(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() } else { tcx.const_of_item(goal.def_id()).instantiate(tcx, goal.args).skip_norm_wip().into() diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index 59c5f69463b38..176c05a3fa54e 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -734,8 +734,8 @@ impl AliasTerm { Self::new_from_args(interner, kind, args) } - pub fn expect_ty(self, interner: I) -> ty::AliasTy { - let kind = match self.kind(interner) { + pub fn expect_ty(self) -> ty::AliasTy { + let kind = match self.kind { AliasTermKind::ProjectionTy { def_id } => AliasTyKind::Projection { def_id }, AliasTermKind::InherentTy { def_id } => AliasTyKind::Inherent { def_id }, AliasTermKind::OpaqueTy { def_id } => AliasTyKind::Opaque { def_id }, @@ -750,8 +750,8 @@ impl AliasTerm { ty::AliasTy { kind, args: self.args, _use_alias_ty_new_instead: () } } - pub fn expect_ct(self, interner: I) -> ty::UnevaluatedConst { - let def = match self.kind(interner) { + pub fn expect_ct(self) -> ty::UnevaluatedConst { + let kind = match self.kind { AliasTermKind::InherentConst { def_id } => UnevaluatedConstKind::Inherent { def_id }, AliasTermKind::FreeConst { def_id } => UnevaluatedConstKind::Free { def_id }, AliasTermKind::AnonConst { def_id } => UnevaluatedConstKind::Anon { def_id }, @@ -765,12 +765,7 @@ impl AliasTerm { panic!("Cannot turn `{}` into `UnevaluatedConst`", kind.descr()) } }; - ty::UnevaluatedConst::new(interner, def, self.args) - } - - // FIXME: remove this function (access the field instead) - pub fn kind(self, _interner: I) -> AliasTermKind { - self.kind + ty::UnevaluatedConst { kind, args: self.args, _use_unevaluated_const_new_instead: () } } // FIXME: replace with explicit matches @@ -789,7 +784,7 @@ impl AliasTerm { ) .into() }; - match self.kind(interner) { + match self.kind { AliasTermKind::FreeConst { def_id } => { unevaluated_const(UnevaluatedConstKind::Free { def_id }) } @@ -894,7 +889,7 @@ impl AliasTerm { interner: I, ) -> I::GenericArgs { debug_assert!(matches!( - self.kind(interner), + self.kind, AliasTermKind::InherentTy { .. } | AliasTermKind::InherentConst { .. } )); interner.mk_args_from_iter(impl_args.iter().chain(self.args.iter().skip(1))) diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index d1c9a5c8fd903..e1df344d896d8 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -239,7 +239,7 @@ impl Relate for ty::AliasTerm { if a.def_id() != b.def_id() { Err(TypeError::ProjectionMismatched(ExpectedFound::new(a.def_id(), b.def_id()))) } else { - let args = match a.kind(relation.cx()) { + let args = match a.kind { ty::AliasTermKind::OpaqueTy { .. } => relate_args_with_variances( relation, relation.cx().variances_of(a.def_id()), diff --git a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs index 40db810c12840..f8fe6aa15d324 100644 --- a/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/src/tools/clippy/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -433,7 +433,7 @@ fn replace_types<'tcx>( let projection = projection_predicate .projection_term .with_replaced_self_ty(cx.tcx, new_ty) - .expect_ty(cx.tcx) + .expect_ty() .to_ty(cx.tcx); if let Ok(projected_ty) = cx From 7092ebf8624c2a31684b4bb04e20a640c6c47497 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 24 May 2026 18:49:41 +0000 Subject: [PATCH 07/26] Integrate `field_names` inside `field_tys`. We already have a vector of `CoroutineSavedTy`, no need to have a separate one just for debuginfo. --- .../src/debuginfo/metadata/enums/mod.rs | 3 ++- compiler/rustc_middle/src/mir/pretty.rs | 17 +++++--------- compiler/rustc_middle/src/mir/query.rs | 5 ++-- compiler/rustc_middle/src/ty/mod.rs | 1 - compiler/rustc_mir_transform/src/coroutine.rs | 23 +++++++++---------- compiler/rustc_ty_utils/src/layout.rs | 2 +- 6 files changed, 22 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs index 86060f068eaf0..3a1b4fb91faa7 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata/enums/mod.rs @@ -328,7 +328,8 @@ fn build_coroutine_variant_struct_type_di_node<'ll, 'tcx>( .map(|field_index| { let coroutine_saved_local = coroutine_layout.variant_fields[variant_index] [FieldIdx::from_usize(field_index)]; - let field_name_maybe = coroutine_layout.field_names[coroutine_saved_local]; + let field_name_maybe = + coroutine_layout.field_tys[coroutine_saved_local].debuginfo_name; let field_name = field_name_maybe .as_ref() .map(|s| Cow::from(s.as_str())) diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index f93c4b0d24f80..38782c4eb8d57 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -429,9 +429,9 @@ fn write_scope_tree( // Coroutine debuginfo. if let Some(layout) = body.coroutine_layout_raw() { - for (field, name) in layout.field_names.iter_enumerated() { - let source_info = layout.field_tys[field].source_info; - if let Some(name) = name + for (field, field_decl) in layout.field_tys.iter_enumerated() { + let source_info = field_decl.source_info; + if let Some(name) = field_decl.debuginfo_name && source_info.scope == parent { let indented_debug_info = @@ -559,17 +559,12 @@ fn write_coroutine_layout<'tcx>( w: &mut dyn io::Write, options: PrettyPrintMirOptions, ) -> io::Result<()> { - let CoroutineLayout { - field_tys, - field_names: _, // Dumped in scope tree with debug info. - variant_fields, - variant_source_info, - storage_conflicts, - } = layout; + let CoroutineLayout { field_tys, variant_fields, variant_source_info, storage_conflicts } = + layout; writeln!(w, "{INDENT}coroutine layout {{")?; - for (field, CoroutineSavedTy { ty, source_info, ignore_for_traits }) in + for (field, CoroutineSavedTy { ty, source_info, ignore_for_traits, debuginfo_name: _ }) in field_tys.iter_enumerated() { let ignore_for_traits = if *ignore_for_traits { " (ignored for traits)" } else { "" }; diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index f8607cafcfa6e..616b1719359f1 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -27,6 +27,8 @@ pub struct CoroutineSavedTy<'tcx> { pub source_info: SourceInfo, /// Whether the local should be ignored for trait bound computations. pub ignore_for_traits: bool, + /// The name for debuginfo. + pub debuginfo_name: Option, } /// The layout of coroutine state. @@ -36,9 +38,6 @@ pub struct CoroutineLayout<'tcx> { /// The type of every local stored inside the coroutine. pub field_tys: IndexVec>, - /// The name for debuginfo. - pub field_names: IndexVec>, - /// Which of the above fields are in each variant. Note that one field may /// be stored in multiple variants. pub variant_fields: IndexVec>, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6df1ed82d260a..bfb9869383b56 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1929,7 +1929,6 @@ impl<'tcx> TyCtxt<'tcx> { iter::repeat(source_info).take(CoroutineArgs::RESERVED_VARIANTS).collect(); let proxy_layout = CoroutineLayout { field_tys: [].into(), - field_names: [].into(), variant_fields, variant_source_info, storage_conflicts: BitMatrix::new(0, 0), diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 9047055bc2570..27410a396b971 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -1001,8 +1001,13 @@ fn compute_layout<'tcx>( ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true, _ => false, }; - let decl = - CoroutineSavedTy { ty: decl.ty, source_info: decl.source_info, ignore_for_traits }; + let decl = CoroutineSavedTy { + ty: decl.ty, + source_info: decl.source_info, + ignore_for_traits, + // Will be set later when walking debuginfo. + debuginfo_name: None, + }; debug!(?decl); tys.push(decl); @@ -1046,7 +1051,6 @@ fn compute_layout<'tcx>( debug!(?variant_fields); debug!(?storage_conflicts); - let mut field_names = IndexVec::from_elem(None, &tys); for var in &body.var_debug_info { let VarDebugInfoContents::Place(place) = &var.value else { continue }; let Some(local) = place.as_local() else { continue }; @@ -1054,17 +1058,12 @@ fn compute_layout<'tcx>( continue; }; - let saved_local = variant_fields[variant][field]; - field_names.get_or_insert_with(saved_local, || var.name); + let saved_local: CoroutineSavedLocal = variant_fields[variant][field]; + tys[saved_local].debuginfo_name.get_or_insert(var.name); } - let layout = CoroutineLayout { - field_tys: tys, - field_names, - variant_fields, - variant_source_info, - storage_conflicts, - }; + let layout = + CoroutineLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts }; debug!(?remap); debug!(?layout); debug!(?storage_liveness); diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 9cc15a374ff70..85b6534f095a7 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -968,7 +968,7 @@ fn variant_info_for_coroutine<'tcx>( .iter() .enumerate() .map(|(field_idx, local)| { - let field_name = coroutine.field_names[*local]; + let field_name = coroutine.field_tys[*local].debuginfo_name; let field_layout = variant_layout.field(cx, field_idx); let offset = variant_layout.fields.offset(field_idx); // The struct is as large as the last field's end From c8ce74aa2619b3f9e74aebbc8aebe24c9352f804 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Tue, 2 Jun 2026 08:29:39 +0000 Subject: [PATCH 08/26] Simplify `compute_layout`. Avoid complicated loops just for an optimization. --- compiler/rustc_mir_transform/src/coroutine.rs | 70 ++++++++++--------- 1 file changed, 36 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 27410a396b971..7a5375f1c14b5 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -978,40 +978,39 @@ fn compute_layout<'tcx>( storage_liveness, } = liveness; - // Gather live local types and their indices. - let mut locals = IndexVec::::with_capacity(saved_locals.domain_size()); - let mut tys = IndexVec::::with_capacity(saved_locals.domain_size()); - for (saved_local, local) in saved_locals.iter_enumerated() { - debug!("coroutine saved local {:?} => {:?}", saved_local, local); - - locals.push(local); - let decl = &body.local_decls[local]; - debug!(?decl); - - // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared - // the information. This is alright, since `ignore_for_traits` is only relevant when - // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer - // default. - let ignore_for_traits = match decl.local_info { - // Do not include raw pointers created from accessing `static` items, as those could - // well be re-created by another access to the same static. - ClearCrossCrate::Set(LocalInfo::StaticRef { is_thread_local, .. }) => !is_thread_local, - // Fake borrows are only read by fake reads, so do not have any reality in - // post-analysis MIR. - ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true, - _ => false, - }; - let decl = CoroutineSavedTy { - ty: decl.ty, - source_info: decl.source_info, - ignore_for_traits, - // Will be set later when walking debuginfo. - debuginfo_name: None, - }; - debug!(?decl); + // Gather live local types. + let mut tys: IndexVec> = saved_locals + .iter_enumerated() + .map(|(saved_local, local)| { + debug!("coroutine saved local {:?} => {:?}", saved_local, local); + + let decl = &body.local_decls[local]; + + // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared + // the information. This is alright, since `ignore_for_traits` is only relevant when + // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer + // default. + let ignore_for_traits = match decl.local_info { + // Do not include raw pointers created from accessing `static` items, as those could + // well be re-created by another access to the same static. + ClearCrossCrate::Set(LocalInfo::StaticRef { is_thread_local, .. }) => { + !is_thread_local + } + // Fake borrows are only read by fake reads, so do not have any reality in + // post-analysis MIR. + ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true, + _ => false, + }; - tys.push(decl); - } + CoroutineSavedTy { + ty: decl.ty, + source_info: decl.source_info, + ignore_for_traits, + // Will be set later when walking debuginfo. + debuginfo_name: None, + } + }) + .collect(); // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. // In debuginfo, these will correspond to the beginning (UNRESUMED) or end @@ -1026,6 +1025,9 @@ fn compute_layout<'tcx>( SourceInfo::outermost(body_span.shrink_to_hi()), ]); + // Simple map from new to old indices to avoid repeatedly counting bits. + let reverse_local_map: IndexVec = saved_locals.iter().collect(); + // Build the coroutine variant field list. // Create a map from local indices to coroutine struct indices. let mut variant_fields: IndexVec = IndexVec::from_elem_n( @@ -1044,7 +1046,7 @@ fn compute_layout<'tcx>( // just use the first one here. That's fine; fields do not move // around inside coroutines, so it doesn't matter which variant // index we access them by. - remap[locals[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); + remap[reverse_local_map[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); } variant_source_info.push(source_info_at_suspension_point); } From 2a2e4c9b7e155c695bd76a63435c0e2f1c61dad9 Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 31 May 2026 08:32:56 +0000 Subject: [PATCH 09/26] Split coroutine layout computation to its own file. `coroutine.rs` was getting too large, and mixing MIR analyses for trait solving and runtime transformations. --- compiler/rustc_mir_transform/src/coroutine.rs | 701 +---------------- .../src/coroutine/layout.rs | 722 ++++++++++++++++++ 2 files changed, 731 insertions(+), 692 deletions(-) create mode 100644 compiler/rustc_mir_transform/src/coroutine/layout.rs diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs index 7a5375f1c14b5..235654fd3454e 100644 --- a/compiler/rustc_mir_transform/src/coroutine.rs +++ b/compiler/rustc_mir_transform/src/coroutine.rs @@ -52,7 +52,7 @@ mod by_move_body; mod drop; -use std::ops; +mod layout; pub(super) use by_move_body::coroutine_by_move_body_def_id; use drop::{ @@ -60,36 +60,25 @@ use drop::{ create_coroutine_drop_shim_proxy_async, elaborate_coroutine_drops, has_async_drops, insert_clean_drop, }; -use itertools::izip; +pub(super) use layout::mir_coroutine_witnesses; +use layout::{CoroutineSavedLocals, compute_layout, locals_live_across_suspend_points}; use rustc_abi::{FieldIdx, VariantIdx}; -use rustc_data_structures::fx::FxHashSet; -use rustc_errors::pluralize; use rustc_hir::lang_items::LangItem; -use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind, find_attr}; +use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_index::bit_set::{BitMatrix, DenseBitSet, GrowableBitSet}; use rustc_index::{Idx, IndexVec, indexvec}; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; use rustc_middle::ty::{ - self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, TypingMode, + self, CoroutineArgs, CoroutineArgsExt, GenericArgsRef, InstanceKind, Ty, TyCtxt, }; use rustc_middle::{bug, span_bug}; -use rustc_mir_dataflow::impls::{ - MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, - always_storage_live_locals, -}; -use rustc_mir_dataflow::{ - Analysis, Results, ResultsCursor, ResultsVisitor, visit_reachable_results, -}; -use rustc_span::Span; -use rustc_span::def_id::{DefId, LocalDefId}; -use rustc_trait_selection::error_reporting::InferCtxtErrorExt; -use rustc_trait_selection::infer::TyCtxtInferExt as _; -use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; -use tracing::{debug, instrument, trace}; +use rustc_mir_dataflow::impls::always_storage_live_locals; +use rustc_span::def_id::DefId; +use tracing::{debug, instrument}; use crate::deref_separator::deref_finder; -use crate::{abort_unwinding_calls, errors, pass_manager as pm, simplify}; +use crate::{abort_unwinding_calls, pass_manager as pm, simplify}; pub(super) struct StateTransform; @@ -673,406 +662,6 @@ fn transform_gen_context<'tcx>(body: &mut Body<'tcx>) { body.arg_count = 1; } -struct LivenessInfo { - /// Which locals are live across any suspension point. - saved_locals: CoroutineSavedLocals, - - /// The set of saved locals live at each suspension point. - live_locals_at_suspension_points: Vec>, - - /// Parallel vec to the above with SourceInfo for each yield terminator. - source_info_at_suspension_points: Vec, - - /// For every saved local, the set of other saved locals that are - /// storage-live at the same time as this local. We cannot overlap locals in - /// the layout which have conflicting storage. - storage_conflicts: BitMatrix, - - /// For every suspending block, the locals which are storage-live across - /// that suspension point. - storage_liveness: IndexVec>>, -} - -/// Computes which locals have to be stored in the state-machine for the -/// given coroutine. -/// -/// The basic idea is as follows: -/// - a local is live until we encounter a `StorageDead` statement. In -/// case none exist, the local is considered to be always live. -/// - a local has to be stored if it is either directly used after the -/// the suspend point, or if it is live and has been previously borrowed. -#[tracing::instrument(level = "trace", skip(tcx, body))] -fn locals_live_across_suspend_points<'tcx>( - tcx: TyCtxt<'tcx>, - body: &Body<'tcx>, - always_live_locals: &DenseBitSet, - movable: bool, -) -> LivenessInfo { - // Calculate when MIR locals have live storage. This gives us an upper bound of their - // lifetimes. - let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)) - .iterate_to_fixpoint(tcx, body, None) - .into_results_cursor(body); - - // Calculate the MIR locals that have been previously borrowed (even if they are still active). - let borrowed_locals = MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")); - let borrowed_locals_cursor1 = ResultsCursor::new_borrowing(body, &borrowed_locals); - let mut borrowed_locals_cursor2 = ResultsCursor::new_borrowing(body, &borrowed_locals); - - // Calculate the MIR locals that we need to keep storage around for. - let requires_storage = - MaybeRequiresStorage::new(borrowed_locals_cursor1).iterate_to_fixpoint(tcx, body, None); - let mut requires_storage_cursor = ResultsCursor::new_borrowing(body, &requires_storage); - - // Calculate the liveness of MIR locals ignoring borrows. - let mut liveness = - MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")).into_results_cursor(body); - - let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks); - let mut live_locals_at_suspension_points = Vec::new(); - let mut source_info_at_suspension_points = Vec::new(); - let mut live_locals_at_any_suspension_point = DenseBitSet::new_empty(body.local_decls.len()); - - for (block, data) in body.basic_blocks.iter_enumerated() { - let TerminatorKind::Yield { .. } = data.terminator().kind else { continue }; - - let loc = Location { block, statement_index: data.statements.len() }; - - liveness.seek_to_block_end(block); - let mut live_locals = liveness.get().clone(); - - if !movable { - // The `liveness` variable contains the liveness of MIR locals ignoring borrows. - // This is correct for movable coroutines since borrows cannot live across - // suspension points. However for immovable coroutines we need to account for - // borrows, so we conservatively assume that all borrowed locals are live until - // we find a StorageDead statement referencing the locals. - // To do this we just union our `liveness` result with `borrowed_locals`, which - // contains all the locals which has been borrowed before this suspension point. - // If a borrow is converted to a raw reference, we must also assume that it lives - // forever. Note that the final liveness is still bounded by the storage liveness - // of the local, which happens using the `intersect` operation below. - borrowed_locals_cursor2.seek_before_primary_effect(loc); - live_locals.union(borrowed_locals_cursor2.get()); - } - - // Store the storage liveness for later use so we can restore the state - // after a suspension point - storage_live.seek_before_primary_effect(loc); - storage_liveness_map[block] = Some(storage_live.get().clone()); - - // Locals live are live at this point only if they are used across - // suspension points (the `liveness` variable) - // and their storage is required (the `storage_required` variable) - requires_storage_cursor.seek_before_primary_effect(loc); - live_locals.intersect(requires_storage_cursor.get()); - - // The coroutine argument is ignored. - live_locals.remove(SELF_ARG); - - debug!(?loc, ?live_locals); - - // Add the locals live at this suspension point to the set of locals which live across - // any suspension points - live_locals_at_any_suspension_point.union(&live_locals); - - live_locals_at_suspension_points.push(live_locals); - source_info_at_suspension_points.push(data.terminator().source_info); - } - - debug!(?live_locals_at_any_suspension_point); - let saved_locals = CoroutineSavedLocals(live_locals_at_any_suspension_point); - - // Renumber our liveness_map bitsets to include only the locals we are - // saving. - let live_locals_at_suspension_points = live_locals_at_suspension_points - .iter() - .map(|live_here| saved_locals.renumber_bitset(live_here)) - .collect(); - - let storage_conflicts = compute_storage_conflicts( - body, - &saved_locals, - always_live_locals.clone(), - &requires_storage, - ); - - LivenessInfo { - saved_locals, - live_locals_at_suspension_points, - source_info_at_suspension_points, - storage_conflicts, - storage_liveness: storage_liveness_map, - } -} - -/// The set of `Local`s that must be saved across yield points. -/// -/// `CoroutineSavedLocal` is indexed in terms of the elements in this set; -/// i.e. `CoroutineSavedLocal::new(1)` corresponds to the second local -/// included in this set. -struct CoroutineSavedLocals(DenseBitSet); - -impl CoroutineSavedLocals { - /// Returns an iterator over each `CoroutineSavedLocal` along with the `Local` it corresponds - /// to. - fn iter_enumerated(&self) -> impl '_ + Iterator { - self.iter().enumerate().map(|(i, l)| (CoroutineSavedLocal::from(i), l)) - } - - /// Transforms a `DenseBitSet` that contains only locals saved across yield points to the - /// equivalent `DenseBitSet`. - fn renumber_bitset(&self, input: &DenseBitSet) -> DenseBitSet { - assert!(self.superset(input), "{:?} not a superset of {:?}", self.0, input); - let mut out = DenseBitSet::new_empty(self.count()); - for (saved_local, local) in self.iter_enumerated() { - if input.contains(local) { - out.insert(saved_local); - } - } - out - } - - fn get(&self, local: Local) -> Option { - if !self.contains(local) { - return None; - } - - let idx = self.iter().take_while(|&l| l < local).count(); - Some(CoroutineSavedLocal::new(idx)) - } -} - -impl ops::Deref for CoroutineSavedLocals { - type Target = DenseBitSet; - - fn deref(&self) -> &Self::Target { - &self.0 - } -} - -/// For every saved local, looks for which locals are StorageLive at the same -/// time. Generates a bitset for every local of all the other locals that may be -/// StorageLive simultaneously with that local. This is used in the layout -/// computation; see `CoroutineLayout` for more. -fn compute_storage_conflicts<'mir, 'tcx>( - body: &'mir Body<'tcx>, - saved_locals: &'mir CoroutineSavedLocals, - always_live_locals: DenseBitSet, - results: &Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, -) -> BitMatrix { - assert_eq!(body.local_decls.len(), saved_locals.domain_size()); - - debug!("compute_storage_conflicts({:?})", body.span); - debug!("always_live = {:?}", always_live_locals); - - // Locals that are always live or ones that need to be stored across - // suspension points are not eligible for overlap. - let mut ineligible_locals = always_live_locals; - ineligible_locals.intersect(&**saved_locals); - - // Compute the storage conflicts for all eligible locals. - let mut visitor = StorageConflictVisitor { - body, - saved_locals, - local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), - eligible_storage_live: DenseBitSet::new_empty(body.local_decls.len()), - }; - - visit_reachable_results(body, results, &mut visitor); - - let local_conflicts = visitor.local_conflicts; - - // Compress the matrix using only stored locals (Local -> CoroutineSavedLocal). - // - // NOTE: Today we store a full conflict bitset for every local. Technically - // this is twice as many bits as we need, since the relation is symmetric. - // However, in practice these bitsets are not usually large. The layout code - // also needs to keep track of how many conflicts each local has, so it's - // simpler to keep it this way for now. - let mut storage_conflicts = BitMatrix::new(saved_locals.count(), saved_locals.count()); - for (saved_local_a, local_a) in saved_locals.iter_enumerated() { - if ineligible_locals.contains(local_a) { - // Conflicts with everything. - storage_conflicts.insert_all_into_row(saved_local_a); - } else { - // Keep overlap information only for stored locals. - for (saved_local_b, local_b) in saved_locals.iter_enumerated() { - if local_conflicts.contains(local_a, local_b) { - storage_conflicts.insert(saved_local_a, saved_local_b); - } - } - } - } - storage_conflicts -} - -struct StorageConflictVisitor<'a, 'tcx> { - body: &'a Body<'tcx>, - saved_locals: &'a CoroutineSavedLocals, - // FIXME(tmandry): Consider using sparse bitsets here once we have good - // benchmarks for coroutines. - local_conflicts: BitMatrix, - // We keep this bitset as a buffer to avoid reallocating memory. - eligible_storage_live: DenseBitSet, -} - -impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage<'a, 'tcx>> - for StorageConflictVisitor<'a, 'tcx> -{ - fn visit_after_early_statement_effect( - &mut self, - _analysis: &MaybeRequiresStorage<'a, 'tcx>, - state: &DenseBitSet, - _statement: &Statement<'tcx>, - loc: Location, - ) { - self.apply_state(state, loc); - } - - fn visit_after_early_terminator_effect( - &mut self, - _analysis: &MaybeRequiresStorage<'a, 'tcx>, - state: &DenseBitSet, - _terminator: &Terminator<'tcx>, - loc: Location, - ) { - self.apply_state(state, loc); - } -} - -impl StorageConflictVisitor<'_, '_> { - fn apply_state(&mut self, state: &DenseBitSet, loc: Location) { - // Ignore unreachable blocks. - if let TerminatorKind::Unreachable = self.body.basic_blocks[loc.block].terminator().kind { - return; - } - - self.eligible_storage_live.clone_from(state); - self.eligible_storage_live.intersect(&**self.saved_locals); - - for local in self.eligible_storage_live.iter() { - self.local_conflicts.union_row_with(&self.eligible_storage_live, local); - } - - if self.eligible_storage_live.count() > 1 { - trace!("at {:?}, eligible_storage_live={:?}", loc, self.eligible_storage_live); - } - } -} - -#[tracing::instrument(level = "trace", skip(liveness, body))] -fn compute_layout<'tcx>( - liveness: LivenessInfo, - body: &Body<'tcx>, -) -> ( - IndexVec, VariantIdx, FieldIdx)>>, - CoroutineLayout<'tcx>, - IndexVec>>, -) { - let LivenessInfo { - saved_locals, - live_locals_at_suspension_points, - source_info_at_suspension_points, - storage_conflicts, - storage_liveness, - } = liveness; - - // Gather live local types. - let mut tys: IndexVec> = saved_locals - .iter_enumerated() - .map(|(saved_local, local)| { - debug!("coroutine saved local {:?} => {:?}", saved_local, local); - - let decl = &body.local_decls[local]; - - // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared - // the information. This is alright, since `ignore_for_traits` is only relevant when - // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer - // default. - let ignore_for_traits = match decl.local_info { - // Do not include raw pointers created from accessing `static` items, as those could - // well be re-created by another access to the same static. - ClearCrossCrate::Set(LocalInfo::StaticRef { is_thread_local, .. }) => { - !is_thread_local - } - // Fake borrows are only read by fake reads, so do not have any reality in - // post-analysis MIR. - ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true, - _ => false, - }; - - CoroutineSavedTy { - ty: decl.ty, - source_info: decl.source_info, - ignore_for_traits, - // Will be set later when walking debuginfo. - debuginfo_name: None, - } - }) - .collect(); - - // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. - // In debuginfo, these will correspond to the beginning (UNRESUMED) or end - // (RETURNED, POISONED) of the function. - let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span; - let mut variant_source_info: IndexVec = IndexVec::with_capacity( - CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), - ); - variant_source_info.extend([ - SourceInfo::outermost(body_span.shrink_to_lo()), - SourceInfo::outermost(body_span.shrink_to_hi()), - SourceInfo::outermost(body_span.shrink_to_hi()), - ]); - - // Simple map from new to old indices to avoid repeatedly counting bits. - let reverse_local_map: IndexVec = saved_locals.iter().collect(); - - // Build the coroutine variant field list. - // Create a map from local indices to coroutine struct indices. - let mut variant_fields: IndexVec = IndexVec::from_elem_n( - IndexVec::new(), - CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), - ); - let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size()); - for (live_locals, &source_info_at_suspension_point, (variant_index, fields)) in izip!( - &live_locals_at_suspension_points, - &source_info_at_suspension_points, - variant_fields.iter_enumerated_mut().skip(CoroutineArgs::RESERVED_VARIANTS) - ) { - *fields = live_locals.iter().collect(); - for (idx, &saved_local) in fields.iter_enumerated() { - // Note that if a field is included in multiple variants, we will - // just use the first one here. That's fine; fields do not move - // around inside coroutines, so it doesn't matter which variant - // index we access them by. - remap[reverse_local_map[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); - } - variant_source_info.push(source_info_at_suspension_point); - } - debug!(?variant_fields); - debug!(?storage_conflicts); - - for var in &body.var_debug_info { - let VarDebugInfoContents::Place(place) = &var.value else { continue }; - let Some(local) = place.as_local() else { continue }; - let Some(&Some((_, variant, field))) = remap.get(local) else { - continue; - }; - - let saved_local: CoroutineSavedLocal = variant_fields[variant][field]; - tys[saved_local].debuginfo_name.get_or_insert(var.name); - } - - let layout = - CoroutineLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts }; - debug!(?remap); - debug!(?layout); - debug!(?storage_liveness); - - (remap, layout, storage_liveness) -} - /// Replaces the entry point of `body` with a block that switches on the coroutine discriminant and /// dispatches to blocks according to `cases`. /// @@ -1375,79 +964,6 @@ fn create_cases<'tcx>( .collect() } -#[instrument(level = "debug", skip(tcx), ret)] -pub(crate) fn mir_coroutine_witnesses<'tcx>( - tcx: TyCtxt<'tcx>, - def_id: LocalDefId, -) -> Option> { - let (body, _) = tcx.mir_promoted(def_id); - let body = body.borrow(); - let body = &*body; - - // The first argument is the coroutine type passed by value - let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; - - let movable = match *coroutine_ty.kind() { - ty::Coroutine(def_id, _) => tcx.coroutine_movability(def_id) == hir::Movability::Movable, - ty::Error(_) => return None, - _ => span_bug!(body.span, "unexpected coroutine type {}", coroutine_ty), - }; - - // The witness simply contains all locals live across suspend points. - - let always_live_locals = always_storage_live_locals(body); - let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); - - // Extract locals which are live across suspension point into `layout` - // `remap` gives a mapping from local indices onto coroutine struct indices - // `storage_liveness` tells us which locals have live storage at suspension points - let (_, coroutine_layout, _) = compute_layout(liveness_info, body); - - check_suspend_tys(tcx, &coroutine_layout, body); - check_field_tys_sized(tcx, &coroutine_layout, def_id); - - Some(coroutine_layout) -} - -fn check_field_tys_sized<'tcx>( - tcx: TyCtxt<'tcx>, - coroutine_layout: &CoroutineLayout<'tcx>, - def_id: LocalDefId, -) { - // No need to check if unsized_fn_params is disabled, - // since we will error during typeck. - if !tcx.features().unsized_fn_params() { - return; - } - - // FIXME(#132279): @lcnr believes that we may want to support coroutines - // whose `Sized`-ness relies on the hidden types of opaques defined by the - // parent function. In this case we'd have to be able to reveal only these - // opaques here. - let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); - let param_env = tcx.param_env(def_id); - - let ocx = ObligationCtxt::new_with_diagnostics(&infcx); - for field_ty in &coroutine_layout.field_tys { - ocx.register_bound( - ObligationCause::new( - field_ty.source_info.span, - def_id, - ObligationCauseCode::SizedCoroutineInterior(def_id), - ), - param_env, - field_ty.ty, - tcx.require_lang_item(hir::LangItem::Sized, field_ty.source_info.span), - ); - } - - let errors = ocx.evaluate_obligations_error_on_ambiguity(); - debug!(?errors); - if !errors.is_empty() { - infcx.err_ctxt().report_fulfillment_errors(errors); - } -} - impl<'tcx> crate::MirPass<'tcx> for StateTransform { #[instrument(level = "debug", skip(self, tcx, body), ret)] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { @@ -1773,202 +1289,3 @@ impl<'tcx> Visitor<'tcx> for EnsureCoroutineFieldAssignmentsNeverAlias<'_> { } } } - -fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &CoroutineLayout<'tcx>, body: &Body<'tcx>) { - let mut linted_tys = FxHashSet::default(); - - for (variant, yield_source_info) in - layout.variant_fields.iter().zip(&layout.variant_source_info) - { - debug!(?variant); - for &local in variant { - let decl = &layout.field_tys[local]; - debug!(?decl); - - if !decl.ignore_for_traits && linted_tys.insert(decl.ty) { - let Some(hir_id) = decl.source_info.scope.lint_root(&body.source_scopes) else { - continue; - }; - - check_must_not_suspend_ty( - tcx, - decl.ty, - hir_id, - SuspendCheckData { - source_span: decl.source_info.span, - yield_span: yield_source_info.span, - plural_len: 1, - ..Default::default() - }, - ); - } - } - } -} - -#[derive(Default)] -struct SuspendCheckData<'a> { - source_span: Span, - yield_span: Span, - descr_pre: &'a str, - descr_post: &'a str, - plural_len: usize, -} - -// Returns whether it emitted a diagnostic or not -// Note that this fn and the proceeding one are based on the code -// for creating must_use diagnostics -// -// Note that this technique was chosen over things like a `Suspend` marker trait -// as it is simpler and has precedent in the compiler -fn check_must_not_suspend_ty<'tcx>( - tcx: TyCtxt<'tcx>, - ty: Ty<'tcx>, - hir_id: hir::HirId, - data: SuspendCheckData<'_>, -) -> bool { - if ty.is_unit() { - return false; - } - - let plural_suffix = pluralize!(data.plural_len); - - debug!("Checking must_not_suspend for {}", ty); - - match *ty.kind() { - ty::Adt(_, args) if ty.is_box() => { - let boxed_ty = args.type_at(0); - let allocator_ty = args.type_at(1); - check_must_not_suspend_ty( - tcx, - boxed_ty, - hir_id, - SuspendCheckData { descr_pre: &format!("{}boxed ", data.descr_pre), ..data }, - ) || check_must_not_suspend_ty( - tcx, - allocator_ty, - hir_id, - SuspendCheckData { descr_pre: &format!("{}allocator ", data.descr_pre), ..data }, - ) - } - // FIXME(sized_hierarchy): This should be replaced with a requirement that types in - // coroutines implement `const Sized`. Scalable vectors are temporarily `Sized` while - // `feature(sized_hierarchy)` is not fully implemented, but in practice are - // non-`const Sized` and so do not have a known size at compilation time. Layout computation - // for a coroutine containing scalable vectors would be incorrect. - ty::Adt(def, _) if def.repr().scalable() => { - tcx.dcx() - .span_err(data.source_span, "scalable vectors cannot be held over await points"); - true - } - ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data), - // FIXME: support adding the attribute to TAITs - ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: def }, .. }) => { - let mut has_emitted = false; - for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() { - // We only look at the `DefId`, so it is safe to skip the binder here. - if let ty::ClauseKind::Trait(ref poly_trait_predicate) = - predicate.kind().skip_binder() - { - let def_id = poly_trait_predicate.trait_ref.def_id; - let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); - if check_must_not_suspend_def( - tcx, - def_id, - hir_id, - SuspendCheckData { descr_pre, ..data }, - ) { - has_emitted = true; - break; - } - } - } - has_emitted - } - ty::Dynamic(binder, _) => { - let mut has_emitted = false; - for predicate in binder.iter() { - if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { - let def_id = trait_ref.def_id; - let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post); - if check_must_not_suspend_def( - tcx, - def_id, - hir_id, - SuspendCheckData { descr_post, ..data }, - ) { - has_emitted = true; - break; - } - } - } - has_emitted - } - ty::Tuple(fields) => { - let mut has_emitted = false; - for (i, ty) in fields.iter().enumerate() { - let descr_post = &format!(" in tuple element {i}"); - if check_must_not_suspend_ty( - tcx, - ty, - hir_id, - SuspendCheckData { descr_post, ..data }, - ) { - has_emitted = true; - } - } - has_emitted - } - ty::Array(ty, len) => { - let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix); - check_must_not_suspend_ty( - tcx, - ty, - hir_id, - SuspendCheckData { - descr_pre, - // FIXME(must_not_suspend): This is wrong. We should handle printing unevaluated consts. - plural_len: len.try_to_target_usize(tcx).unwrap_or(0) as usize + 1, - ..data - }, - ) - } - // If drop tracking is enabled, we want to look through references, since the referent - // may not be considered live across the await point. - ty::Ref(_region, ty, _mutability) => { - let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix); - check_must_not_suspend_ty(tcx, ty, hir_id, SuspendCheckData { descr_pre, ..data }) - } - _ => false, - } -} - -fn check_must_not_suspend_def( - tcx: TyCtxt<'_>, - def_id: DefId, - hir_id: hir::HirId, - data: SuspendCheckData<'_>, -) -> bool { - if let Some(reason_str) = find_attr!(tcx, def_id, MustNotSupend {reason} => reason) { - let reason = - reason_str.map(|s| errors::MustNotSuspendReason { span: data.source_span, reason: s }); - tcx.emit_node_span_lint( - rustc_session::lint::builtin::MUST_NOT_SUSPEND, - hir_id, - data.source_span, - errors::MustNotSupend { - tcx, - yield_sp: data.yield_span, - reason, - src_sp: data.source_span, - pre: data.descr_pre, - def_id, - post: data.descr_post, - }, - ); - - true - } else { - false - } -} diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs new file mode 100644 index 0000000000000..ed997cc08a888 --- /dev/null +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -0,0 +1,722 @@ +//! Coroutine `StateTransform` inverts control flow in a coroutine from a function with yield +//! points to a state machine. Each yield point corresponds to a state variant, and each variant +//! stores the locals that are needed to continue the coroutine. +//! +//! The state transform creates a `poll` method such that calling the coroutine `f()` is equivalent +//! to: +//! ```rust (ignore) +//! fn initial_mir(state: CoroutineState, mut resume_arg: ResumeTy) { +//! // Repeatedly poll the state machine. +//! loop { +//! match final_mir(&mut state, resume_arg) { +//! CoroutineState::Yielded(yield_value) => resume_arg = yield yield_value, +//! CoroutineState::Complete(return_value) => return return_value, +//! } +//! } +//! } +//! ``` +//! +//! This file compute for each yield point the set of locals that need to be saved in the coroutine +//! state. This is also used for borrowck to compute the set of types held inside that state, which +//! determine trait and region predicates that hold for this state. + +use std::ops; + +use itertools::izip; +use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_data_structures::fx::FxHashSet; +use rustc_errors::pluralize; +use rustc_hir::{self as hir, find_attr}; +use rustc_index::bit_set::{BitMatrix, DenseBitSet}; +use rustc_index::{Idx, IndexVec}; +use rustc_middle::mir::*; +use rustc_middle::span_bug; +use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, Ty, TyCtxt, TypingMode}; +use rustc_mir_dataflow::impls::{ + MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, + always_storage_live_locals, +}; +use rustc_mir_dataflow::{ + Analysis, Results, ResultsCursor, ResultsVisitor, visit_reachable_results, +}; +use rustc_span::Span; +use rustc_span::def_id::{DefId, LocalDefId}; +use rustc_trait_selection::error_reporting::InferCtxtErrorExt; +use rustc_trait_selection::infer::TyCtxtInferExt as _; +use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode, ObligationCtxt}; +use tracing::{debug, instrument, trace}; + +use crate::errors::{MustNotSupend, MustNotSuspendReason}; + +const SELF_ARG: Local = Local::arg(0); + +pub(super) struct LivenessInfo { + /// Which locals are live across any suspension point. + pub(super) saved_locals: CoroutineSavedLocals, + + /// The set of saved locals live at each suspension point. + live_locals_at_suspension_points: Vec>, + + /// Parallel vec to the above with SourceInfo for each yield terminator. + source_info_at_suspension_points: Vec, + + /// For every saved local, the set of other saved locals that are + /// storage-live at the same time as this local. We cannot overlap locals in + /// the layout which have conflicting storage. + pub(super) storage_conflicts: BitMatrix, + + /// For every suspending block, the locals which are storage-live across + /// that suspension point. + storage_liveness: IndexVec>>, +} + +/// Computes which locals have to be stored in the state-machine for the +/// given coroutine. +/// +/// The basic idea is as follows: +/// - a local is live until we encounter a `StorageDead` statement. In +/// case none exist, the local is considered to be always live. +/// - a local has to be stored if it is either directly used after the +/// the suspend point, or if it is live and has been previously borrowed. +#[tracing::instrument(level = "trace", skip(tcx, body))] +pub(super) fn locals_live_across_suspend_points<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + always_live_locals: &DenseBitSet, + movable: bool, +) -> LivenessInfo { + // Calculate when MIR locals have live storage. This gives us an upper bound of their + // lifetimes. + let mut storage_live = MaybeStorageLive::new(std::borrow::Cow::Borrowed(always_live_locals)) + .iterate_to_fixpoint(tcx, body, None) + .into_results_cursor(body); + + // Calculate the MIR locals that have been previously borrowed (even if they are still active). + let borrowed_locals = MaybeBorrowedLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")); + let borrowed_locals_cursor1 = ResultsCursor::new_borrowing(body, &borrowed_locals); + let mut borrowed_locals_cursor2 = ResultsCursor::new_borrowing(body, &borrowed_locals); + + // Calculate the MIR locals that we need to keep storage around for. + let requires_storage = + MaybeRequiresStorage::new(borrowed_locals_cursor1).iterate_to_fixpoint(tcx, body, None); + let mut requires_storage_cursor = ResultsCursor::new_borrowing(body, &requires_storage); + + // Calculate the liveness of MIR locals ignoring borrows. + let mut liveness = + MaybeLiveLocals.iterate_to_fixpoint(tcx, body, Some("coroutine")).into_results_cursor(body); + + let mut storage_liveness_map = IndexVec::from_elem(None, &body.basic_blocks); + let mut live_locals_at_suspension_points = Vec::new(); + let mut source_info_at_suspension_points = Vec::new(); + let mut live_locals_at_any_suspension_point = DenseBitSet::new_empty(body.local_decls.len()); + + for (block, data) in body.basic_blocks.iter_enumerated() { + let TerminatorKind::Yield { .. } = data.terminator().kind else { continue }; + + let loc = Location { block, statement_index: data.statements.len() }; + + liveness.seek_to_block_end(block); + let mut live_locals = liveness.get().clone(); + + if !movable { + // The `liveness` variable contains the liveness of MIR locals ignoring borrows. + // This is correct for movable coroutines since borrows cannot live across + // suspension points. However for immovable coroutines we need to account for + // borrows, so we conservatively assume that all borrowed locals are live until + // we find a StorageDead statement referencing the locals. + // To do this we just union our `liveness` result with `borrowed_locals`, which + // contains all the locals which has been borrowed before this suspension point. + // If a borrow is converted to a raw reference, we must also assume that it lives + // forever. Note that the final liveness is still bounded by the storage liveness + // of the local, which happens using the `intersect` operation below. + borrowed_locals_cursor2.seek_before_primary_effect(loc); + live_locals.union(borrowed_locals_cursor2.get()); + } + + // Store the storage liveness for later use so we can restore the state + // after a suspension point + storage_live.seek_before_primary_effect(loc); + storage_liveness_map[block] = Some(storage_live.get().clone()); + + // Locals live are live at this point only if they are used across + // suspension points (the `liveness` variable) + // and their storage is required (the `storage_required` variable) + requires_storage_cursor.seek_before_primary_effect(loc); + live_locals.intersect(requires_storage_cursor.get()); + + // The coroutine argument is ignored. + live_locals.remove(SELF_ARG); + + debug!(?loc, ?live_locals); + + // Add the locals live at this suspension point to the set of locals which live across + // any suspension points + live_locals_at_any_suspension_point.union(&live_locals); + + live_locals_at_suspension_points.push(live_locals); + source_info_at_suspension_points.push(data.terminator().source_info); + } + + debug!(?live_locals_at_any_suspension_point); + let saved_locals = CoroutineSavedLocals(live_locals_at_any_suspension_point); + + // Renumber our liveness_map bitsets to include only the locals we are + // saving. + let live_locals_at_suspension_points = live_locals_at_suspension_points + .iter() + .map(|live_here| saved_locals.renumber_bitset(live_here)) + .collect(); + + let storage_conflicts = compute_storage_conflicts( + body, + &saved_locals, + always_live_locals.clone(), + &requires_storage, + ); + + LivenessInfo { + saved_locals, + live_locals_at_suspension_points, + source_info_at_suspension_points, + storage_conflicts, + storage_liveness: storage_liveness_map, + } +} + +/// The set of `Local`s that must be saved across yield points. +/// +/// `CoroutineSavedLocal` is indexed in terms of the elements in this set; +/// i.e. `CoroutineSavedLocal::new(1)` corresponds to the second local +/// included in this set. +pub(super) struct CoroutineSavedLocals(DenseBitSet); + +impl CoroutineSavedLocals { + /// Returns an iterator over each `CoroutineSavedLocal` along with the `Local` it corresponds + /// to. + fn iter_enumerated(&self) -> impl '_ + Iterator { + self.iter().enumerate().map(|(i, l)| (CoroutineSavedLocal::from(i), l)) + } + + /// Transforms a `DenseBitSet` that contains only locals saved across yield points to the + /// equivalent `DenseBitSet`. + fn renumber_bitset(&self, input: &DenseBitSet) -> DenseBitSet { + assert!(self.superset(input), "{:?} not a superset of {:?}", self.0, input); + let mut out = DenseBitSet::new_empty(self.count()); + for (saved_local, local) in self.iter_enumerated() { + if input.contains(local) { + out.insert(saved_local); + } + } + out + } + + pub(super) fn get(&self, local: Local) -> Option { + if !self.contains(local) { + return None; + } + + let idx = self.iter().take_while(|&l| l < local).count(); + Some(CoroutineSavedLocal::new(idx)) + } +} + +impl ops::Deref for CoroutineSavedLocals { + type Target = DenseBitSet; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +/// For every saved local, looks for which locals are StorageLive at the same +/// time. Generates a bitset for every local of all the other locals that may be +/// StorageLive simultaneously with that local. This is used in the layout +/// computation; see `CoroutineLayout` for more. +fn compute_storage_conflicts<'mir, 'tcx>( + body: &'mir Body<'tcx>, + saved_locals: &'mir CoroutineSavedLocals, + always_live_locals: DenseBitSet, + results: &Results<'tcx, MaybeRequiresStorage<'mir, 'tcx>>, +) -> BitMatrix { + assert_eq!(body.local_decls.len(), saved_locals.domain_size()); + + debug!("compute_storage_conflicts({:?})", body.span); + debug!("always_live = {:?}", always_live_locals); + + // Locals that are always live or ones that need to be stored across + // suspension points are not eligible for overlap. + let mut ineligible_locals = always_live_locals; + ineligible_locals.intersect(&**saved_locals); + + // Compute the storage conflicts for all eligible locals. + let mut visitor = StorageConflictVisitor { + body, + saved_locals, + local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), + eligible_storage_live: DenseBitSet::new_empty(body.local_decls.len()), + }; + + visit_reachable_results(body, results, &mut visitor); + + let local_conflicts = visitor.local_conflicts; + + // Compress the matrix using only stored locals (Local -> CoroutineSavedLocal). + // + // NOTE: Today we store a full conflict bitset for every local. Technically + // this is twice as many bits as we need, since the relation is symmetric. + // However, in practice these bitsets are not usually large. The layout code + // also needs to keep track of how many conflicts each local has, so it's + // simpler to keep it this way for now. + let mut storage_conflicts = BitMatrix::new(saved_locals.count(), saved_locals.count()); + for (saved_local_a, local_a) in saved_locals.iter_enumerated() { + if ineligible_locals.contains(local_a) { + // Conflicts with everything. + storage_conflicts.insert_all_into_row(saved_local_a); + } else { + // Keep overlap information only for stored locals. + for (saved_local_b, local_b) in saved_locals.iter_enumerated() { + if local_conflicts.contains(local_a, local_b) { + storage_conflicts.insert(saved_local_a, saved_local_b); + } + } + } + } + storage_conflicts +} + +struct StorageConflictVisitor<'a, 'tcx> { + body: &'a Body<'tcx>, + saved_locals: &'a CoroutineSavedLocals, + // FIXME(tmandry): Consider using sparse bitsets here once we have good + // benchmarks for coroutines. + local_conflicts: BitMatrix, + // We keep this bitset as a buffer to avoid reallocating memory. + eligible_storage_live: DenseBitSet, +} + +impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage<'a, 'tcx>> + for StorageConflictVisitor<'a, 'tcx> +{ + fn visit_after_early_statement_effect( + &mut self, + _analysis: &MaybeRequiresStorage<'a, 'tcx>, + state: &DenseBitSet, + _statement: &Statement<'tcx>, + loc: Location, + ) { + self.apply_state(state, loc); + } + + fn visit_after_early_terminator_effect( + &mut self, + _analysis: &MaybeRequiresStorage<'a, 'tcx>, + state: &DenseBitSet, + _terminator: &Terminator<'tcx>, + loc: Location, + ) { + self.apply_state(state, loc); + } +} + +impl StorageConflictVisitor<'_, '_> { + fn apply_state(&mut self, state: &DenseBitSet, loc: Location) { + // Ignore unreachable blocks. + if let TerminatorKind::Unreachable = self.body.basic_blocks[loc.block].terminator().kind { + return; + } + + self.eligible_storage_live.clone_from(state); + self.eligible_storage_live.intersect(&**self.saved_locals); + + for local in self.eligible_storage_live.iter() { + self.local_conflicts.union_row_with(&self.eligible_storage_live, local); + } + + if self.eligible_storage_live.count() > 1 { + trace!("at {:?}, eligible_storage_live={:?}", loc, self.eligible_storage_live); + } + } +} + +#[tracing::instrument(level = "trace", skip(liveness, body))] +pub(super) fn compute_layout<'tcx>( + liveness: LivenessInfo, + body: &Body<'tcx>, +) -> ( + IndexVec, VariantIdx, FieldIdx)>>, + CoroutineLayout<'tcx>, + IndexVec>>, +) { + let LivenessInfo { + saved_locals, + live_locals_at_suspension_points, + source_info_at_suspension_points, + storage_conflicts, + storage_liveness, + } = liveness; + + // Gather live local types. + let mut tys: IndexVec> = saved_locals + .iter_enumerated() + .map(|(saved_local, local)| { + debug!("coroutine saved local {:?} => {:?}", saved_local, local); + + let decl = &body.local_decls[local]; + + // Do not `unwrap_crate_local` here, as post-borrowck cleanup may have already cleared + // the information. This is alright, since `ignore_for_traits` is only relevant when + // this code runs on pre-cleanup MIR, and `ignore_for_traits = false` is the safer + // default. + let ignore_for_traits = match decl.local_info { + // Do not include raw pointers created from accessing `static` items, as those could + // well be re-created by another access to the same static. + ClearCrossCrate::Set(LocalInfo::StaticRef { is_thread_local, .. }) => { + !is_thread_local + } + // Fake borrows are only read by fake reads, so do not have any reality in + // post-analysis MIR. + ClearCrossCrate::Set(LocalInfo::FakeBorrow) => true, + _ => false, + }; + + CoroutineSavedTy { + ty: decl.ty, + source_info: decl.source_info, + ignore_for_traits, + // Will be set later when walking debuginfo. + debuginfo_name: None, + } + }) + .collect(); + + // Leave empty variants for the UNRESUMED, RETURNED, and POISONED states. + // In debuginfo, these will correspond to the beginning (UNRESUMED) or end + // (RETURNED, POISONED) of the function. + let body_span = body.source_scopes[OUTERMOST_SOURCE_SCOPE].span; + let mut variant_source_info: IndexVec = IndexVec::with_capacity( + CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), + ); + variant_source_info.extend([ + SourceInfo::outermost(body_span.shrink_to_lo()), + SourceInfo::outermost(body_span.shrink_to_hi()), + SourceInfo::outermost(body_span.shrink_to_hi()), + ]); + + // Simple map from new to old indices to avoid repeatedly counting bits. + let reverse_local_map: IndexVec = saved_locals.iter().collect(); + + // Build the coroutine variant field list. + // Create a map from local indices to coroutine struct indices. + let mut variant_fields: IndexVec = IndexVec::from_elem_n( + IndexVec::new(), + CoroutineArgs::RESERVED_VARIANTS + live_locals_at_suspension_points.len(), + ); + let mut remap = IndexVec::from_elem_n(None, saved_locals.domain_size()); + for (live_locals, &source_info_at_suspension_point, (variant_index, fields)) in izip!( + &live_locals_at_suspension_points, + &source_info_at_suspension_points, + variant_fields.iter_enumerated_mut().skip(CoroutineArgs::RESERVED_VARIANTS) + ) { + *fields = live_locals.iter().collect(); + for (idx, &saved_local) in fields.iter_enumerated() { + // Note that if a field is included in multiple variants, we will + // just use the first one here. That's fine; fields do not move + // around inside coroutines, so it doesn't matter which variant + // index we access them by. + remap[reverse_local_map[saved_local]] = Some((tys[saved_local].ty, variant_index, idx)); + } + variant_source_info.push(source_info_at_suspension_point); + } + debug!(?variant_fields); + debug!(?storage_conflicts); + + for var in &body.var_debug_info { + let VarDebugInfoContents::Place(place) = &var.value else { continue }; + let Some(local) = place.as_local() else { continue }; + let Some(&Some((_, variant, field))) = remap.get(local) else { + continue; + }; + + let saved_local: CoroutineSavedLocal = variant_fields[variant][field]; + tys[saved_local].debuginfo_name.get_or_insert(var.name); + } + + let layout = + CoroutineLayout { field_tys: tys, variant_fields, variant_source_info, storage_conflicts }; + debug!(?remap); + debug!(?layout); + debug!(?storage_liveness); + + (remap, layout, storage_liveness) +} + +#[instrument(level = "debug", skip(tcx), ret)] +pub(crate) fn mir_coroutine_witnesses<'tcx>( + tcx: TyCtxt<'tcx>, + def_id: LocalDefId, +) -> Option> { + let (body, _) = tcx.mir_promoted(def_id); + let body = body.borrow(); + let body = &*body; + + // The first argument is the coroutine type passed by value + let coroutine_ty = body.local_decls[ty::CAPTURE_STRUCT_LOCAL].ty; + + let movable = match *coroutine_ty.kind() { + ty::Coroutine(def_id, _) => tcx.coroutine_movability(def_id) == hir::Movability::Movable, + ty::Error(_) => return None, + _ => span_bug!(body.span, "unexpected coroutine type {}", coroutine_ty), + }; + + // The witness simply contains all locals live across suspend points. + + let always_live_locals = always_storage_live_locals(body); + let liveness_info = locals_live_across_suspend_points(tcx, body, &always_live_locals, movable); + + // Extract locals which are live across suspension point into `layout` + // `remap` gives a mapping from local indices onto coroutine struct indices + // `storage_liveness` tells us which locals have live storage at suspension points + let (_, coroutine_layout, _) = compute_layout(liveness_info, body); + + check_suspend_tys(tcx, &coroutine_layout, body); + check_field_tys_sized(tcx, &coroutine_layout, def_id); + + Some(coroutine_layout) +} + +fn check_field_tys_sized<'tcx>( + tcx: TyCtxt<'tcx>, + coroutine_layout: &CoroutineLayout<'tcx>, + def_id: LocalDefId, +) { + // No need to check if unsized_fn_params is disabled, + // since we will error during typeck. + if !tcx.features().unsized_fn_params() { + return; + } + + // FIXME(#132279): @lcnr believes that we may want to support coroutines + // whose `Sized`-ness relies on the hidden types of opaques defined by the + // parent function. In this case we'd have to be able to reveal only these + // opaques here. + let infcx = tcx.infer_ctxt().ignoring_regions().build(TypingMode::non_body_analysis()); + let param_env = tcx.param_env(def_id); + + let ocx = ObligationCtxt::new_with_diagnostics(&infcx); + for field_ty in &coroutine_layout.field_tys { + ocx.register_bound( + ObligationCause::new( + field_ty.source_info.span, + def_id, + ObligationCauseCode::SizedCoroutineInterior(def_id), + ), + param_env, + field_ty.ty, + tcx.require_lang_item(hir::LangItem::Sized, field_ty.source_info.span), + ); + } + + let errors = ocx.evaluate_obligations_error_on_ambiguity(); + debug!(?errors); + if !errors.is_empty() { + infcx.err_ctxt().report_fulfillment_errors(errors); + } +} + +fn check_suspend_tys<'tcx>(tcx: TyCtxt<'tcx>, layout: &CoroutineLayout<'tcx>, body: &Body<'tcx>) { + let mut linted_tys = FxHashSet::default(); + + for (variant, yield_source_info) in + layout.variant_fields.iter().zip(&layout.variant_source_info) + { + debug!(?variant); + for &local in variant { + let decl = &layout.field_tys[local]; + debug!(?decl); + + if !decl.ignore_for_traits && linted_tys.insert(decl.ty) { + let Some(hir_id) = decl.source_info.scope.lint_root(&body.source_scopes) else { + continue; + }; + + check_must_not_suspend_ty( + tcx, + decl.ty, + hir_id, + SuspendCheckData { + source_span: decl.source_info.span, + yield_span: yield_source_info.span, + plural_len: 1, + ..Default::default() + }, + ); + } + } + } +} + +#[derive(Default)] +struct SuspendCheckData<'a> { + source_span: Span, + yield_span: Span, + descr_pre: &'a str, + descr_post: &'a str, + plural_len: usize, +} + +// Returns whether it emitted a diagnostic or not +// Note that this fn and the proceeding one are based on the code +// for creating must_use diagnostics +// +// Note that this technique was chosen over things like a `Suspend` marker trait +// as it is simpler and has precedent in the compiler +fn check_must_not_suspend_ty<'tcx>( + tcx: TyCtxt<'tcx>, + ty: Ty<'tcx>, + hir_id: hir::HirId, + data: SuspendCheckData<'_>, +) -> bool { + if ty.is_unit() { + return false; + } + + let plural_suffix = pluralize!(data.plural_len); + + debug!("Checking must_not_suspend for {}", ty); + + match *ty.kind() { + ty::Adt(_, args) if ty.is_box() => { + let boxed_ty = args.type_at(0); + let allocator_ty = args.type_at(1); + check_must_not_suspend_ty( + tcx, + boxed_ty, + hir_id, + SuspendCheckData { descr_pre: &format!("{}boxed ", data.descr_pre), ..data }, + ) || check_must_not_suspend_ty( + tcx, + allocator_ty, + hir_id, + SuspendCheckData { descr_pre: &format!("{}allocator ", data.descr_pre), ..data }, + ) + } + // FIXME(sized_hierarchy): This should be replaced with a requirement that types in + // coroutines implement `const Sized`. Scalable vectors are temporarily `Sized` while + // `feature(sized_hierarchy)` is not fully implemented, but in practice are + // non-`const Sized` and so do not have a known size at compilation time. Layout computation + // for a coroutine containing scalable vectors would be incorrect. + ty::Adt(def, _) if def.repr().scalable() => { + tcx.dcx() + .span_err(data.source_span, "scalable vectors cannot be held over await points"); + true + } + ty::Adt(def, _) => check_must_not_suspend_def(tcx, def.did(), hir_id, data), + // FIXME: support adding the attribute to TAITs + ty::Alias(ty::AliasTy { kind: ty::Opaque { def_id: def }, .. }) => { + let mut has_emitted = false; + for &(predicate, _) in tcx.explicit_item_bounds(def).skip_binder() { + // We only look at the `DefId`, so it is safe to skip the binder here. + if let ty::ClauseKind::Trait(ref poly_trait_predicate) = + predicate.kind().skip_binder() + { + let def_id = poly_trait_predicate.trait_ref.def_id; + let descr_pre = &format!("{}implementer{} of ", data.descr_pre, plural_suffix); + if check_must_not_suspend_def( + tcx, + def_id, + hir_id, + SuspendCheckData { descr_pre, ..data }, + ) { + has_emitted = true; + break; + } + } + } + has_emitted + } + ty::Dynamic(binder, _) => { + let mut has_emitted = false; + for predicate in binder.iter() { + if let ty::ExistentialPredicate::Trait(ref trait_ref) = predicate.skip_binder() { + let def_id = trait_ref.def_id; + let descr_post = &format!(" trait object{}{}", plural_suffix, data.descr_post); + if check_must_not_suspend_def( + tcx, + def_id, + hir_id, + SuspendCheckData { descr_post, ..data }, + ) { + has_emitted = true; + break; + } + } + } + has_emitted + } + ty::Tuple(fields) => { + let mut has_emitted = false; + for (i, ty) in fields.iter().enumerate() { + let descr_post = &format!(" in tuple element {i}"); + if check_must_not_suspend_ty( + tcx, + ty, + hir_id, + SuspendCheckData { descr_post, ..data }, + ) { + has_emitted = true; + } + } + has_emitted + } + ty::Array(ty, len) => { + let descr_pre = &format!("{}array{} of ", data.descr_pre, plural_suffix); + check_must_not_suspend_ty( + tcx, + ty, + hir_id, + SuspendCheckData { + descr_pre, + // FIXME(must_not_suspend): This is wrong. We should handle printing unevaluated consts. + plural_len: len.try_to_target_usize(tcx).unwrap_or(0) as usize + 1, + ..data + }, + ) + } + // If drop tracking is enabled, we want to look through references, since the referent + // may not be considered live across the await point. + ty::Ref(_region, ty, _mutability) => { + let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix); + check_must_not_suspend_ty(tcx, ty, hir_id, SuspendCheckData { descr_pre, ..data }) + } + _ => false, + } +} + +fn check_must_not_suspend_def( + tcx: TyCtxt<'_>, + def_id: DefId, + hir_id: hir::HirId, + data: SuspendCheckData<'_>, +) -> bool { + if let Some(reason_str) = find_attr!(tcx, def_id, MustNotSupend {reason} => reason) { + let reason = reason_str.map(|s| MustNotSuspendReason { span: data.source_span, reason: s }); + tcx.emit_node_span_lint( + rustc_session::lint::builtin::MUST_NOT_SUSPEND, + hir_id, + data.source_span, + MustNotSupend { + tcx, + yield_sp: data.yield_span, + reason, + src_sp: data.source_span, + pre: data.descr_pre, + def_id, + post: data.descr_post, + }, + ); + + true + } else { + false + } +} From 62690a61004d70983648e9b7e337f115624afbde Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Sun, 31 May 2026 08:40:09 +0000 Subject: [PATCH 10/26] Move coroutine.rs to be a mod.rs --- .../rustc_mir_transform/src/{coroutine.rs => coroutine/mod.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename compiler/rustc_mir_transform/src/{coroutine.rs => coroutine/mod.rs} (100%) diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine/mod.rs similarity index 100% rename from compiler/rustc_mir_transform/src/coroutine.rs rename to compiler/rustc_mir_transform/src/coroutine/mod.rs From e3468ae5f97b5bc2fac1b98609d9303dcfffca3d Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Tue, 2 Jun 2026 09:50:03 +0800 Subject: [PATCH 11/26] Promotes 5 Thumb-mode bare-metal Arm targets to Tier 2 --- .../src/spec/targets/thumbv7a_none_eabi.rs | 2 +- .../src/spec/targets/thumbv7a_none_eabihf.rs | 2 +- .../src/spec/targets/thumbv7r_none_eabi.rs | 2 +- .../src/spec/targets/thumbv7r_none_eabihf.rs | 2 +- .../src/spec/targets/thumbv8r_none_eabihf.rs | 2 +- .../docker/host-x86_64/dist-various-1/Dockerfile | 15 +++++++++++++++ src/doc/rustc/src/platform-support.md | 10 +++++----- .../rustc/src/platform-support/arm-none-eabi.md | 3 +++ .../src/platform-support/armv7a-none-eabi.md | 3 +-- .../src/platform-support/armv7r-none-eabi.md | 3 +-- .../src/platform-support/armv8r-none-eabihf.md | 3 +-- 11 files changed, 31 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs index 4e20f04173f0e..011307a50c346 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabi.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7a-none-eabi".into(), metadata: TargetMetadata { description: Some("Thumb-mode Bare Armv7-A".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs index bf4241a47277a..4baa73c3cdb8b 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7a_none_eabihf.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7a-none-eabihf".into(), metadata: TargetMetadata { description: Some("Thumb-mode Bare Armv7-A, hardfloat".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs index 296a1d00bad3b..da66a53432003 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabi.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7r-none-eabi".into(), metadata: TargetMetadata { description: Some("Thumb-mode Bare Armv7-R".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs index 8d5ac8a2d0a36..d591db8faf6a8 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv7r_none_eabihf.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv7r-none-eabihf".into(), metadata: TargetMetadata { description: Some("Thumb-mode Bare Armv7-R, hardfloat".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, diff --git a/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs b/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs index 808287ffa3d64..459dff9c1aa9b 100644 --- a/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs +++ b/compiler/rustc_target/src/spec/targets/thumbv8r_none_eabihf.rs @@ -7,7 +7,7 @@ pub(crate) fn target() -> Target { llvm_target: "thumbv8r-none-eabihf".into(), metadata: TargetMetadata { description: Some("Thumb-mode Bare Armv8-R, hardfloat".into()), - tier: Some(3), + tier: Some(2), host_tools: Some(false), std: Some(false), }, diff --git a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile index 33b48de872711..415709d388a99 100644 --- a/src/ci/docker/host-x86_64/dist-various-1/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-various-1/Dockerfile @@ -114,11 +114,16 @@ ENV TARGETS=$TARGETS,riscv32imafc-unknown-none-elf ENV TARGETS=$TARGETS,riscv64imac-unknown-none-elf ENV TARGETS=$TARGETS,riscv64gc-unknown-none-elf ENV TARGETS=$TARGETS,armv7r-none-eabi +ENV TARGETS=$TARGETS,thumbv7r-none-eabi ENV TARGETS=$TARGETS,armv7r-none-eabihf +ENV TARGETS=$TARGETS,thumbv7r-none-eabihf ENV TARGETS=$TARGETS,armv8r-none-eabihf +ENV TARGETS=$TARGETS,thumbv8r-none-eabihf ENV TARGETS=$TARGETS,thumbv7neon-unknown-linux-gnueabihf ENV TARGETS=$TARGETS,armv7a-none-eabi +ENV TARGETS=$TARGETS,thumbv7a-none-eabi ENV TARGETS=$TARGETS,armv7a-none-eabihf +ENV TARGETS=$TARGETS,thumbv7a-none-eabihf ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft" \ CFLAGS_arm_unknown_linux_musleabi="-march=armv6 -marm" \ @@ -133,8 +138,18 @@ ENV CFLAGS_armv5te_unknown_linux_musleabi="-march=armv5te -marm -mfloat-abi=soft CC_armv7a_none_eabihf=arm-none-eabi-gcc \ CFLAGS_armv7a_none_eabi=-march=armv7-a \ CFLAGS_armv7a_none_eabihf=-march=armv7-a+fp \ + CC_thumbv7a_none_eabi=arm-none-eabi-gcc \ + CC_thumbv7a_none_eabihf=arm-none-eabi-gcc \ + CFLAGS_thumbv7a_none_eabi=-march=armv7-a \ + CFLAGS_thumbv7a_none_eabihf="-march=armv7-a+fp -mfpu=vfpv3-d16" \ + CC_thumbv7r_none_eabi=arm-none-eabi-gcc \ + CC_thumbv7r_none_eabihf=arm-none-eabi-gcc \ + CFLAGS_thumbv7r_none_eabi=-march=armv7-r \ + CFLAGS_thumbv7r_none_eabihf="-march=armv7-r+fp -mfpu=vfpv3-d16" \ CC_armv8r_none_eabihf=arm-none-eabi-gcc \ CFLAGS_armv8r_none_eabihf="-march=armv8-r+fp.sp -mfpu=fp-armv8" \ + CC_thumbv8r_none_eabihf=arm-none-eabi-gcc \ + CFLAGS_thumbv8r_none_eabihf="-march=armv8-r+fp.sp -mfpu=fp-armv8" \ CC_aarch64_unknown_none_softfloat=aarch64-none-elf-gcc \ CFLAGS_aarch64_unknown_none_softfloat=-mstrict-align -march=armv8-a+nofp+nosimd \ CC_aarch64_unknown_none=aarch64-none-elf-gcc \ diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index 26dd6b31b8991..7cbfb8dd11345 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -174,6 +174,11 @@ target | std | notes [`armv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R [`armv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Bare Armv7-R, hardfloat [`armv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | Bare Armv8-R, hardfloat +[`thumbv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | Thumb-mode Bare Armv7-A +[`thumbv7a-none-eabihf`](platform-support/armv7a-none-eabi.md) | * | Thumb-mode Bare Armv7-A, hardfloat +[`thumbv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | Thumb-mode Bare Armv7-R +[`thumbv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | Thumb-mode Bare Armv7-R, hardfloat +[`thumbv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | Thumb-mode Bare Armv8-R, hardfloat `i586-unknown-linux-gnu` | ✓ | 32-bit Linux (kernel 3.2+, glibc 2.17, original Pentium) [^x86_32-floats-x87] `i586-unknown-linux-musl` | ✓ | 32-bit Linux (musl 1.2.5, original Pentium) [^x86_32-floats-x87] [`i686-linux-android`](platform-support/android.md) | ✓ | 32-bit x86 Android ([Pentium 4 plus various extensions](https://developer.android.com/ndk/guides/abis.html#x86)) [^x86_32-floats-return-ABI] @@ -419,8 +424,6 @@ target | std | host | notes [`thumbv5te-none-eabi`](platform-support/armv5te-none-eabi.md) | * | | Thumb-mode Bare Armv5TE [`thumbv6-none-eabi`](platform-support/armv6-none-eabi.md) | * | | Thumb-mode Bare Armv6 [`thumbv6m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv6M with NuttX -[`thumbv7a-none-eabi`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A -[`thumbv7a-none-eabihf`](platform-support/armv7a-none-eabi.md) | * | | Thumb-mode Bare Armv7-A, hardfloat [`thumbv7a-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX [`thumbv7a-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7-A with NuttX, hardfloat `thumbv7a-pc-windows-msvc` | | | @@ -429,12 +432,9 @@ target | std | host | notes [`thumbv7em-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv7EM with NuttX, hardfloat [`thumbv7m-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv7M with NuttX `thumbv7neon-unknown-linux-musleabihf` | ? | | Thumb2-mode Armv7-A Linux with NEON, musl 1.2.5 -[`thumbv7r-none-eabi`](platform-support/armv7r-none-eabi.md) | * | | Thumb-mode Bare Armv7-R -[`thumbv7r-none-eabihf`](platform-support/armv7r-none-eabi.md) | * | | Thumb-mode Bare Armv7-R, hardfloat [`thumbv8m.base-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Baseline with NuttX [`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX [`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ | | ARMv8M Mainline with NuttX, hardfloat -[`thumbv8r-none-eabihf`](platform-support/armv8r-none-eabihf.md) | * | | Thumb-mode Bare Armv8-R, hardfloat [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? | | WebAssembly [`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? | | WebAssembly with [WALI](https://github.com/arjunr2/WALI) [`wasm32-wasip3`](platform-support/wasm32-wasip3.md) | ✓ | | WebAssembly with WASIp3 diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index cf1fe9ed59ed6..5d22cef92d220 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -13,10 +13,13 @@ their own document. - Arm A-Profile Architectures - [`armv7a-none-eabi`](armv7a-none-eabi.md) + - [`thumbv7a-none-eabi` and `thumbv7a-none-eabihf`](armv7a-none-eabi.md) - Arm R-Profile Architectures - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md) - [`armebv7r-none-eabi` and `armebv7r-none-eabihf`](armebv7r-none-eabi.md) - [`armv8r-none-eabihf`](armv8r-none-eabihf.md) + - [`thumbv7r-none-eabi` and `thumbv7r-none-eabihf`](armv7r-none-eabi.md) + - [`thumbv8r-none-eabihf`](armv8r-none-eabihf.md) - Arm M-Profile Architectures - [`thumbv6m-none-eabi`](thumbv6m-none-eabi.md) - [`thumbv7m-none-eabi`](thumbv7m-none-eabi.md) diff --git a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md index 0fa09d3955ff3..73f2e303579a0 100644 --- a/src/doc/rustc/src/platform-support/armv7a-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7a-none-eabi.md @@ -1,7 +1,6 @@ # `armv7a-none-eabi*` and `thumbv7a-none-eabi*` -* **Tier: 2** (`armv7a-none-eabi` and `armv7a-none-eabihf`) -* **Tier: 3** (`thumbv7a-none-eabi` and `thumbv7a-none-eabihf`) +* **Tier: 2** * **Library Support:** core and alloc (bare-metal, `#![no_std]`) Bare-metal target for CPUs in the Armv7-A architecture family, supporting dual diff --git a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md index 5f95af44a7935..d4937052a95ce 100644 --- a/src/doc/rustc/src/platform-support/armv7r-none-eabi.md +++ b/src/doc/rustc/src/platform-support/armv7r-none-eabi.md @@ -1,7 +1,6 @@ # `armv7r-none-eabi*` and `thumbv7r-none-eabi*` -* **Tier: 2** (`armv7r-none-eabi` and `armv7r-none-eabihf`) -* **Tier: 3** (`thumbv7r-none-eabi` and `thumbv7r-none-eabihf`) +* **Tier: 2** * **Library Support:** core and alloc (bare-metal, `#![no_std]`) Bare-metal target for CPUs in the Armv7-R architecture family, supporting dual diff --git a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md index 1ff36b47beb2f..2f6d83e01b27d 100644 --- a/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md +++ b/src/doc/rustc/src/platform-support/armv8r-none-eabihf.md @@ -1,7 +1,6 @@ # `armv8r-none-eabihf` and `thumbv8r-none-eabihf` -* **Tier: 2**: `armv8r-none-eabihf` -* **Tier: 3**: `thumbv8r-none-eabihf` +* **Tier: 2** * **Library Support:** core and alloc (bare-metal, `#![no_std]`) Bare-metal target for CPUs in the Armv8-R architecture family, supporting dual From ac63a3e4aeb0a6d42918b942f7819eac0f149f8c Mon Sep 17 00:00:00 2001 From: Camille Gillot Date: Tue, 2 Jun 2026 15:26:17 +0000 Subject: [PATCH 12/26] Pacify doc-checker. --- compiler/rustc_mir_transform/src/coroutine/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index ed997cc08a888..be8402f082e62 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -4,7 +4,7 @@ //! //! The state transform creates a `poll` method such that calling the coroutine `f()` is equivalent //! to: -//! ```rust (ignore) +//! ```ignore (example) //! fn initial_mir(state: CoroutineState, mut resume_arg: ResumeTy) { //! // Repeatedly poll the state machine. //! loop { From 0e1bd7ccf9cb3a1f45165f26650d9ff262d3bbf9 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Mon, 1 Jun 2026 18:54:29 +0300 Subject: [PATCH 13/26] rustc_codegen_ssa: Refactor `ArchiveEntry` to include entry kind --- .../rustc_codegen_ssa/src/back/archive.rs | 62 ++++++++++++------- compiler/rustc_codegen_ssa/src/back/link.rs | 40 ++++++------ 2 files changed, 60 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index ba811825dce23..e4bfbdccba4a0 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -21,7 +21,7 @@ use rustc_target::spec::Arch; use tracing::trace; use super::metadata::{create_compressed_metadata_file, search_for_section}; -use super::rmeta_link::{self, RmetaLink}; +use super::rmeta_link; use crate::common; // Public for ArchiveBuilderBuilder::extract_bundled_libs pub use crate::errors::ExtractBundledLibsError; @@ -309,12 +309,12 @@ fn find_binutils_dlltool(sess: &Session) -> OsString { } pub trait ArchiveBuilder { - fn add_file(&mut self, path: &Path); + fn add_file(&mut self, path: &Path, kind: ArchiveEntryKind); fn add_archive( &mut self, archive: &Path, - skip: Option) -> bool + 'static>>, + skip: Option bool + 'static>>, ) -> io::Result<()>; fn build(self: Box, output: &Path) -> bool; @@ -383,12 +383,27 @@ pub struct ArArchiveBuilder<'a> { entries: Vec<(Vec, ArchiveEntry)>, } +#[derive(Clone, Copy, PartialEq, Debug)] +pub enum ArchiveEntryKind { + /// Object file produced from Rust code. + RustObj, + /// Anything else, introduce new variants as needed. + Other, +} + #[derive(Debug)] -enum ArchiveEntry { - FromArchive { archive_index: usize, file_range: (u64, u64) }, +enum ArchiveEntrySource { + Archive { archive_index: usize, file_range: (u64, u64) }, File(PathBuf), } +#[derive(Debug)] +struct ArchiveEntry { + source: ArchiveEntrySource, + #[expect(dead_code)] // used in #155338 + kind: ArchiveEntryKind, +} + impl<'a> ArArchiveBuilder<'a> { pub fn new(sess: &'a Session, object_reader: &'static ObjectReader) -> ArArchiveBuilder<'a> { ArArchiveBuilder { sess, object_reader, src_archives: vec![], entries: vec![] } @@ -446,7 +461,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { fn add_archive( &mut self, archive_path: &Path, - mut skip: Option) -> bool + 'static>>, + mut skip: Option bool + 'static>>, ) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") @@ -462,8 +477,7 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; let archive = ArchiveFile::parse(&*archive_map) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let metadata_link = - skip.as_ref().and_then(|_| rmeta_link::read(&archive, &archive_map, &archive_path)); + let metadata_link = rmeta_link::read(&archive, &archive_map, &archive_path); let archive_index = self.src_archives.len(); if let Some(expected_kind) = @@ -483,17 +497,23 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let entry = entry.map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; let file_name = String::from_utf8(entry.name().to_vec()) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let drop = skip.as_mut().is_some_and(|f| f(&file_name, metadata_link.as_ref())); + let kind = if metadata_link + .as_ref() + .is_some_and(|m| m.rust_object_files.iter().any(|f| f == &file_name)) + { + ArchiveEntryKind::RustObj + } else { + ArchiveEntryKind::Other + }; + let drop = skip.as_mut().is_some_and(|f| f(&file_name, kind)); if !drop { - if entry.is_thin() { + let source = if entry.is_thin() { let member_path = archive_path.parent().unwrap().join(Path::new(&file_name)); - self.entries.push((file_name.into_bytes(), ArchiveEntry::File(member_path))); + ArchiveEntrySource::File(member_path) } else { - self.entries.push(( - file_name.into_bytes(), - ArchiveEntry::FromArchive { archive_index, file_range: entry.file_range() }, - )); - } + ArchiveEntrySource::Archive { archive_index, file_range: entry.file_range() } + }; + self.entries.push((file_name.into_bytes(), ArchiveEntry { source, kind })); } } @@ -502,10 +522,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { } /// Adds an arbitrary file to this archive - fn add_file(&mut self, file: &Path) { + fn add_file(&mut self, file: &Path, kind: ArchiveEntryKind) { self.entries.push(( file.file_name().unwrap().to_str().unwrap().to_string().into_bytes(), - ArchiveEntry::File(file.to_owned()), + ArchiveEntry { source: ArchiveEntrySource::File(file.to_owned()), kind }, )); } @@ -539,8 +559,8 @@ impl<'a> ArArchiveBuilder<'a> { for (entry_name, entry) in self.entries { let data = - match entry { - ArchiveEntry::FromArchive { archive_index, file_range } => { + match entry.source { + ArchiveEntrySource::Archive { archive_index, file_range } => { let src_archive = &self.src_archives[archive_index]; let archive_data = &src_archive.1; let start = file_range.0 as usize; @@ -563,7 +583,7 @@ impl<'a> ArArchiveBuilder<'a> { Box::new(data) as Box> } - ArchiveEntry::File(file) => unsafe { + ArchiveEntrySource::File(file) => unsafe { Box::new( Mmap::map(File::open(file).map_err(|err| { io_error_context("failed to open object file", err) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d54f9141d8225..955616b04c1c1 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -53,7 +53,7 @@ use rustc_target::spec::{ }; use tracing::{debug, info, warn}; -use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder}; +use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ArchiveEntryKind}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; @@ -342,11 +342,11 @@ fn link_rlib<'a>( // normal linkers for the platform. Sometimes this is not possible however. // If it is possible however, placing the metadata object first improves // performance of getting metadata from rlibs. - ab.add_file(&metadata); + ab.add_file(&metadata, ArchiveEntryKind::Other); // Place the rmeta-link member immediately after metadata so consumers // can find it without iterating the whole archive. if let Some(file) = &metadata_link_file { - ab.add_file(file); + ab.add_file(file, ArchiveEntryKind::Other); } None } @@ -359,15 +359,15 @@ fn link_rlib<'a>( for m in &compiled_modules.modules { if let Some(obj) = m.object.as_ref() { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } if let Some(obj) = m.global_asm_object.as_ref() { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } if let Some(dwarf_obj) = m.dwarf_object.as_ref() { - ab.add_file(dwarf_obj); + ab.add_file(dwarf_obj, ArchiveEntryKind::Other); } } @@ -376,10 +376,10 @@ fn link_rlib<'a>( RlibFlavor::StaticlibBase => { if let Some(m) = &compiled_modules.allocator_module { if let Some(obj) = &m.object { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } if let Some(obj) = &m.global_asm_object { - ab.add_file(obj); + ab.add_file(obj, ArchiveEntryKind::RustObj); } } } @@ -469,18 +469,18 @@ fn link_rlib<'a>( // // Basically, all this means is that this code should not move above the // code above. - ab.add_file(&trailing_metadata); + ab.add_file(&trailing_metadata, ArchiveEntryKind::Other); // Place the rmeta-link member immediately after metadata so consumers can // find it without iterating the whole archive. if let Some(file) = &metadata_link_file { - ab.add_file(file); + ab.add_file(file, ArchiveEntryKind::Other); } } // Add all bundled static native library dependencies. // Archives added to the end of .rlib archive, see comment above for the reason. for lib in packed_bundled_libs { - ab.add_file(&lib) + ab.add_file(&lib, ArchiveEntryKind::Other) } ab @@ -529,16 +529,14 @@ fn link_staticlib( let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); ab.add_archive( path, - Some(Box::new(move |fname: &str, metadata_link| { + Some(Box::new(move |fname: &str, entry_kind| { // Ignore metadata and rmeta-link files. if fname == METADATA_FILENAME || fname == rmeta_link::FILENAME { return true; } // Don't include Rust objects if LTO is enabled. - if lto - && metadata_link.is_some_and(|m| m.rust_object_files.iter().any(|f| f == fname)) - { + if lto && entry_kind == ArchiveEntryKind::RustObj { return true; } @@ -1266,7 +1264,7 @@ fn link_natively( if should_archive { let mut ab = archive_builder_builder.new_archive_builder(sess); - ab.add_file(temp_filename); + ab.add_file(temp_filename, ArchiveEntryKind::Other); ab.build(out_filename); } } @@ -3242,19 +3240,19 @@ fn add_static_crate( let mut archive = archive_builder_builder.new_archive_builder(sess); if let Err(error) = archive.add_archive( cratepath, - Some(Box::new(move |f, metadata_link| { + Some(Box::new(move |f, entry_kind| { if f == METADATA_FILENAME || f == rmeta_link::FILENAME { return true; } - let is_rust_object = - metadata_link.is_some_and(|m| m.rust_object_files.iter().any(|rf| rf == f)); - // If we're performing LTO and this is a rust-generated object // file, then we don't need the object file as it's part of the // LTO module. Note that `#![no_builtins]` is excluded from LTO, // though, so we let that object file slide. - if upstream_rust_objects_already_included && is_rust_object && is_builtins { + if upstream_rust_objects_already_included + && entry_kind == ArchiveEntryKind::RustObj + && is_builtins + { return true; } From d39ecc046e90feeb35ab74fe271b1818df8430c6 Mon Sep 17 00:00:00 2001 From: Vadim Petrochenkov Date: Tue, 2 Jun 2026 18:51:23 +0300 Subject: [PATCH 14/26] rustc_codegen_ssa: check whether `add_archive` argument is a rlib --- .../rustc_codegen_ssa/src/back/archive.rs | 27 ++++++++++--------- compiler/rustc_codegen_ssa/src/back/link.rs | 16 +++++------ 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/archive.rs b/compiler/rustc_codegen_ssa/src/back/archive.rs index e4bfbdccba4a0..b08693f53938b 100644 --- a/compiler/rustc_codegen_ssa/src/back/archive.rs +++ b/compiler/rustc_codegen_ssa/src/back/archive.rs @@ -308,14 +308,15 @@ fn find_binutils_dlltool(sess: &Session) -> OsString { tool_name } +pub enum AddArchiveKind<'a> { + Rlib(/*skip*/ &'a dyn Fn(&str, ArchiveEntryKind) -> bool), + Other, +} + pub trait ArchiveBuilder { fn add_file(&mut self, path: &Path, kind: ArchiveEntryKind); - fn add_archive( - &mut self, - archive: &Path, - skip: Option bool + 'static>>, - ) -> io::Result<()>; + fn add_archive(&mut self, archive: &Path, kind: AddArchiveKind<'_>) -> io::Result<()>; fn build(self: Box, output: &Path) -> bool; } @@ -458,11 +459,7 @@ pub fn try_extract_macho_fat_archive( } impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { - fn add_archive( - &mut self, - archive_path: &Path, - mut skip: Option bool + 'static>>, - ) -> io::Result<()> { + fn add_archive(&mut self, archive_path: &Path, ar_kind: AddArchiveKind<'_>) -> io::Result<()> { let mut archive_path = archive_path.to_path_buf(); if self.sess.target.llvm_target.contains("-apple-macosx") && let Some(new_archive_path) = try_extract_macho_fat_archive(self.sess, &archive_path)? @@ -477,7 +474,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { let archive_map = unsafe { Mmap::map(File::open(&archive_path)?)? }; let archive = ArchiveFile::parse(&*archive_map) .map_err(|err| io::Error::new(io::ErrorKind::InvalidData, err))?; - let metadata_link = rmeta_link::read(&archive, &archive_map, &archive_path); + let metadata_link = match ar_kind { + AddArchiveKind::Rlib(..) => rmeta_link::read(&archive, &archive_map, &archive_path), + AddArchiveKind::Other => None, + }; let archive_index = self.src_archives.len(); if let Some(expected_kind) = @@ -505,7 +505,10 @@ impl<'a> ArchiveBuilder for ArArchiveBuilder<'a> { } else { ArchiveEntryKind::Other }; - let drop = skip.as_mut().is_some_and(|f| f(&file_name, kind)); + let drop = match ar_kind { + AddArchiveKind::Rlib(skip) => skip(&file_name, kind), + AddArchiveKind::Other => false, + }; if !drop { let source = if entry.is_thin() { let member_path = archive_path.parent().unwrap().join(Path::new(&file_name)); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 955616b04c1c1..cba4e518a99bb 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -53,7 +53,7 @@ use rustc_target::spec::{ }; use tracing::{debug, info, warn}; -use super::archive::{ArchiveBuilder, ArchiveBuilderBuilder, ArchiveEntryKind}; +use super::archive::{AddArchiveKind, ArchiveBuilder, ArchiveBuilderBuilder, ArchiveEntryKind}; use super::command::Command; use super::linker::{self, Linker}; use super::metadata::{MetadataPosition, create_wrapper_file}; @@ -419,7 +419,7 @@ fn link_rlib<'a>( packed_bundled_libs.push(wrapper_file); } else { let path = find_native_static_library(lib.name.as_str(), lib.verbatim, sess); - ab.add_archive(&path, None).unwrap_or_else(|error| { + ab.add_archive(&path, AddArchiveKind::Other).unwrap_or_else(|error| { sess.dcx().emit_fatal(errors::AddNativeLibrary { library_path: path, error }) }); } @@ -436,7 +436,7 @@ fn link_rlib<'a>( tmpdir.as_ref(), true, ) { - ab.add_archive(&output_path, None).unwrap_or_else(|error| { + ab.add_archive(&output_path, AddArchiveKind::Other).unwrap_or_else(|error| { sess.dcx() .emit_fatal(errors::AddNativeLibrary { library_path: output_path, error }); }); @@ -529,7 +529,7 @@ fn link_staticlib( let bundled_libs: FxIndexSet<_> = native_libs.filter_map(|lib| lib.filename).collect(); ab.add_archive( path, - Some(Box::new(move |fname: &str, entry_kind| { + AddArchiveKind::Rlib(&|fname: &str, entry_kind| { // Ignore metadata and rmeta-link files. if fname == METADATA_FILENAME || fname == rmeta_link::FILENAME { return true; @@ -546,7 +546,7 @@ fn link_staticlib( } false - })), + }), ) .unwrap(); @@ -557,7 +557,7 @@ fn link_staticlib( for filename in relevant_libs.iter() { let joined = tempdir.as_ref().join(filename.as_str()); let path = joined.as_path(); - ab.add_archive(path, None).unwrap(); + ab.add_archive(path, AddArchiveKind::Other).unwrap(); } all_native_libs.extend(crate_info.native_libraries[&cnum].iter().cloned()); @@ -3240,7 +3240,7 @@ fn add_static_crate( let mut archive = archive_builder_builder.new_archive_builder(sess); if let Err(error) = archive.add_archive( cratepath, - Some(Box::new(move |f, entry_kind| { + AddArchiveKind::Rlib(&|f, entry_kind| { if f == METADATA_FILENAME || f == rmeta_link::FILENAME { return true; } @@ -3266,7 +3266,7 @@ fn add_static_crate( } false - })), + }), ) { sess.dcx() .emit_fatal(errors::RlibArchiveBuildFailure { path: cratepath.clone(), error }); From 9b7623a1621a3fedd1eb7f3cdac4b48e9f819013 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 25 May 2026 20:11:36 +0200 Subject: [PATCH 15/26] Remove -Zemscripten-wasm-eh This was necessary when transitioning from JS to wasm exception handling on Emscripten. Enough time has probably passed that we no longer need to support JS exception handling on Emscripten. This enables cleaning up a fair bit of code. --- compiler/rustc_codegen_llvm/src/context.rs | 20 --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 85 +---------- compiler/rustc_codegen_llvm/src/llvm_util.rs | 7 - compiler/rustc_codegen_llvm/src/type_.rs | 4 - compiler/rustc_codegen_ssa/src/back/link.rs | 8 +- compiler/rustc_codegen_ssa/src/base.rs | 1 - compiler/rustc_feature/src/builtin_attrs.rs | 1 - compiler/rustc_feature/src/unstable.rs | 2 - compiler/rustc_hir/src/lang_items.rs | 1 - compiler/rustc_hir/src/weak_lang_items.rs | 1 - compiler/rustc_interface/src/tests.rs | 1 - .../rustc_middle/src/middle/lang_items.rs | 8 +- compiler/rustc_passes/src/weak_lang_items.rs | 13 +- compiler/rustc_session/src/config/cfg.rs | 6 - compiler/rustc_session/src/options.rs | 2 - compiler/rustc_span/src/symbol.rs | 4 - library/panic_abort/src/lib.rs | 43 ------ library/panic_unwind/Cargo.toml | 4 - library/panic_unwind/src/emcc.rs | 135 ------------------ library/panic_unwind/src/lib.rs | 15 +- library/unwind/Cargo.toml | 2 +- library/unwind/src/lib.rs | 3 +- .../wasm32-unknown-emscripten.md | 3 +- .../src/compiler-flags/emscripten-wasm-eh.md | 6 - .../src/language-features/lang-items.md | 3 +- .../emscripten-catch-unwind-js-eh.rs | 71 --------- ...-wasm-eh.rs => emscripten-catch-unwind.rs} | 4 +- tests/codegen-llvm/terminating-catchpad.rs | 2 +- tests/codegen-llvm/wasm_exceptions.rs | 2 +- ...llowed-cli-cfgs.emscripten_wasm_eh_.stderr | 8 -- tests/ui/cfg/disallowed-cli-cfgs.rs | 2 - .../const-eval/const_panic_libcore_bin.rs | 2 - tests/ui/extern-flag/empty-extern-arg.rs | 1 - .../feature-gate-cfg-emscripten-wasm-eh.rs | 4 - ...feature-gate-cfg-emscripten-wasm-eh.stderr | 12 -- .../macros/macro-comma-behavior.core.stderr | 16 +-- tests/ui/macros/macro-comma-behavior.rs | 1 - .../ui/macros/macro-comma-behavior.std.stderr | 26 ++-- tests/ui/panic-handler/weak-lang-item.rs | 1 - tests/ui/panic-handler/weak-lang-item.stderr | 2 +- .../auxiliary/panic-runtime-lang-items.rs | 2 - tests/ui/range/issue-54505-no-std.rs | 3 - tests/ui/range/issue-54505-no-std.stderr | 26 ++-- 43 files changed, 56 insertions(+), 507 deletions(-) delete mode 100644 library/panic_unwind/src/emcc.rs delete mode 100644 src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md delete mode 100644 tests/codegen-llvm/emscripten-catch-unwind-js-eh.rs rename tests/codegen-llvm/{emscripten-catch-unwind-wasm-eh.rs => emscripten-catch-unwind.rs} (96%) delete mode 100644 tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr delete mode 100644 tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs delete mode 100644 tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 6e0ff1c75149b..85a7f9cab73a4 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -26,7 +26,6 @@ use rustc_session::config::{ BranchProtection, CFGuard, CFProtection, CrateType, DebugInfo, FunctionReturn, PAuthKey, PacRet, }; use rustc_span::{DUMMY_SP, Span, Spanned, Symbol, sym}; -use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::spec::{ Arch, CfgAbi, Env, FramePointer, HasTargetSpec, Os, RelocModel, SmallDataThresholdSupport, Target, TlsModel, @@ -136,7 +135,6 @@ pub(crate) struct FullCx<'ll, 'tcx> { pub dbg_cx: Option>, eh_personality: Cell>, - eh_catch_typeinfo: Cell>, pub rust_try_fn: Cell>, intrinsics: @@ -672,7 +670,6 @@ impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { coverage_cx, dbg_cx, eh_personality: Cell::new(None), - eh_catch_typeinfo: Cell::new(None), rust_try_fn: Cell::new(None), intrinsics: Default::default(), local_gen_sym_counter: Cell::new(0), @@ -1042,23 +1039,6 @@ impl<'ll> CodegenCx<'ll, '_> { } } } - - pub(crate) fn eh_catch_typeinfo(&self) -> &'ll Value { - if let Some(eh_catch_typeinfo) = self.eh_catch_typeinfo.get() { - return eh_catch_typeinfo; - } - let tcx = self.tcx; - assert!(self.sess().target.os == Os::Emscripten); - let eh_catch_typeinfo = match tcx.lang_items().eh_catch_typeinfo() { - Some(def_id) => self.get_static(def_id), - _ => { - let ty = self.type_struct(&[self.type_ptr(), self.type_ptr()], false); - self.declare_global(&mangle_internal_symbol(self.tcx, "rust_eh_catch_typeinfo"), ty) - } - }; - self.eh_catch_typeinfo.set(Some(eh_catch_typeinfo)); - eh_catch_typeinfo - } } impl CodegenCx<'_, '_> { diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 1c7b415fd04c7..393837375769e 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -28,7 +28,7 @@ use rustc_session::lint::builtin::DEPRECATED_LLVM_INTRINSIC; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate}; use rustc_target::callconv::PassMode; -use rustc_target::spec::{Arch, Os}; +use rustc_target::spec::Arch; use tracing::debug; use crate::abi::FnAbiLlvmExt; @@ -1356,8 +1356,6 @@ fn catch_unwind_intrinsic<'ll, 'tcx>( codegen_msvc_try(bx, try_func, data, catch_func) } else if wants_wasm_eh(bx.sess()) { codegen_wasm_try(bx, try_func, data, catch_func) - } else if bx.sess().target.os == Os::Emscripten { - codegen_emcc_try(bx, try_func, data, catch_func) } else { codegen_gnu_try(bx, try_func, data, catch_func) } @@ -1654,87 +1652,6 @@ fn codegen_gnu_try<'ll, 'tcx>( ret } -// Variant of codegen_gnu_try used for emscripten where Rust panics are -// implemented using C++ exceptions. Here we use exceptions of a specific type -// (`struct rust_panic`) to represent Rust panics. -fn codegen_emcc_try<'ll, 'tcx>( - bx: &mut Builder<'_, 'll, 'tcx>, - try_func: &'ll Value, - data: &'ll Value, - catch_func: &'ll Value, -) -> &'ll Value { - let (llty, llfn) = get_rust_try_fn(bx, &mut |mut bx| { - // Codegens the shims described above: - // - // bx: - // invoke %try_func(%data) normal %normal unwind %catch - // - // normal: - // ret 0 - // - // catch: - // (%ptr, %selector) = landingpad - // %rust_typeid = @llvm.eh.typeid.for(@_ZTI10rust_panic) - // %is_rust_panic = %selector == %rust_typeid - // %catch_data = alloca { i8*, i8 } - // %catch_data[0] = %ptr - // %catch_data[1] = %is_rust_panic - // call %catch_func(%data, %catch_data) - // ret 1 - let then = bx.append_sibling_block("then"); - let catch = bx.append_sibling_block("catch"); - - let try_func = llvm::get_param(bx.llfn(), 0); - let data = llvm::get_param(bx.llfn(), 1); - let catch_func = llvm::get_param(bx.llfn(), 2); - let try_func_ty = bx.type_func(&[bx.type_ptr()], bx.type_void()); - bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None); - - bx.switch_to_block(then); - bx.ret(bx.const_bool(false)); - - // Type indicator for the exception being thrown. - // - // The first value in this tuple is a pointer to the exception object - // being thrown. The second value is a "selector" indicating which of - // the landing pad clauses the exception's type had been matched to. - bx.switch_to_block(catch); - let tydesc = bx.eh_catch_typeinfo(); - let lpad_ty = bx.type_struct(&[bx.type_ptr(), bx.type_i32()], false); - let vals = bx.landing_pad(lpad_ty, bx.eh_personality(), 2); - bx.add_clause(vals, tydesc); - bx.add_clause(vals, bx.const_null(bx.type_ptr())); - let ptr = bx.extract_value(vals, 0); - let selector = bx.extract_value(vals, 1); - - // Check if the typeid we got is the one for a Rust panic. - let rust_typeid = bx.call_intrinsic("llvm.eh.typeid.for", &[bx.val_ty(tydesc)], &[tydesc]); - let is_rust_panic = bx.icmp(IntPredicate::IntEQ, selector, rust_typeid); - let is_rust_panic = bx.zext(is_rust_panic, bx.type_bool()); - - // We need to pass two values to catch_func (ptr and is_rust_panic), so - // create an alloca and pass a pointer to that. - let ptr_size = bx.tcx().data_layout.pointer_size(); - let ptr_align = bx.tcx().data_layout.pointer_align().abi; - let i8_align = bx.tcx().data_layout.i8_align; - // Required in order for there to be no padding between the fields. - assert!(i8_align <= ptr_align); - let catch_data = bx.alloca(2 * ptr_size, ptr_align); - bx.store(ptr, catch_data, ptr_align); - let catch_data_1 = bx.inbounds_ptradd(catch_data, bx.const_usize(ptr_size.bytes())); - bx.store(is_rust_panic, catch_data_1, i8_align); - - let catch_ty = bx.type_func(&[bx.type_ptr(), bx.type_ptr()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, &[data, catch_data], None, None); - bx.ret(bx.const_bool(true)); - }); - - // Note that no invoke is used here because by definition this function - // can't panic (that's what it's catching). - let ret = bx.call(llty, None, None, llfn, &[try_func, data, catch_func], None, None); - ret -} - // Helper function to give a Block to a closure to codegen a shim function. // This is currently primarily used for the `try` intrinsic functions above. fn gen_fn<'a, 'll, 'tcx>( diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index eb1efa31ae4ab..73b7f699b606d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -109,13 +109,6 @@ unsafe fn configure_llvm(sess: &Session) { add("-wasm-enable-eh", false); } - if sess.target.os == Os::Emscripten - && !sess.opts.unstable_opts.emscripten_wasm_eh - && sess.panic_strategy().unwinds() - { - add("-enable-emscripten-cxx-exceptions", false); - } - // HACK(eddyb) LLVM inserts `llvm.assume` calls to preserve align attributes // during inlining. Unfortunately these may block other optimizations. add("-preserve-alignment-assumptions-during-inlining=false", false); diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 796f3d9ef60ba..0d49971f52533 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -106,10 +106,6 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { } } impl<'ll, 'tcx> CodegenCx<'ll, 'tcx> { - pub(crate) fn type_bool(&self) -> &'ll Type { - self.type_i8() - } - pub(crate) fn type_int_from_ty(&self, t: ty::IntTy) -> &'ll Type { match t { ty::IntTy::Isize => self.type_isize(), diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index d54f9141d8225..c0308fecf0d93 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2774,13 +2774,7 @@ fn add_order_independent_options( } if sess.target.os == Os::Emscripten { - cmd.cc_arg(if sess.opts.unstable_opts.emscripten_wasm_eh { - "-fwasm-exceptions" - } else if sess.panic_strategy().unwinds() { - "-sDISABLE_EXCEPTION_CATCHING=0" - } else { - "-sDISABLE_EXCEPTION_CATCHING=1" - }); + cmd.cc_arg("-fwasm-exceptions"); } if flavor == LinkerFlavor::Llbc { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 78bc07869895a..bc4c2aef8da67 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -373,7 +373,6 @@ pub(crate) fn build_shift_expr_rhs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( // us pub fn wants_wasm_eh(sess: &Session) -> bool { sess.target.is_like_wasm - && (sess.target.os != Os::Emscripten || sess.opts.unstable_opts.emscripten_wasm_eh) } /// Returns `true` if this session's target will use SEH-based unwinding. diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index 673ac38a1d338..72919028f1ce9 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -32,7 +32,6 @@ const GATED_CFGS: &[GatedCfg] = &[ (sym::sanitizer_cfi_normalize_integers, sym::cfg_sanitizer_cfi, Features::cfg_sanitizer_cfi), // this is consistent with naming of the compiler flag it's for (sym::fmt_debug, sym::fmt_debug, Features::fmt_debug), - (sym::emscripten_wasm_eh, sym::cfg_emscripten_wasm_eh, Features::cfg_emscripten_wasm_eh), ( sym::target_has_reliable_f16, sym::cfg_target_has_reliable_f16_f128, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 388482209cf9e..3040d016195d5 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -250,8 +250,6 @@ declare_features! ( (internal, allow_internal_unstable, "1.0.0", None), /// Allows using anonymous lifetimes in argument-position impl-trait. (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), - /// Allows access to the emscripten_wasm_eh config, used by panic_unwind and unwind - (internal, cfg_emscripten_wasm_eh, "1.86.0", None), /// Allows checking whether or not the backend correctly supports unstable float types. (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None), /// Allows identifying the `compiler_builtins` crate. diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs index 4a3615e5421fe..2069b746b5a7f 100644 --- a/compiler/rustc_hir/src/lang_items.rs +++ b/compiler/rustc_hir/src/lang_items.rs @@ -332,7 +332,6 @@ language_item_table! { Start, sym::start, start_fn, Target::Fn, GenericRequirement::Exact(1); EhPersonality, sym::eh_personality, eh_personality, Target::Fn, GenericRequirement::None; - EhCatchTypeinfo, sym::eh_catch_typeinfo, eh_catch_typeinfo, Target::Static, GenericRequirement::None; // Profiling markers for move/copy operations (used by -Z annotate-moves) CompilerMove, sym::compiler_move, compiler_move_fn, Target::Fn, GenericRequirement::Exact(2); diff --git a/compiler/rustc_hir/src/weak_lang_items.rs b/compiler/rustc_hir/src/weak_lang_items.rs index b4e548effd46d..85b0e3958c2d6 100644 --- a/compiler/rustc_hir/src/weak_lang_items.rs +++ b/compiler/rustc_hir/src/weak_lang_items.rs @@ -26,5 +26,4 @@ macro_rules! weak_lang_items { weak_lang_items! { PanicImpl, rust_begin_unwind; EhPersonality, rust_eh_personality; - EhCatchTypeinfo, rust_eh_catch_typeinfo; } diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0498d835df5f5..fc124348a202c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -791,7 +791,6 @@ fn test_unstable_options_tracking_hash() { tracked!(dwarf_version, Some(5)); tracked!(embed_metadata, false); tracked!(embed_source, true); - tracked!(emscripten_wasm_eh, false); tracked!(export_executable_symbols, true); tracked!(fewer_names, Some(true)); tracked!(fixed_x18, true); diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index 8a2595e2938b8..07153d688d477 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -109,13 +109,11 @@ impl<'tcx> TyCtxt<'tcx> { /// the case of panic=abort. In these situations some lang items are injected by /// crates and don't actually need to be defined in libstd. pub fn required(tcx: TyCtxt<'_>, lang_item: LangItem) -> bool { - // If we're not compiling with unwinding, we won't actually need these - // symbols. Other panic runtimes ensure that the relevant symbols are + // If we're not compiling with unwinding, we won't actually need this + // symbol. Other panic runtimes ensure that the relevant symbols are // available to link things together, but they're never exercised. match tcx.sess.panic_strategy() { - PanicStrategy::Abort => { - lang_item != LangItem::EhPersonality && lang_item != LangItem::EhCatchTypeinfo - } + PanicStrategy::Abort => lang_item != LangItem::EhPersonality, PanicStrategy::Unwind => true, PanicStrategy::ImmediateAbort => false, } diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index 4200003ea1d1a..2d5eee183aec4 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -8,7 +8,6 @@ use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_session::config::CrateType; -use rustc_target::spec::Os; use crate::errors::{ MissingLangItem, MissingPanicHandler, PanicUnwindWithoutStd, UnknownExternLangItem, @@ -22,18 +21,12 @@ pub(crate) fn check_crate( items: &mut lang_items::LanguageItems, krate: &ast::Crate, ) { - // These are never called by user code, they're generated by the compiler. - // They will never implicitly be added to the `missing` array unless we do - // so here. + // This is never called by user code, it's generated by the compiler. It + // will never implicitly be added to the `missing` array unless we do so + // here. if items.eh_personality().is_none() { items.missing.push(LangItem::EhPersonality); } - if tcx.sess.target.os == Os::Emscripten - && items.eh_catch_typeinfo().is_none() - && !tcx.sess.opts.unstable_opts.emscripten_wasm_eh - { - items.missing.push(LangItem::EhCatchTypeinfo); - } visit::Visitor::visit_crate(&mut WeakLangItemVisitor { tcx, items }, krate); diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index d16ab59a02d9e..cd301bea4eebf 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -157,7 +157,6 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { | (sym::target_has_reliable_f128_math, None | Some(_)) | (sym::target_thread_local, None) => disallow(cfg, "--target"), (sym::fmt_debug, None | Some(_)) => disallow(cfg, "-Z fmt-debug"), - (sym::emscripten_wasm_eh, None | Some(_)) => disallow(cfg, "-Z emscripten_wasm_eh"), _ => {} } } @@ -322,11 +321,6 @@ pub(crate) fn default_configuration(sess: &Session) -> Cfg { ins_none!(sym::ub_checks); } - // Nightly-only implementation detail for the `panic_unwind` and `unwind` crates. - if sess.is_nightly_build() && sess.opts.unstable_opts.emscripten_wasm_eh { - ins_none!(sym::emscripten_wasm_eh); - } - if sess.contract_checks() { ins_none!(sym::contract_checks); } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index de606458d048e..57db7a3eba3b7 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2315,8 +2315,6 @@ options! { "embed source text in DWARF debug sections (default: no)"), emit_stack_sizes: bool = (false, parse_bool, [UNTRACKED], "emit a section containing stack size metadata (default: no)"), - emscripten_wasm_eh: bool = (true, parse_bool, [TRACKED], - "Use WebAssembly error handling for wasm32-unknown-emscripten"), enforce_type_length_limit: bool = (false, parse_bool, [TRACKED], "enforce the type length limit when monomorphizing instances in codegen"), experimental_default_bounds: bool = (false, parse_bool, [TRACKED], diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 7263680c302f1..cf295142d36b1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -577,7 +577,6 @@ symbols! { cfg_boolean_literals, cfg_contract_checks, cfg_doctest, - cfg_emscripten_wasm_eh, cfg_eval, cfg_overflow_checks, cfg_panic, @@ -854,7 +853,6 @@ symbols! { edition_panic, effective_target_features, effects, - eh_catch_typeinfo, eh_personality, eii, eii_declaration, @@ -871,7 +869,6 @@ symbols! { // to be detected if it accidentally does get used. empty: "", empty_braces: "{}", - emscripten_wasm_eh, enable, end, entry_nops, @@ -1701,7 +1698,6 @@ symbols! { rust_analyzer, rust_begin_unwind, rust_cold_cc, - rust_eh_catch_typeinfo, rust_eh_personality, rust_future, rust_logo, diff --git a/library/panic_abort/src/lib.rs b/library/panic_abort/src/lib.rs index d1706b6525295..e62d758e9e5d1 100644 --- a/library/panic_abort/src/lib.rs +++ b/library/panic_abort/src/lib.rs @@ -49,46 +49,3 @@ pub unsafe fn __rust_start_panic(_payload: &mut dyn PanicPayload) -> u32 { __rust_abort() } - -// This... is a bit of an oddity. The tl;dr; is that this is required to link -// correctly, the longer explanation is below. -// -// Right now the binaries of core/std that we ship are all compiled with -// `-C panic=unwind`. This is done to ensure that the binaries are maximally -// compatible with as many situations as possible. The compiler, however, -// requires a "personality function" for all functions compiled with `-C -// panic=unwind`. This personality function is hardcoded to the symbol -// `rust_eh_personality` and is defined by the `eh_personality` lang item. -// -// So... why not just define that lang item here? Good question! The way that -// panic runtimes are linked in is actually a little subtle in that they're -// "sort of" in the compiler's crate store, but only actually linked if another -// isn't actually linked. This ends up meaning that both this crate and the -// panic_unwind crate can appear in the compiler's crate store, and if both -// define the `eh_personality` lang item then that'll hit an error. -// -// To handle this the compiler only requires the `eh_personality` is defined if -// the panic runtime being linked in is the unwinding runtime, and otherwise -// it's not required to be defined (rightfully so). In this case, however, this -// library just defines this symbol so there's at least some personality -// somewhere. -// -// Essentially this symbol is just defined to get wired up to core/std -// binaries, but it should never be called as we don't link in an unwinding -// runtime at all. -pub mod personalities { - // In the past this module used to contain stubs for the personality - // functions of various platforms, but these where removed when personality - // functions were moved to std. - - // This corresponds to the `eh_catch_typeinfo` lang item - // that's only used on Emscripten currently. - // - // Since panics don't generate exceptions and foreign exceptions are - // currently UB with -C panic=abort (although this may be subject to - // change), any catch_unwind calls will never use this typeinfo. - #[rustc_std_internal_symbol] - #[allow(non_upper_case_globals)] - #[cfg(target_os = "emscripten")] - static rust_eh_catch_typeinfo: [usize; 2] = [0; 2]; -} diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 67fc919c42c2b..72c1041b46795 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -18,7 +18,3 @@ unwind = { path = "../unwind" } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2", default-features = false } - -[lints.rust.unexpected_cfgs] -level = "warn" -check-cfg = ['cfg(emscripten_wasm_eh)'] diff --git a/library/panic_unwind/src/emcc.rs b/library/panic_unwind/src/emcc.rs deleted file mode 100644 index bad795a019c9a..0000000000000 --- a/library/panic_unwind/src/emcc.rs +++ /dev/null @@ -1,135 +0,0 @@ -//! Unwinding for *emscripten* target. -//! -//! Whereas Rust's usual unwinding implementation for Unix platforms -//! calls into the libunwind APIs directly, on Emscripten we instead -//! call into the C++ unwinding APIs. This is just an expedience since -//! Emscripten's runtime always implements those APIs and does not -//! implement libunwind. - -use alloc::boxed::Box; -use core::any::Any; -use core::sync::atomic::{AtomicBool, Ordering}; -use core::{intrinsics, ptr}; - -use unwind as uw; - -// This matches the layout of std::type_info in C++ -#[repr(C)] -struct TypeInfo { - vtable: *const usize, - name: *const u8, -} -unsafe impl Sync for TypeInfo {} - -unsafe extern "C" { - // The leading `\x01` byte here is actually a magical signal to LLVM to - // *not* apply any other mangling like prefixing with a `_` character. - // - // This symbol is the vtable used by C++'s `std::type_info`. Objects of type - // `std::type_info`, type descriptors, have a pointer to this table. Type - // descriptors are referenced by the C++ EH structures defined above and - // that we construct below. - // - // Note that the real size is larger than 3 usize, but we only need our - // vtable to point to the third element. - #[link_name = "\x01_ZTVN10__cxxabiv117__class_type_infoE"] - static CLASS_TYPE_INFO_VTABLE: [usize; 3]; -} - -// std::type_info for a rust_panic class -#[lang = "eh_catch_typeinfo"] -static EXCEPTION_TYPE_INFO: TypeInfo = TypeInfo { - // Normally we would use .as_ptr().add(2) but this doesn't work in a const context. - vtable: unsafe { &CLASS_TYPE_INFO_VTABLE[2] }, - // This intentionally doesn't use the normal name mangling scheme because - // we don't want C++ to be able to produce or catch Rust panics. - name: b"rust_panic\0".as_ptr(), -}; - -// NOTE(nbdd0121): The `canary` field is part of stable ABI. -#[repr(C)] -struct Exception { - // See `gcc.rs` on why this is present. We already have a static here so just use it. - canary: *const TypeInfo, - - // This is necessary because C++ code can capture our exception with - // std::exception_ptr and rethrow it multiple times, possibly even in - // another thread. - caught: AtomicBool, - - // This needs to be an Option because the object's lifetime follows C++ - // semantics: when catch_unwind moves the Box out of the exception it must - // still leave the exception object in a valid state because its destructor - // is still going to be called by __cxa_end_catch. - data: Option>, -} - -pub(crate) unsafe fn cleanup(ptr: *mut u8) -> Box { - // intrinsics::try actually gives us a pointer to this structure. - #[repr(C)] - struct CatchData { - ptr: *mut u8, - is_rust_panic: bool, - } - unsafe { - let catch_data = &*(ptr as *mut CatchData); - - let adjusted_ptr = __cxa_begin_catch(catch_data.ptr as *mut libc::c_void) as *mut Exception; - if !catch_data.is_rust_panic { - super::__rust_foreign_exception(); - } - - let canary = (&raw const (*adjusted_ptr).canary).read(); - if !ptr::eq(canary, &EXCEPTION_TYPE_INFO) { - super::__rust_foreign_exception(); - } - - let was_caught = (*adjusted_ptr).caught.swap(true, Ordering::Relaxed); - if was_caught { - // Since cleanup() isn't allowed to panic, we just abort instead. - intrinsics::abort(); - } - let out = (*adjusted_ptr).data.take().unwrap(); - __cxa_end_catch(); - out - } -} - -pub(crate) unsafe fn panic(data: Box) -> u32 { - unsafe { - let exception = __cxa_allocate_exception(size_of::()) as *mut Exception; - if exception.is_null() { - return uw::_URC_FATAL_PHASE1_ERROR as u32; - } - ptr::write( - exception, - Exception { - canary: &EXCEPTION_TYPE_INFO, - caught: AtomicBool::new(false), - data: Some(data), - }, - ); - __cxa_throw(exception as *mut _, &EXCEPTION_TYPE_INFO, exception_cleanup); - } -} - -extern "C" fn exception_cleanup(ptr: *mut libc::c_void) -> *mut libc::c_void { - unsafe { - if let Some(b) = (ptr as *mut Exception).read().data { - drop(b); - super::__rust_drop_panic(); - } - ptr - } -} - -unsafe extern "C" { - fn __cxa_allocate_exception(thrown_size: libc::size_t) -> *mut libc::c_void; - fn __cxa_begin_catch(thrown_exception: *mut libc::c_void) -> *mut libc::c_void; - fn __cxa_end_catch(); - fn __cxa_throw( - thrown_exception: *mut libc::c_void, - tinfo: *const TypeInfo, - dest: extern "C" fn(*mut libc::c_void) -> *mut libc::c_void, - ) -> !; -} diff --git a/library/panic_unwind/src/lib.rs b/library/panic_unwind/src/lib.rs index fc0a627d293f3..9d204a150dd45 100644 --- a/library/panic_unwind/src/lib.rs +++ b/library/panic_unwind/src/lib.rs @@ -2,11 +2,12 @@ //! //! This crate is an implementation of panics in Rust using "most native" stack //! unwinding mechanism of the platform this is being compiled for. This -//! essentially gets categorized into three buckets currently: +//! essentially gets categorized into four buckets currently: //! -//! 1. MSVC targets use SEH in the `seh.rs` file. -//! 2. Emscripten uses C++ exceptions in the `emcc.rs` file. -//! 3. All other targets use libunwind/libgcc in the `gcc.rs` file. +//! 1. When running inside miri, MSVC targets use Miri intrinsics in the `miri.rs` file. +//! 2. MSVC targets use SEH in the `seh.rs` file. +//! 3. Some targets use an aborting implementation in the `dummy.rs` or `hermit.rs` files. +//! 4. All other targets use libunwind/libgcc in the `gcc.rs` file. //! //! More documentation about each implementation can be found in the respective //! module. @@ -14,8 +15,6 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] #![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] -#![cfg_attr(all(target_os = "emscripten", not(emscripten_wasm_eh)), feature(lang_items))] -#![feature(cfg_emscripten_wasm_eh)] #![feature(core_intrinsics)] #![feature(panic_unwind)] #![feature(staged_api)] @@ -33,10 +32,6 @@ use core::any::Any; use core::panic::PanicPayload; cfg_select! { - all(target_os = "emscripten", not(emscripten_wasm_eh)) => { - #[path = "emcc.rs"] - mod imp; - } target_os = "hermit" => { #[path = "hermit.rs"] mod imp; diff --git a/library/unwind/Cargo.toml b/library/unwind/Cargo.toml index f02744a107082..1293c469d11c1 100644 --- a/library/unwind/Cargo.toml +++ b/library/unwind/Cargo.toml @@ -35,4 +35,4 @@ system-llvm-libunwind = [] [lints.rust.unexpected_cfgs] level = "warn" -check-cfg = ['cfg(emscripten_wasm_eh)', 'cfg(target_arch, values("loongarch32"))'] +check-cfg = ['cfg(target_arch, values("loongarch32"))'] diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 22568d5f6f1f9..4e380d8894781 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -1,10 +1,9 @@ #![no_std] #![unstable(feature = "panic_unwind", issue = "32837")] -#![feature(cfg_emscripten_wasm_eh)] #![feature(link_cfg)] #![feature(staged_api)] #![cfg_attr( - all(target_family = "wasm", any(not(target_os = "emscripten"), emscripten_wasm_eh)), + target_family = "wasm", feature(link_llvm_intrinsics, simd_wasm64, asm_experimental_arch) )] #![allow(internal_features)] diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md index d5e3125fd3c79..0d15097468b17 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -160,8 +160,7 @@ which features are enabled. Note that Rust code compiled for `wasm32-unknown-emscripten` currently enables `-fwasm-exceptions` (legacy WASM exceptions) by default unless the Rust code is -compiled with `-Cpanic=abort`. It is possible to use JS exceptions by passing -the flag ``-Z emscripten-wasm-eh=false`` but this will be removed in the future. +compiled with `-Cpanic=abort`. Please refer to the [Emscripten ABI compatibility](#emscripten-abi-compatibility) section to ensure that the features that are enabled do not cause an ABI mismatch diff --git a/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md b/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md deleted file mode 100644 index eab29a1744b67..0000000000000 --- a/src/doc/unstable-book/src/compiler-flags/emscripten-wasm-eh.md +++ /dev/null @@ -1,6 +0,0 @@ -# `emscripten-wasm-eh` - -Use the WebAssembly exception handling ABI to unwind for the -`wasm32-unknown-emscripten`. If compiling with this setting, the `emcc` linker -should be invoked with `-fwasm-exceptions`. If linking with C/C++ files, the -C/C++ files should also be compiled with `-fwasm-exceptions`. diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index ee4d976dfd246..deb7fbca716c3 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -27,8 +27,7 @@ Some features provided by lang items: failure mechanisms of the compiler. This is often mapped to GCC's personality function (see the [`std` implementation][personality] for more information), but programs which don't trigger a panic can be assured that this function is - never called. Additionally, a `eh_catch_typeinfo` static is needed for certain - targets which implement Rust panics on top of C++ exceptions. + never called. - the traits in `core::marker` used to indicate types of various kinds; e.g. lang items `sized`, `sync` and `copy`. - memory allocation, see below. diff --git a/tests/codegen-llvm/emscripten-catch-unwind-js-eh.rs b/tests/codegen-llvm/emscripten-catch-unwind-js-eh.rs deleted file mode 100644 index 4f62d3e56a787..0000000000000 --- a/tests/codegen-llvm/emscripten-catch-unwind-js-eh.rs +++ /dev/null @@ -1,71 +0,0 @@ -//@ compile-flags: -Copt-level=3 --target wasm32-unknown-emscripten -Z emscripten-wasm-eh=false -//@ needs-llvm-components: webassembly - -// Emscripten has its own unique implementation of catch_unwind (in `codegen_emcc_try`), -// make sure it generates something reasonable. - -#![feature(no_core, lang_items, intrinsics, rustc_attrs)] -#![crate_type = "lib"] -#![no_std] -#![no_core] - -#[lang = "pointee_sized"] -pub trait PointeeSized {} - -#[lang = "meta_sized"] -pub trait MetaSized: PointeeSized {} - -#[lang = "sized"] -pub trait Sized: MetaSized {} -#[lang = "freeze"] -trait Freeze {} -#[lang = "copy"] -trait Copy {} - -impl Copy for *mut T {} - -#[rustc_intrinsic] -const fn size_of() -> usize { - loop {} -} - -#[rustc_intrinsic] -unsafe fn catch_unwind( - try_fn: unsafe fn(_: *mut Data), - data: *mut Data, - catch_fn: unsafe fn(_: *mut Data, _: *mut u8), -) -> bool; - -// CHECK-LABEL: @ptr_size -#[no_mangle] -pub fn ptr_size() -> usize { - // CHECK: ret [[PTR_SIZE:.*]] - const { size_of::<*mut u8>() } -} - -// CHECK-LABEL: @test_catch_unwind -#[no_mangle] -pub unsafe fn test_catch_unwind( - try_fn: unsafe fn(_: *mut u8), - data: *mut u8, - catch_fn: unsafe fn(_: *mut u8, _: *mut u8), -) -> bool { - // CHECK: start: - // CHECK: [[ALLOCA:%.*]] = alloca - - // CHECK: catch.i: - // CHECK: [[LANDINGPAD:%.*]] = landingpad - // CHECK: [[EXCEPTION:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 0 - // CHECK: [[SELECTOR:%.*]] = extractvalue {{.*}} [[LANDINGPAD]], 1 - - // CHECK: [[IS_RUST_EXN:%.*]] = icmp eq {{.*}}[[SELECTOR]] - // CHECK: [[IS_RUST_EXN_I8:%.*]] = zext i1 [[IS_RUST_EXN]] to i8 - - // CHECK: store ptr [[EXCEPTION]], ptr [[ALLOCA]] - // CHECK: [[IS_RUST_SLOT:%.*]] = getelementptr inbounds{{( nuw)?}} i8, ptr [[ALLOCA]], [[PTR_SIZE]] - // CHECK: store i8 [[IS_RUST_EXN_I8]], ptr [[IS_RUST_SLOT]] - - // CHECK: call void %catch_fn(ptr %data, ptr nonnull [[ALLOCA]]) - - catch_unwind(try_fn, data, catch_fn) -} diff --git a/tests/codegen-llvm/emscripten-catch-unwind-wasm-eh.rs b/tests/codegen-llvm/emscripten-catch-unwind.rs similarity index 96% rename from tests/codegen-llvm/emscripten-catch-unwind-wasm-eh.rs rename to tests/codegen-llvm/emscripten-catch-unwind.rs index 25ac3181ba3b2..b3af16c4ed0ee 100644 --- a/tests/codegen-llvm/emscripten-catch-unwind-wasm-eh.rs +++ b/tests/codegen-llvm/emscripten-catch-unwind.rs @@ -1,7 +1,7 @@ -//@ compile-flags: -Copt-level=3 --target wasm32-unknown-emscripten -Z emscripten-wasm-eh +//@ compile-flags: -Copt-level=3 --target wasm32-unknown-emscripten //@ needs-llvm-components: webassembly -// Emscripten catch_unwind using wasm exceptions +// Emscripten catch_unwind #![feature(no_core, lang_items, intrinsics, rustc_attrs)] #![crate_type = "lib"] diff --git a/tests/codegen-llvm/terminating-catchpad.rs b/tests/codegen-llvm/terminating-catchpad.rs index 7c98ea94fdc13..cea5d48ab99e5 100644 --- a/tests/codegen-llvm/terminating-catchpad.rs +++ b/tests/codegen-llvm/terminating-catchpad.rs @@ -1,5 +1,5 @@ //@ revisions: emscripten wasi seh -//@[emscripten] compile-flags: --target wasm32-unknown-emscripten -Z emscripten-wasm-eh +//@[emscripten] compile-flags: --target wasm32-unknown-emscripten //@[wasi] compile-flags: --target wasm32-wasip1 -C panic=unwind //@[seh] compile-flags: --target x86_64-pc-windows-msvc //@[emscripten] needs-llvm-components: webassembly diff --git a/tests/codegen-llvm/wasm_exceptions.rs b/tests/codegen-llvm/wasm_exceptions.rs index 48c9c0b50e3fb..b4c024e4ed0e6 100644 --- a/tests/codegen-llvm/wasm_exceptions.rs +++ b/tests/codegen-llvm/wasm_exceptions.rs @@ -1,6 +1,6 @@ //@ only-wasm32 //@ revisions: WASM WASMEXN -//@ [WASMEXN] compile-flags: -C panic=unwind -Z emscripten-wasm-eh +//@ [WASMEXN] compile-flags: -C panic=unwind #![crate_type = "lib"] #![feature(core_intrinsics, link_llvm_intrinsics)] diff --git a/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr b/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr deleted file mode 100644 index 8b2ee0e5c0c3d..0000000000000 --- a/tests/ui/cfg/disallowed-cli-cfgs.emscripten_wasm_eh_.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: unexpected `--cfg emscripten_wasm_eh` flag - | - = note: config `emscripten_wasm_eh` is only supposed to be controlled by `-Z emscripten_wasm_eh` - = note: manually setting a built-in cfg can and does create incoherent behaviors - = note: `#[deny(explicit_builtin_cfgs_in_flags)]` on by default - -error: aborting due to 1 previous error - diff --git a/tests/ui/cfg/disallowed-cli-cfgs.rs b/tests/ui/cfg/disallowed-cli-cfgs.rs index 81f3d9313ef1f..57aed0016e971 100644 --- a/tests/ui/cfg/disallowed-cli-cfgs.rs +++ b/tests/ui/cfg/disallowed-cli-cfgs.rs @@ -9,7 +9,6 @@ //@ revisions: target_has_atomic_ target_has_atomic_primitive_alignment_ //@ revisions: target_has_atomic_load_store_ target_thread_local_ relocation_model_ //@ revisions: fmt_debug_ -//@ revisions: emscripten_wasm_eh_ //@ revisions: reliable_f16_ reliable_f16_math_ reliable_f128_ reliable_f128_math_ //@ [overflow_checks_]compile-flags: --cfg overflow_checks @@ -38,7 +37,6 @@ //@ [target_thread_local_]compile-flags: --cfg target_thread_local //@ [relocation_model_]compile-flags: --cfg relocation_model="a" //@ [fmt_debug_]compile-flags: --cfg fmt_debug="shallow" -//@ [emscripten_wasm_eh_]compile-flags: --cfg emscripten_wasm_eh //@ [reliable_f16_]compile-flags: --cfg target_has_reliable_f16 //@ [reliable_f16_math_]compile-flags: --cfg target_has_reliable_f16_math //@ [reliable_f128_]compile-flags: --cfg target_has_reliable_f128 diff --git a/tests/ui/consts/const-eval/const_panic_libcore_bin.rs b/tests/ui/consts/const-eval/const_panic_libcore_bin.rs index 90ae5165d233b..d6fbdb28d56a2 100644 --- a/tests/ui/consts/const-eval/const_panic_libcore_bin.rs +++ b/tests/ui/consts/const-eval/const_panic_libcore_bin.rs @@ -16,8 +16,6 @@ const X: () = unimplemented!(); #[lang = "eh_personality"] fn eh() {} -#[lang = "eh_catch_typeinfo"] -static EH_CATCH_TYPEINFO: u8 = 0; #[panic_handler] fn panic(_info: &PanicInfo) -> ! { diff --git a/tests/ui/extern-flag/empty-extern-arg.rs b/tests/ui/extern-flag/empty-extern-arg.rs index 10cc3be71135e..d57edc6041247 100644 --- a/tests/ui/extern-flag/empty-extern-arg.rs +++ b/tests/ui/extern-flag/empty-extern-arg.rs @@ -2,7 +2,6 @@ //~^ ERROR cannot resolve a prelude import //@ compile-flags: --extern std= //@ needs-unwind since it affects the error output -//@ ignore-emscripten missing eh_catch_typeinfo lang item fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs deleted file mode 100644 index a13e7fa317f5b..0000000000000 --- a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ compile-flags: --check-cfg=cfg(emscripten_wasm_eh) -#[cfg(emscripten_wasm_eh)] -//~^ ERROR `cfg(emscripten_wasm_eh)` is experimental -fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr b/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr deleted file mode 100644 index a829c9b93a566..0000000000000 --- a/tests/ui/feature-gates/feature-gate-cfg-emscripten-wasm-eh.stderr +++ /dev/null @@ -1,12 +0,0 @@ -error[E0658]: `cfg(emscripten_wasm_eh)` is experimental and subject to change - --> $DIR/feature-gate-cfg-emscripten-wasm-eh.rs:2:7 - | -LL | #[cfg(emscripten_wasm_eh)] - | ^^^^^^^^^^^^^^^^^^ - | - = help: add `#![feature(cfg_emscripten_wasm_eh)]` 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: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/macro-comma-behavior.core.stderr b/tests/ui/macros/macro-comma-behavior.core.stderr index ac15e9fa8ea83..e84a33d1f8dee 100644 --- a/tests/ui/macros/macro-comma-behavior.core.stderr +++ b/tests/ui/macros/macro-comma-behavior.core.stderr @@ -1,47 +1,47 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:21:23 + --> $DIR/macro-comma-behavior.rs:20:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:24:23 + --> $DIR/macro-comma-behavior.rs:23:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:29 + --> $DIR/macro-comma-behavior.rs:29:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:33:29 + --> $DIR/macro-comma-behavior.rs:32:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:52:19 + --> $DIR/macro-comma-behavior.rs:51:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:68:21 + --> $DIR/macro-comma-behavior.rs:67:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:77:24 + --> $DIR/macro-comma-behavior.rs:76:24 | LL | write!(f, "{}",)?; | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:26 + --> $DIR/macro-comma-behavior.rs:80:26 | LL | writeln!(f, "{}",)?; | ^^ diff --git a/tests/ui/macros/macro-comma-behavior.rs b/tests/ui/macros/macro-comma-behavior.rs index ea75fdd6842e1..5085f3c9cf83c 100644 --- a/tests/ui/macros/macro-comma-behavior.rs +++ b/tests/ui/macros/macro-comma-behavior.rs @@ -9,7 +9,6 @@ #[cfg(std)] use std::fmt; #[cfg(core)] use core::fmt; #[cfg(core)] #[lang = "eh_personality"] fn eh_personality() {} -#[cfg(core)] #[lang = "eh_catch_typeinfo"] static EH_CATCH_TYPEINFO: u8 = 0; #[cfg(core)] #[panic_handler] fn panic_impl(panic: &core::panic::PanicInfo) -> ! { loop {} } // (see documentation of the similarly-named test in run-pass) diff --git a/tests/ui/macros/macro-comma-behavior.std.stderr b/tests/ui/macros/macro-comma-behavior.std.stderr index 7fd060e222498..e29737e0522a4 100644 --- a/tests/ui/macros/macro-comma-behavior.std.stderr +++ b/tests/ui/macros/macro-comma-behavior.std.stderr @@ -1,77 +1,77 @@ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:21:23 + --> $DIR/macro-comma-behavior.rs:20:23 | LL | assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:24:23 + --> $DIR/macro-comma-behavior.rs:23:23 | LL | assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:30:29 + --> $DIR/macro-comma-behavior.rs:29:29 | LL | debug_assert_eq!(1, 1, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:33:29 + --> $DIR/macro-comma-behavior.rs:32:29 | LL | debug_assert_ne!(1, 2, "{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:38:18 + --> $DIR/macro-comma-behavior.rs:37:18 | LL | eprint!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:43:20 + --> $DIR/macro-comma-behavior.rs:42:20 | LL | eprintln!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:48:18 + --> $DIR/macro-comma-behavior.rs:47:18 | LL | format!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:52:19 + --> $DIR/macro-comma-behavior.rs:51:19 | LL | format_args!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:59:17 + --> $DIR/macro-comma-behavior.rs:58:17 | LL | print!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:64:19 + --> $DIR/macro-comma-behavior.rs:63:19 | LL | println!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:68:21 + --> $DIR/macro-comma-behavior.rs:67:21 | LL | unimplemented!("{}",); | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:77:24 + --> $DIR/macro-comma-behavior.rs:76:24 | LL | write!(f, "{}",)?; | ^^ error: 1 positional argument in format string, but no arguments were given - --> $DIR/macro-comma-behavior.rs:81:26 + --> $DIR/macro-comma-behavior.rs:80:26 | LL | writeln!(f, "{}",)?; | ^^ diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs index a8f7aadf6c722..43a235fd6b418 100644 --- a/tests/ui/panic-handler/weak-lang-item.rs +++ b/tests/ui/panic-handler/weak-lang-item.rs @@ -1,7 +1,6 @@ //@ edition:2015 //@ aux-build:weak-lang-items.rs //@ needs-unwind since it affects the error output -//@ ignore-emscripten missing eh_catch_typeinfo lang item #![no_std] diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr index eb5f4ad56ea31..5acd3e3187051 100644 --- a/tests/ui/panic-handler/weak-lang-item.stderr +++ b/tests/ui/panic-handler/weak-lang-item.stderr @@ -1,5 +1,5 @@ error[E0259]: the name `core` is defined multiple times - --> $DIR/weak-lang-item.rs:8:1 + --> $DIR/weak-lang-item.rs:7:1 | LL | extern crate core; | ^^^^^^^^^^^^^^^^^^ `core` reimported here diff --git a/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs b/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs index 44137b85748fa..1a4346a410b47 100644 --- a/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs +++ b/tests/ui/panic-runtime/auxiliary/panic-runtime-lang-items.rs @@ -11,5 +11,3 @@ use core::panic::PanicInfo; fn panic_impl(info: &PanicInfo) -> ! { loop {} } #[lang = "eh_personality"] fn eh_personality() {} -#[lang = "eh_catch_typeinfo"] -static EH_CATCH_TYPEINFO: u8 = 0; diff --git a/tests/ui/range/issue-54505-no-std.rs b/tests/ui/range/issue-54505-no-std.rs index 0c913f766b709..6ddfc7e231464 100644 --- a/tests/ui/range/issue-54505-no-std.rs +++ b/tests/ui/range/issue-54505-no-std.rs @@ -12,9 +12,6 @@ use core::ops::RangeBounds; #[cfg(any(not(target_arch = "wasm32"), target_os = "emscripten"))] #[lang = "eh_personality"] extern "C" fn eh_personality() {} -#[cfg(target_os = "emscripten")] -#[lang = "eh_catch_typeinfo"] -static EH_CATCH_TYPEINFO: u8 = 0; #[panic_handler] fn panic_handler(_: &core::panic::PanicInfo) -> ! { diff --git a/tests/ui/range/issue-54505-no-std.stderr b/tests/ui/range/issue-54505-no-std.stderr index 866a82afb7e2f..456f9454e5404 100644 --- a/tests/ui/range/issue-54505-no-std.stderr +++ b/tests/ui/range/issue-54505-no-std.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:29:16 + --> $DIR/issue-54505-no-std.rs:26:16 | LL | take_range(0..1); | ---------- ^^^^ expected `&_`, found `Range<{integer}>` @@ -9,7 +9,7 @@ LL | take_range(0..1); = note: expected reference `&_` found struct `core::ops::Range<{integer}>` note: function defined here - --> $DIR/issue-54505-no-std.rs:25:4 + --> $DIR/issue-54505-no-std.rs:22:4 | LL | fn take_range(_r: &impl RangeBounds) {} | ^^^^^^^^^^ ------------------------- @@ -19,7 +19,7 @@ LL | take_range(&(0..1)); | ++ + error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:34:16 + --> $DIR/issue-54505-no-std.rs:31:16 | LL | take_range(1..); | ---------- ^^^ expected `&_`, found `RangeFrom<{integer}>` @@ -29,7 +29,7 @@ LL | take_range(1..); = note: expected reference `&_` found struct `core::ops::RangeFrom<{integer}>` note: function defined here - --> $DIR/issue-54505-no-std.rs:25:4 + --> $DIR/issue-54505-no-std.rs:22:4 | LL | fn take_range(_r: &impl RangeBounds) {} | ^^^^^^^^^^ ------------------------- @@ -39,7 +39,7 @@ LL | take_range(&(1..)); | ++ + error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:39:16 + --> $DIR/issue-54505-no-std.rs:36:16 | LL | take_range(..); | ---------- ^^ expected `&_`, found `RangeFull` @@ -49,12 +49,12 @@ LL | take_range(..); = note: expected reference `&_` found struct `RangeFull` note: function defined here - --> $DIR/issue-54505-no-std.rs:25:4 + --> $DIR/issue-54505-no-std.rs:22:4 | LL | fn take_range(_r: &impl RangeBounds) {} | ^^^^^^^^^^ ------------------------- help: you might have meant to use `..` to skip providing a value for expected fields, but this is only supported on non-tuple struct literals when `#![feature(default_field_values)]` is enabled; it is instead interpreted as a `std::ops::RangeFull` literal - --> $DIR/issue-54505-no-std.rs:39:16 + --> $DIR/issue-54505-no-std.rs:36:16 | LL | take_range(..); | ^^ @@ -64,7 +64,7 @@ LL | take_range(&(..)); | ++ + error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:45:16 + --> $DIR/issue-54505-no-std.rs:42:16 | LL | take_range(0..=1); | ---------- ^^^^^ expected `&_`, found `RangeInclusive<{integer}>` @@ -74,7 +74,7 @@ LL | take_range(0..=1); = note: expected reference `&_` found struct `core::ops::RangeInclusive<{integer}>` note: function defined here - --> $DIR/issue-54505-no-std.rs:25:4 + --> $DIR/issue-54505-no-std.rs:22:4 | LL | fn take_range(_r: &impl RangeBounds) {} | ^^^^^^^^^^ ------------------------- @@ -84,7 +84,7 @@ LL | take_range(&(0..=1)); | ++ + error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:50:16 + --> $DIR/issue-54505-no-std.rs:47:16 | LL | take_range(..5); | ---------- ^^^ expected `&_`, found `RangeTo<{integer}>` @@ -94,7 +94,7 @@ LL | take_range(..5); = note: expected reference `&_` found struct `RangeTo<{integer}>` note: function defined here - --> $DIR/issue-54505-no-std.rs:25:4 + --> $DIR/issue-54505-no-std.rs:22:4 | LL | fn take_range(_r: &impl RangeBounds) {} | ^^^^^^^^^^ ------------------------- @@ -104,7 +104,7 @@ LL | take_range(&(..5)); | ++ + error[E0308]: mismatched types - --> $DIR/issue-54505-no-std.rs:55:16 + --> $DIR/issue-54505-no-std.rs:52:16 | LL | take_range(..=42); | ---------- ^^^^^ expected `&_`, found `RangeToInclusive<{integer}>` @@ -114,7 +114,7 @@ LL | take_range(..=42); = note: expected reference `&_` found struct `core::ops::RangeToInclusive<{integer}>` note: function defined here - --> $DIR/issue-54505-no-std.rs:25:4 + --> $DIR/issue-54505-no-std.rs:22:4 | LL | fn take_range(_r: &impl RangeBounds) {} | ^^^^^^^^^^ ------------------------- From 3a850decb23b38befecba1d0a81641df9ecbbb10 Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Tue, 2 Jun 2026 19:55:45 +0000 Subject: [PATCH 16/26] bootstrap: enable `clippy::mem_replace_with_default` --- src/bootstrap/src/core/build_steps/clippy.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/bootstrap/src/core/build_steps/clippy.rs b/src/bootstrap/src/core/build_steps/clippy.rs index 9e5bfd2e60e9c..d3b533c954293 100644 --- a/src/bootstrap/src/core/build_steps/clippy.rs +++ b/src/bootstrap/src/core/build_steps/clippy.rs @@ -607,6 +607,7 @@ impl Step for CI { "clippy::single_char_add_str".into(), "clippy::to_string_in_format_args".into(), "clippy::unconditional_recursion".into(), + "clippy::mem_replace_with_default".into(), ], forbid: vec![], }; From 3dacac8f4bb2d09de567e501c8b4a0d427b4d8a8 Mon Sep 17 00:00:00 2001 From: Jarl Evanson Date: Tue, 2 Jun 2026 20:37:47 +0000 Subject: [PATCH 17/26] compiler: fix `clippy::mem_replace_with_default` warnings --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_middle/src/dep_graph/serialized.rs | 2 +- compiler/rustc_span/src/lib.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 38bde976b1b02..37546d4aa056d 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1964,7 +1964,7 @@ impl Emitter for SharedEmitter { assert_eq!(diag.is_lint, None); // No sensible check for `diag.emitted_at`. - let args = mem::replace(&mut diag.args, DiagArgMap::default()); + let args = mem::take(&mut diag.args); drop( self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { span: diag.span.primary_spans().iter().map(|span| span.data()).collect::>(), diff --git a/compiler/rustc_middle/src/dep_graph/serialized.rs b/compiler/rustc_middle/src/dep_graph/serialized.rs index ef5e3d9268ad7..6d7f8e37e6c0a 100644 --- a/compiler/rustc_middle/src/dep_graph/serialized.rs +++ b/compiler/rustc_middle/src/dep_graph/serialized.rs @@ -738,7 +738,7 @@ impl EncoderState { // Prevent more indices from being allocated on this thread. local.remaining_node_index = 0; - let data = mem::replace(&mut local.encoder.data, Vec::new()); + let data = mem::take(&mut local.encoder.data); self.file.lock().as_mut().unwrap().emit_raw_bytes(&data); LocalEncoderResult { diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 2371bf15756da..13dea1657339e 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -2573,7 +2573,7 @@ fn normalize_newlines(src: &mut String, normalized_pos: &mut Vec) // directly, let's rather steal the contents of `src`. This makes the code // safe even if a panic occurs. - let mut buf = std::mem::replace(src, String::new()).into_bytes(); + let mut buf = std::mem::take(src).into_bytes(); let mut gap_len = 0; let mut tail = buf.as_mut_slice(); let mut cursor = 0; From c2b9f3955a25cd685184ee0168d7d1d7722d2d05 Mon Sep 17 00:00:00 2001 From: Mathis B <134849385+mathisbot@users.noreply.github.com> Date: Tue, 2 Jun 2026 19:48:58 +0100 Subject: [PATCH 18/26] windows: remove division-by-zero checks for performance counters this removes the panic path when dividing by the frequency. this also makes calls to Instant::now() faster. --- library/std/src/sys/pal/windows/time.rs | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/library/std/src/sys/pal/windows/time.rs b/library/std/src/sys/pal/windows/time.rs index b4b1d50a88896..2646ad28b84a2 100644 --- a/library/std/src/sys/pal/windows/time.rs +++ b/library/std/src/sys/pal/windows/time.rs @@ -20,7 +20,7 @@ pub fn intervals2dur(intervals: u64) -> Duration { pub mod perf_counter { use super::NANOS_PER_SEC; - use crate::sync::atomic::{Atomic, AtomicU64, Ordering}; + use crate::sync::atomic::{AtomicI64, Ordering}; use crate::sys::{c, cvt}; use crate::time::Duration; @@ -32,23 +32,32 @@ pub mod perf_counter { pub fn frequency() -> i64 { // Either the cached result of `QueryPerformanceFrequency` or `0` for - // uninitialized. Storing this as a single `AtomicU64` allows us to use + // uninitialized. Storing this as a single `AtomicI64` allows us to use // `Relaxed` operations, as we are only interested in the effects on a // single memory location. - static FREQUENCY: Atomic = AtomicU64::new(0); + static FREQUENCY: AtomicI64 = AtomicI64::new(0); let cached = FREQUENCY.load(Ordering::Relaxed); // If a previous thread has filled in this global state, use that. if cached != 0 { - return cached as i64; + return cached; } // ... otherwise learn for ourselves ... + frequency_init(&FREQUENCY) + } + + #[cold] + fn frequency_init(cache: &AtomicI64) -> i64 { let mut frequency = 0; unsafe { cvt(c::QueryPerformanceFrequency(&mut frequency)).unwrap(); } - FREQUENCY.store(frequency as u64, Ordering::Relaxed); + // SAFETY: According to the MSDN entry for `QueryPerformanceFrequency`, + // a value of 0 will never be returned starting from Windows XP. + unsafe { crate::hint::assert_unchecked(frequency != 0) } + + cache.store(frequency, Ordering::Relaxed); frequency } From fba47888ce9aec2673d776c434ba0cce6972c352 Mon Sep 17 00:00:00 2001 From: Luca Versari Date: Tue, 2 Jun 2026 11:41:43 +0200 Subject: [PATCH 19/26] Add more tests for the `optimize` attribute --- tests/ui/attributes/malformed-attrs.rs | 4 + tests/ui/attributes/malformed-attrs.stderr | 178 +++++++++++++-------- tests/ui/attributes/optimize.rs | 22 +++ tests/ui/attributes/optimize.stderr | 34 +++- 4 files changed, 168 insertions(+), 70 deletions(-) diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 8eb1f3bcfd346..7ada54310f08d 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -54,6 +54,10 @@ //~^ ERROR malformed #[optimize] //~^ ERROR malformed +#[optimize(none, none)] +//~^ ERROR malformed +#[optimize(none, speed)] +//~^ ERROR malformed #[cold = 1] //~^ ERROR malformed #[must_use()] diff --git a/tests/ui/attributes/malformed-attrs.stderr b/tests/ui/attributes/malformed-attrs.stderr index 4026c49295138..66cc6340be189 100644 --- a/tests/ui/attributes/malformed-attrs.stderr +++ b/tests/ui/attributes/malformed-attrs.stderr @@ -1,5 +1,5 @@ error[E0539]: malformed `cfg` attribute input - --> $DIR/malformed-attrs.rs:105:1 + --> $DIR/malformed-attrs.rs:109:1 | LL | #[cfg] | ^^^^^^ expected this to be a list @@ -11,7 +11,7 @@ LL | #[cfg(predicate)] | +++++++++++ error[E0539]: malformed `cfg_attr` attribute input - --> $DIR/malformed-attrs.rs:107:1 + --> $DIR/malformed-attrs.rs:111:1 | LL | #[cfg_attr] | ^^^^^^^^^^^ expected this to be a list @@ -23,13 +23,13 @@ LL | #[cfg_attr(predicate, attr1, attr2, ...)] | ++++++++++++++++++++++++++++++ error[E0463]: can't find crate for `wloop` - --> $DIR/malformed-attrs.rs:209:1 + --> $DIR/malformed-attrs.rs:213:1 | LL | extern crate wloop; | ^^^^^^^^^^^^^^^^^^^ can't find crate error: malformed `allow` attribute input - --> $DIR/malformed-attrs.rs:175:1 + --> $DIR/malformed-attrs.rs:179:1 | LL | #[allow] | ^^^^^^^^ @@ -45,7 +45,7 @@ LL | #[allow(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `expect` attribute input - --> $DIR/malformed-attrs.rs:177:1 + --> $DIR/malformed-attrs.rs:181:1 | LL | #[expect] | ^^^^^^^^^ @@ -61,7 +61,7 @@ LL | #[expect(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `warn` attribute input - --> $DIR/malformed-attrs.rs:179:1 + --> $DIR/malformed-attrs.rs:183:1 | LL | #[warn] | ^^^^^^^ @@ -77,7 +77,7 @@ LL | #[warn(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `deny` attribute input - --> $DIR/malformed-attrs.rs:181:1 + --> $DIR/malformed-attrs.rs:185:1 | LL | #[deny] | ^^^^^^^ @@ -93,7 +93,7 @@ LL | #[deny(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: malformed `forbid` attribute input - --> $DIR/malformed-attrs.rs:183:1 + --> $DIR/malformed-attrs.rs:187:1 | LL | #[forbid] | ^^^^^^^^^ @@ -109,19 +109,19 @@ LL | #[forbid(lint1, lint2, lint3, reason = "...")] | +++++++++++++++++++++++++++++++++++++ error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:102:1 + --> $DIR/malformed-attrs.rs:106:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:119:1 + --> $DIR/malformed-attrs.rs:123:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: the `#[proc_macro_derive]` attribute is only usable with crates of the `proc-macro` crate type - --> $DIR/malformed-attrs.rs:126:1 + --> $DIR/malformed-attrs.rs:130:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ @@ -263,9 +263,49 @@ LL | #[optimize(size)] LL | #[optimize(speed)] | +++++++ -error[E0565]: malformed `cold` attribute input +error[E0805]: malformed `optimize` attribute input --> $DIR/malformed-attrs.rs:57:1 | +LL | #[optimize(none, none)] + | ^^^^^^^^^^------------^ + | | + | expected a single argument here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[optimize(none, none)] +LL + #[optimize(none)] + | +LL - #[optimize(none, none)] +LL + #[optimize(size)] + | +LL - #[optimize(none, none)] +LL + #[optimize(speed)] + | + +error[E0805]: malformed `optimize` attribute input + --> $DIR/malformed-attrs.rs:59:1 + | +LL | #[optimize(none, speed)] + | ^^^^^^^^^^-------------^ + | | + | expected a single argument here + | +help: try changing it to one of the following valid forms of the attribute + | +LL - #[optimize(none, speed)] +LL + #[optimize(none)] + | +LL - #[optimize(none, speed)] +LL + #[optimize(size)] + | +LL - #[optimize(none, speed)] +LL + #[optimize(speed)] + | + +error[E0565]: malformed `cold` attribute input + --> $DIR/malformed-attrs.rs:61:1 + | LL | #[cold = 1] | ^^^^^^^---^ | | @@ -278,7 +318,7 @@ LL + #[cold] | error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:59:1 + --> $DIR/malformed-attrs.rs:63:1 | LL | #[must_use()] | ^^^^^^^^^^--^ @@ -296,7 +336,7 @@ LL + #[must_use] | error[E0565]: malformed `no_mangle` attribute input - --> $DIR/malformed-attrs.rs:61:1 + --> $DIR/malformed-attrs.rs:65:1 | LL | #[no_mangle = 1] | ^^^^^^^^^^^^---^ @@ -310,7 +350,7 @@ LL + #[no_mangle] | error[E0565]: malformed `naked` attribute input - --> $DIR/malformed-attrs.rs:63:1 + --> $DIR/malformed-attrs.rs:67:1 | LL | #[unsafe(naked())] | ^^^^^^^^^^^^^^--^^ @@ -324,7 +364,7 @@ LL + #[unsafe(naked)] | error[E0565]: malformed `track_caller` attribute input - --> $DIR/malformed-attrs.rs:65:1 + --> $DIR/malformed-attrs.rs:69:1 | LL | #[track_caller()] | ^^^^^^^^^^^^^^--^ @@ -338,7 +378,7 @@ LL + #[track_caller] | error[E0539]: malformed `export_name` attribute input - --> $DIR/malformed-attrs.rs:67:1 + --> $DIR/malformed-attrs.rs:71:1 | LL | #[export_name()] | ^^^^^^^^^^^^^^^^ @@ -350,7 +390,7 @@ LL + #[export_name = "name"] | error[E0805]: malformed `used` attribute input - --> $DIR/malformed-attrs.rs:69:1 + --> $DIR/malformed-attrs.rs:73:1 | LL | #[used()] | ^^^^^^--^ @@ -368,7 +408,7 @@ LL + #[used] | error: `#[used]` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:69:1 + --> $DIR/malformed-attrs.rs:73:1 | LL | #[used()] | ^^^^^^^^^ @@ -376,7 +416,7 @@ LL | #[used()] = help: `#[used]` can only be applied to statics error[E0539]: malformed `crate_name` attribute input - --> $DIR/malformed-attrs.rs:72:1 + --> $DIR/malformed-attrs.rs:76:1 | LL | #[crate_name] | ^^^^^^^^^^^^^ @@ -387,7 +427,7 @@ LL | #[crate_name = "name"] | ++++++++ error[E0539]: malformed `target_feature` attribute input - --> $DIR/malformed-attrs.rs:77:1 + --> $DIR/malformed-attrs.rs:81:1 | LL | #[target_feature] | ^^^^^^^^^^^^^^^^^ expected this to be a list @@ -398,7 +438,7 @@ LL | #[target_feature(enable = "feat1, feat2")] | +++++++++++++++++++++++++ error[E0565]: malformed `export_stable` attribute input - --> $DIR/malformed-attrs.rs:79:1 + --> $DIR/malformed-attrs.rs:83:1 | LL | #[export_stable = 1] | ^^^^^^^^^^^^^^^^---^ @@ -412,7 +452,7 @@ LL + #[export_stable] | error[E0539]: malformed `link` attribute input - --> $DIR/malformed-attrs.rs:81:1 + --> $DIR/malformed-attrs.rs:85:1 | LL | #[link] | ^^^^^^^ expected this to be a list @@ -420,7 +460,7 @@ LL | #[link] = note: for more information, visit error[E0539]: malformed `link_name` attribute input - --> $DIR/malformed-attrs.rs:85:1 + --> $DIR/malformed-attrs.rs:89:1 | LL | #[link_name] | ^^^^^^^^^^^^ @@ -432,7 +472,7 @@ LL | #[link_name = "name"] | ++++++++ error[E0539]: malformed `link_section` attribute input - --> $DIR/malformed-attrs.rs:89:1 + --> $DIR/malformed-attrs.rs:93:1 | LL | #[link_section] | ^^^^^^^^^^^^^^^ @@ -444,7 +484,7 @@ LL | #[link_section = "name"] | ++++++++ error[E0539]: malformed `coverage` attribute input - --> $DIR/malformed-attrs.rs:91:1 + --> $DIR/malformed-attrs.rs:95:1 | LL | #[coverage] | ^^^^^^^^^^^ expected this to be a list @@ -457,13 +497,13 @@ LL | #[coverage(on)] | ++++ error[E0539]: malformed `sanitize` attribute input - --> $DIR/malformed-attrs.rs:93:1 + --> $DIR/malformed-attrs.rs:97:1 | LL | #[sanitize] | ^^^^^^^^^^^ expected this to be a list error[E0565]: malformed `no_implicit_prelude` attribute input - --> $DIR/malformed-attrs.rs:98:1 + --> $DIR/malformed-attrs.rs:102:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^----^ @@ -477,7 +517,7 @@ LL + #[no_implicit_prelude] | error[E0565]: malformed `proc_macro` attribute input - --> $DIR/malformed-attrs.rs:102:1 + --> $DIR/malformed-attrs.rs:106:1 | LL | #[proc_macro = 18] | ^^^^^^^^^^^^^----^ @@ -491,7 +531,7 @@ LL + #[proc_macro] | error[E0539]: malformed `instruction_set` attribute input - --> $DIR/malformed-attrs.rs:109:1 + --> $DIR/malformed-attrs.rs:113:1 | LL | #[instruction_set] | ^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -503,7 +543,7 @@ LL | #[instruction_set(set)] | +++++ error[E0539]: malformed `patchable_function_entry` attribute input - --> $DIR/malformed-attrs.rs:111:1 + --> $DIR/malformed-attrs.rs:115:1 | LL | #[patchable_function_entry] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -514,7 +554,7 @@ LL | #[patchable_function_entry(prefix_nops = m, entry_nops = n)] | +++++++++++++++++++++++++++++++++ error[E0565]: malformed `coroutine` attribute input - --> $DIR/malformed-attrs.rs:114:5 + --> $DIR/malformed-attrs.rs:118:5 | LL | #[coroutine = 63] || {} | ^^^^^^^^^^^^----^ @@ -528,7 +568,7 @@ LL + #[coroutine] || {} | error[E0565]: malformed `proc_macro_attribute` attribute input - --> $DIR/malformed-attrs.rs:119:1 + --> $DIR/malformed-attrs.rs:123:1 | LL | #[proc_macro_attribute = 19] | ^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -542,7 +582,7 @@ LL + #[proc_macro_attribute] | error[E0539]: malformed `must_use` attribute input - --> $DIR/malformed-attrs.rs:122:1 + --> $DIR/malformed-attrs.rs:126:1 | LL | #[must_use = 1] | ^^^^^^^^^^^^^-^ @@ -560,7 +600,7 @@ LL + #[must_use] | error[E0539]: malformed `proc_macro_derive` attribute input - --> $DIR/malformed-attrs.rs:126:1 + --> $DIR/malformed-attrs.rs:130:1 | LL | #[proc_macro_derive] | ^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -574,7 +614,7 @@ LL | #[proc_macro_derive(TraitName, attributes(name1, name2, ...))] | ++++++++++++++++++++++++++++++++++++++++++ error[E0539]: malformed `must_not_suspend` attribute input - --> $DIR/malformed-attrs.rs:131:1 + --> $DIR/malformed-attrs.rs:135:1 | LL | #[must_not_suspend()] | ^^^^^^^^^^^^^^^^^^--^ @@ -590,7 +630,7 @@ LL + #[must_not_suspend] | error[E0539]: malformed `cfi_encoding` attribute input - --> $DIR/malformed-attrs.rs:133:1 + --> $DIR/malformed-attrs.rs:137:1 | LL | #[cfi_encoding = ""] | ^^^^^^^^^^^^^^^^^--^ @@ -603,7 +643,7 @@ LL | #[cfi_encoding = "encoding"] | ++++++++ error[E0565]: malformed `marker` attribute input - --> $DIR/malformed-attrs.rs:152:1 + --> $DIR/malformed-attrs.rs:156:1 | LL | #[marker = 3] | ^^^^^^^^^---^ @@ -617,7 +657,7 @@ LL + #[marker] | error[E0565]: malformed `fundamental` attribute input - --> $DIR/malformed-attrs.rs:154:1 + --> $DIR/malformed-attrs.rs:158:1 | LL | #[fundamental()] | ^^^^^^^^^^^^^--^ @@ -631,7 +671,7 @@ LL + #[fundamental] | error[E0565]: malformed `ffi_pure` attribute input - --> $DIR/malformed-attrs.rs:162:5 + --> $DIR/malformed-attrs.rs:166:5 | LL | #[unsafe(ffi_pure = 1)] | ^^^^^^^^^^^^^^^^^^---^^ @@ -645,7 +685,7 @@ LL + #[unsafe(ffi_pure)] | error[E0539]: malformed `link_ordinal` attribute input - --> $DIR/malformed-attrs.rs:164:5 + --> $DIR/malformed-attrs.rs:168:5 | LL | #[link_ordinal] | ^^^^^^^^^^^^^^^ expected this to be a list @@ -657,7 +697,7 @@ LL | #[link_ordinal(ordinal)] | +++++++++ error[E0565]: malformed `ffi_const` attribute input - --> $DIR/malformed-attrs.rs:168:5 + --> $DIR/malformed-attrs.rs:172:5 | LL | #[unsafe(ffi_const = 1)] | ^^^^^^^^^^^^^^^^^^^---^^ @@ -671,13 +711,13 @@ LL + #[unsafe(ffi_const)] | error[E0539]: malformed `linkage` attribute input - --> $DIR/malformed-attrs.rs:170:5 + --> $DIR/malformed-attrs.rs:174:5 | LL | #[linkage] | ^^^^^^^^^^ expected this to be of the form `linkage = "..."` error[E0539]: malformed `debugger_visualizer` attribute input - --> $DIR/malformed-attrs.rs:185:1 + --> $DIR/malformed-attrs.rs:189:1 | LL | #[debugger_visualizer] | ^^^^^^^^^^^^^^^^^^^^^^ expected this to be a list @@ -689,7 +729,7 @@ LL | #[debugger_visualizer(natvis_file = "...", gdb_script_file = "...")] | ++++++++++++++++++++++++++++++++++++++++++++++ error[E0565]: malformed `automatically_derived` attribute input - --> $DIR/malformed-attrs.rs:187:1 + --> $DIR/malformed-attrs.rs:191:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^----^ @@ -703,7 +743,7 @@ LL + #[automatically_derived] | error[E0565]: malformed `non_exhaustive` attribute input - --> $DIR/malformed-attrs.rs:195:1 + --> $DIR/malformed-attrs.rs:199:1 | LL | #[non_exhaustive = 1] | ^^^^^^^^^^^^^^^^^---^ @@ -717,7 +757,7 @@ LL + #[non_exhaustive] | error[E0565]: malformed `thread_local` attribute input - --> $DIR/malformed-attrs.rs:201:1 + --> $DIR/malformed-attrs.rs:205:1 | LL | #[thread_local()] | ^^^^^^^^^^^^^^--^ @@ -731,7 +771,7 @@ LL + #[thread_local] | error[E0565]: malformed `no_link` attribute input - --> $DIR/malformed-attrs.rs:205:1 + --> $DIR/malformed-attrs.rs:209:1 | LL | #[no_link()] | ^^^^^^^^^--^ @@ -745,7 +785,7 @@ LL + #[no_link] | error[E0539]: malformed `macro_use` attribute input - --> $DIR/malformed-attrs.rs:207:1 + --> $DIR/malformed-attrs.rs:211:1 | LL | #[macro_use = 1] | ^^^^^^^^^^^^---^ @@ -763,7 +803,7 @@ LL + #[macro_use] | error[E0539]: malformed `macro_export` attribute input - --> $DIR/malformed-attrs.rs:212:1 + --> $DIR/malformed-attrs.rs:216:1 | LL | #[macro_export = 18] | ^^^^^^^^^^^^^^^----^ @@ -780,7 +820,7 @@ LL + #[macro_export] | error[E0658]: allow_internal_unsafe side-steps the unsafe_code lint - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:218:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -789,7 +829,7 @@ LL | #[allow_internal_unsafe = 1] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0565]: malformed `allow_internal_unsafe` attribute input - --> $DIR/malformed-attrs.rs:214:1 + --> $DIR/malformed-attrs.rs:218:1 | LL | #[allow_internal_unsafe = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^---^ @@ -815,7 +855,7 @@ LL | | } | |_- not a `const fn` warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/malformed-attrs.rs:81:1 + --> $DIR/malformed-attrs.rs:85:1 | LL | #[link] | ^^^^^^^ @@ -852,13 +892,13 @@ LL | #[inline = 5] = note: `#[deny(ill_formed_attribute_input)]` (part of `#[deny(future_incompatible)]`) on by default warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]` - --> $DIR/malformed-attrs.rs:72:1 + --> $DIR/malformed-attrs.rs:76:1 | LL | #[crate_name] | ^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/malformed-attrs.rs:113:1 + --> $DIR/malformed-attrs.rs:117:1 | LL | / fn test() { LL | | #[coroutine = 63] || {} @@ -867,13 +907,13 @@ LL | | } | |_^ error: valid forms for the attribute are `#[doc = "string"]`, `#[doc(alias)]`, `#[doc(attribute)]`, `#[doc(auto_cfg)]`, `#[doc(cfg)]`, `#[doc(fake_variadic)]`, `#[doc(hidden)]`, `#[doc(html_favicon_url)]`, `#[doc(html_logo_url)]`, `#[doc(html_no_source)]`, `#[doc(html_playground_url)]`, `#[doc(html_root_url)]`, `#[doc(include)]`, `#[doc(inline)]`, `#[doc(issue_tracker_base_url)]`, `#[doc(keyword)]`, `#[doc(masked)]`, `#[doc(no_default_passes)]`, `#[doc(no_inline)]`, `#[doc(notable_trait)]`, `#[doc(passes)]`, `#[doc(plugins)]`, `#[doc(rust_logo)]`, `#[doc(search_unbox)]`, `#[doc(spotlight)]`, and `#[doc(test)]` - --> $DIR/malformed-attrs.rs:75:1 + --> $DIR/malformed-attrs.rs:79:1 | LL | #[doc] | ^^^^^^ warning: `#[link_name]` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:85:1 + --> $DIR/malformed-attrs.rs:89:1 | LL | #[link_name] | ^^^^^^^^^^^^ @@ -882,7 +922,7 @@ LL | #[link_name] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:95:1 + --> $DIR/malformed-attrs.rs:99:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -891,7 +931,7 @@ LL | #[ignore()] = note: for more information, see issue #57571 warning: `#[no_implicit_prelude]` attribute cannot be used on functions - --> $DIR/malformed-attrs.rs:98:1 + --> $DIR/malformed-attrs.rs:102:1 | LL | #[no_implicit_prelude = 23] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -900,7 +940,7 @@ LL | #[no_implicit_prelude = 23] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: missing options for `diagnostic::on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:137:1 + --> $DIR/malformed-attrs.rs:141:1 | LL | #[diagnostic::on_unimplemented] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -909,7 +949,7 @@ LL | #[diagnostic::on_unimplemented] = note: `#[warn(malformed_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default warning: malformed `diagnostic::on_unimplemented` attribute - --> $DIR/malformed-attrs.rs:139:1 + --> $DIR/malformed-attrs.rs:143:1 | LL | #[diagnostic::on_unimplemented = 1] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ invalid option found here @@ -917,13 +957,13 @@ LL | #[diagnostic::on_unimplemented = 1] = help: only `message`, `note` and `label` are allowed as options warning: `#[diagnostic::do_not_recommend]` does not expect any arguments - --> $DIR/malformed-attrs.rs:146:1 + --> $DIR/malformed-attrs.rs:150:1 | LL | #[diagnostic::do_not_recommend()] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: `#[automatically_derived]` attribute cannot be used on modules - --> $DIR/malformed-attrs.rs:187:1 + --> $DIR/malformed-attrs.rs:191:1 | LL | #[automatically_derived = 18] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -932,7 +972,7 @@ LL | #[automatically_derived = 18] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:221:1 + --> $DIR/malformed-attrs.rs:225:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ @@ -941,7 +981,7 @@ LL | #[ignore = 1] = note: for more information, see issue #57571 error[E0308]: mismatched types - --> $DIR/malformed-attrs.rs:114:23 + --> $DIR/malformed-attrs.rs:118:23 | LL | fn test() { | - help: a return type might be missing here: `-> _` @@ -949,9 +989,9 @@ LL | #[coroutine = 63] || {} | ^^^^^ expected `()`, found coroutine | = note: expected unit type `()` - found coroutine `{coroutine@$DIR/malformed-attrs.rs:114:23: 114:25}` + found coroutine `{coroutine@$DIR/malformed-attrs.rs:118:23: 118:25}` -error: aborting due to 72 previous errors; 8 warnings emitted +error: aborting due to 74 previous errors; 8 warnings emitted Some errors have detailed explanations: E0308, E0463, E0539, E0565, E0658, E0805. For more information about an error, try `rustc --explain E0308`. @@ -968,7 +1008,7 @@ LL | #[inline = 5] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:95:1 + --> $DIR/malformed-attrs.rs:99:1 | LL | #[ignore()] | ^^^^^^^^^^^ @@ -979,7 +1019,7 @@ LL | #[ignore()] Future breakage diagnostic: error: valid forms for the attribute are `#[ignore = "reason"]` and `#[ignore]` - --> $DIR/malformed-attrs.rs:221:1 + --> $DIR/malformed-attrs.rs:225:1 | LL | #[ignore = 1] | ^^^^^^^^^^^^^ diff --git a/tests/ui/attributes/optimize.rs b/tests/ui/attributes/optimize.rs index 78e05f111e7bf..c55353d4cfb3f 100644 --- a/tests/ui/attributes/optimize.rs +++ b/tests/ui/attributes/optimize.rs @@ -40,3 +40,25 @@ fn async_block() -> impl Future { async fn async_fn() { () } + +trait Foo { + #[optimize(speed)] //~ ERROR attribute cannot be used on + fn invalid(); + #[optimize(speed)] + fn valid() {} +} + +impl Foo for () { + #[optimize(speed)] + fn invalid() {} + #[optimize(size)] + fn valid() {} +} + +#[optimize(speed)] +#[optimize(speed)] //~ ERROR multiple `optimize` attributes +fn duplicate_same() {} + +#[optimize(speed)] +#[optimize(size)] //~ ERROR multiple `optimize` attributes +fn duplicate_different() {} diff --git a/tests/ui/attributes/optimize.stderr b/tests/ui/attributes/optimize.stderr index 2ded1a973f33d..ba766e1dd8bb5 100644 --- a/tests/ui/attributes/optimize.stderr +++ b/tests/ui/attributes/optimize.stderr @@ -30,5 +30,37 @@ LL | #[optimize(speed)] | = help: `#[optimize]` can only be applied to functions -error: aborting due to 4 previous errors +error: `#[optimize]` attribute cannot be used on required trait methods + --> $DIR/optimize.rs:45:5 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + | + = help: `#[optimize]` can be applied to closures, functions, inherent methods, provided trait methods, and trait methods in impl blocks + +error: multiple `optimize` attributes + --> $DIR/optimize.rs:59:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/optimize.rs:58:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + +error: multiple `optimize` attributes + --> $DIR/optimize.rs:63:1 + | +LL | #[optimize(size)] + | ^^^^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/optimize.rs:62:1 + | +LL | #[optimize(speed)] + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 7 previous errors From c611d64e99139c08ce7ba5d8cab0b4bf0e52932d Mon Sep 17 00:00:00 2001 From: Fallible <118682743+fallible-algebra@users.noreply.github.com> Date: Wed, 3 Jun 2026 07:51:09 +0100 Subject: [PATCH 20/26] Fix some wf module argument/doc comment name mismatches --- compiler/rustc_trait_selection/src/traits/wf.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index fdf32d32e9058..49b6066c71ee0 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -22,9 +22,9 @@ use tracing::{debug, instrument, trace}; use crate::infer::InferCtxt; use crate::traits; -/// Returns the set of obligations needed to make `arg` well-formed. -/// If `arg` contains unresolved inference variables, this may include -/// further WF obligations. However, if `arg` IS an unresolved +/// Returns the set of obligations needed to make `term` well-formed. +/// If `term` contains unresolved inference variables, this may include +/// further WF obligations. However, if `term` IS an unresolved /// inference variable, returns `None`, because we are not able to /// make any progress at all. This is to prevent cycles where we /// say "?0 is WF if ?0 is WF". @@ -100,7 +100,7 @@ pub fn unnormalized_obligations<'tcx>( ) -> Option> { debug_assert_eq!(term, infcx.resolve_vars_if_possible(term)); - // However, if `arg` IS an unresolved inference variable, returns `None`, + // However, if `term` IS an unresolved inference variable, returns `None`, // because we are not able to make any progress at all. This is to prevent // cycles where we say "?0 is WF if ?0 is WF". if term.is_infer() { From 42d5c9666806dfa0f2c2487e5125680295b1729c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 2 Jun 2026 22:09:12 +0200 Subject: [PATCH 21/26] Rewrite target checking for `#[sanitize]` --- .../src/attributes/codegen_attrs.rs | 27 ++- .../src/session_diagnostics.rs | 9 + compiler/rustc_passes/src/check_attr.rs | 52 +---- compiler/rustc_passes/src/errors.rs | 13 -- tests/ui/sanitize-attr/valid-sanitize.rs | 36 ++-- tests/ui/sanitize-attr/valid-sanitize.stderr | 188 +++++++----------- 6 files changed, 126 insertions(+), 199 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index 14d3eebf8fa1a..1ff3d6c13d0aa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -8,6 +8,7 @@ use crate::attributes::AttributeSafety; use crate::session_diagnostics::{ EmptyExportName, NakedFunctionIncompatibleAttribute, NullOnExport, NullOnObjcClass, NullOnObjcSelector, ObjcClassExpectedStringLiteral, ObjcSelectorExpectedStringLiteral, + SanitizeInvalidStatic, }; use crate::target_checking::Policy::AllowSilent; @@ -566,8 +567,18 @@ pub(crate) struct SanitizeParser; impl SingleAttributeParser for SanitizeParser { const PATH: &[Symbol] = &[sym::sanitize]; - // FIXME: still checked in check_attrs.rs - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[ + Allow(Target::Fn), + Allow(Target::Closure), + Allow(Target::Method(MethodKind::Inherent)), + Allow(Target::Method(MethodKind::Trait { body: true })), + Allow(Target::Method(MethodKind::TraitImpl)), + Allow(Target::Impl { of_trait: false }), + Allow(Target::Impl { of_trait: true }), + Allow(Target::Mod), + Allow(Target::Crate), + Allow(Target::Static), + ]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"address = "on|off""#, r#"kernel_address = "on|off""#, @@ -668,6 +679,18 @@ impl SingleAttributeParser for SanitizeParser { } } + // The sanitizer attribute is only allowed on statics, if only address bits are set + let all_set_except_address = + (on_set | off_set) & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS); + if cx.target == Target::Static + && let Some(set) = all_set_except_address.iter().next() + { + cx.emit_err(SanitizeInvalidStatic { + span: cx.attr_span, + field: set.as_str().expect("Since this `SanitizerSet` is returned from an iterator, exactly one field is set") + }); + } + Some(AttributeKind::Sanitize { on_set, off_set, rtsan, span: cx.attr_span }) } } diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 1d4d8d8123633..b4afdfd7ce409 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -1023,3 +1023,12 @@ pub(crate) enum InvalidMachoSectionReason { #[note("section name `{$section}` is longer than 16 bytes")] SectionTooLong { section: String }, } + +#[derive(Diagnostic)] +#[diag("`#[sanitize({$field} = ...)]` attribute cannot be used on statics")] +#[help("`#[sanitize]` can be used on statics if only the address is sanitized")] +pub(crate) struct SanitizeInvalidStatic { + #[primary_span] + pub span: Span, + pub field: &'static str, +} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index a265325fd8e77..de373d821891f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -18,7 +18,7 @@ use rustc_feature::BUILTIN_ATTRIBUTE_MAP; use rustc_hir::attrs::diagnostic::Directive; use rustc_hir::attrs::{ AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, - ReprAttr, SanitizerSet, + ReprAttr, }; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModDefId; @@ -227,9 +227,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } &AttributeKind::FfiPure(attr_span) => self.check_ffi_pure(attr_span, attrs), AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span), - &AttributeKind::Sanitize { on_set, off_set, rtsan: _, span: attr_span } => { - self.check_sanitize(attr_span, on_set | off_set, span, target); - } AttributeKind::Link(_, attr_span) => self.check_link(hir_id, *attr_span, span, target), AttributeKind::MacroExport { span, .. } => { self.check_macro_export(hir_id, *span, target) @@ -401,6 +398,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcThenThisWouldNeed(..) => (), AttributeKind::RustcTrivialFieldReads => (), AttributeKind::RustcUnsafeSpecializationMarker => (), + AttributeKind::Sanitize { .. } => {} AttributeKind::ShouldPanic { .. } => (), AttributeKind::Stability { .. } => (), AttributeKind::TestRunner(..) => (), @@ -627,52 +625,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks that the `#[sanitize(..)]` attribute is applied to a - /// function/closure/method, or to an impl block or module. - fn check_sanitize( - &self, - attr_span: Span, - set: SanitizerSet, - target_span: Span, - target: Target, - ) { - let mut not_fn_impl_mod = None; - let mut no_body = None; - - match target { - Target::Fn - | Target::Closure - | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) - | Target::Impl { .. } - | Target::Mod => return, - Target::Static - // if we mask out the address bits, i.e. *only* address was set, - // we allow it - if set & !(SanitizerSet::ADDRESS | SanitizerSet::KERNELADDRESS) - == SanitizerSet::empty() => - { - return; - } - - // These are "functions", but they aren't allowed because they don't - // have a body, so the usual explanation would be confusing. - Target::Method(MethodKind::Trait { body: false }) | Target::ForeignFn => { - no_body = Some(target_span); - } - - _ => { - not_fn_impl_mod = Some(target_span); - } - } - - self.dcx().emit_err(errors::SanitizeAttributeNotAllowed { - attr_span, - not_fn_impl_mod, - no_body, - help: (), - }); - } - /// Checks if `#[naked]` is applied to a function definition. fn check_naked(&self, hir_id: HirId, target: Target) { match target { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 66c33b3e49756..f59a33ab721e9 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1052,19 +1052,6 @@ pub(crate) struct UnnecessaryPartialStableFeature { #[note("see issue #55436 for more information")] pub(crate) struct IneffectiveUnstableImpl; -#[derive(Diagnostic)] -#[diag("sanitize attribute not allowed here")] -pub(crate) struct SanitizeAttributeNotAllowed { - #[primary_span] - pub attr_span: Span, - #[label("not a function, impl block, or module")] - pub not_fn_impl_mod: Option, - #[label("function has no body")] - pub no_body: Option, - #[help("sanitize attribute can be applied to a function (with body), impl block, or module")] - pub help: (), -} - // FIXME(jdonszelmann): move back to rustc_attr #[derive(Diagnostic)] #[diag( diff --git a/tests/ui/sanitize-attr/valid-sanitize.rs b/tests/ui/sanitize-attr/valid-sanitize.rs index ebe76fcba0442..56167a0070e97 100644 --- a/tests/ui/sanitize-attr/valid-sanitize.rs +++ b/tests/ui/sanitize-attr/valid-sanitize.rs @@ -12,27 +12,27 @@ mod submod {} #[sanitize(address = "off")] static FOO: u32 = 0; -#[sanitize(thread = "off")] //~ ERROR sanitize attribute not allowed here +#[sanitize(thread = "off")] //~ ERROR attribute cannot be used on static BAR: u32 = 0; -#[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here +#[sanitize(address = "off")] //~ ERROR attribute cannot be used on type MyTypeAlias = (); -#[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here +#[sanitize(address = "off")] //~ ERROR attribute cannot be used on trait MyTrait { - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on const TRAIT_ASSOC_CONST: u32; - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on type TraitAssocType; - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on fn trait_method(&self); #[sanitize(address = "off", thread = "on")] fn trait_method_with_default(&self) {} - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on fn trait_assoc_fn(); } @@ -40,7 +40,7 @@ trait MyTrait { impl MyTrait for () { const TRAIT_ASSOC_CONST: u32 = 0; - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on type TraitAssocType = Self; #[sanitize(address = "off", thread = "on")] @@ -57,14 +57,14 @@ trait HasAssocType { } impl HasAssocType for () { - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on type T = impl Copy; fn constrain_assoc_type() -> Self::T {} } -#[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here +#[sanitize(address = "off")] //~ ERROR attribute cannot be used on struct MyStruct { - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on field: u32, } @@ -77,25 +77,25 @@ impl MyStruct { } extern "C" { - #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off", thread = "on")] //~ ERROR attribute cannot be used on static X: u32; - #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off", thread = "on")] //~ ERROR attribute cannot be used on type T; - #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off", thread = "on")] //~ ERROR attribute cannot be used on fn foreign_fn(); } #[sanitize(address = "off", thread = "on")] fn main() { - #[sanitize(address = "off", thread = "on")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off", thread = "on")] //~ ERROR attribute cannot be used on let _ = (); // Currently not allowed on let statements, even if they bind to a closure. // It might be nice to support this as a special case someday, but trying // to define the precise boundaries of that special case might be tricky. - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on let _let_closure = || (); // In situations where attributes can already be applied to expressions, @@ -106,10 +106,10 @@ fn main() { }; match () { - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on () => (), } - #[sanitize(address = "off")] //~ ERROR sanitize attribute not allowed here + #[sanitize(address = "off")] //~ ERROR attribute cannot be used on return (); } diff --git a/tests/ui/sanitize-attr/valid-sanitize.stderr b/tests/ui/sanitize-attr/valid-sanitize.stderr index ff9fe63eaf558..9ca2457353f32 100644 --- a/tests/ui/sanitize-attr/valid-sanitize.stderr +++ b/tests/ui/sanitize-attr/valid-sanitize.stderr @@ -1,190 +1,146 @@ -error: sanitize attribute not allowed here +error: `#[sanitize(thread = ...)]` attribute cannot be used on statics --> $DIR/valid-sanitize.rs:15:1 | LL | #[sanitize(thread = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | static BAR: u32 = 0; - | -------------------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be used on statics if only the address is sanitized -error: sanitize attribute not allowed here +error: `#[sanitize]` attribute cannot be used on type aliases --> $DIR/valid-sanitize.rs:18:1 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | type MyTypeAlias = (); - | ---------------------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here +error: `#[sanitize]` attribute cannot be used on traits --> $DIR/valid-sanitize.rs:21:1 | -LL | #[sanitize(address = "off")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | / trait MyTrait { -LL | | #[sanitize(address = "off")] -LL | | const TRAIT_ASSOC_CONST: u32; -... | -LL | | fn trait_assoc_fn(); -LL | | } - | |_- not a function, impl block, or module - | - = help: sanitize attribute can be applied to a function (with body), impl block, or module - -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:65:1 - | -LL | #[sanitize(address = "off")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | / struct MyStruct { -LL | | #[sanitize(address = "off")] -LL | | field: u32, -LL | | } - | |_- not a function, impl block, or module - | - = help: sanitize attribute can be applied to a function (with body), impl block, or module - -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:67:5 - | -LL | #[sanitize(address = "off")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | field: u32, - | ---------- not a function, impl block, or module - | - = help: sanitize attribute can be applied to a function (with body), impl block, or module - -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:92:5 - | -LL | #[sanitize(address = "off", thread = "on")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | let _ = (); - | ----------- not a function, impl block, or module +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:98:5 +error: `#[sanitize]` attribute cannot be used on associated consts + --> $DIR/valid-sanitize.rs:23:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | let _let_closure = || (); - | ------------------------- not a function, impl block, or module - | - = help: sanitize attribute can be applied to a function (with body), impl block, or module - -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:109:9 - | -LL | #[sanitize(address = "off")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | () => (), - | -------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:113:5 +error: `#[sanitize]` attribute cannot be used on associated types + --> $DIR/valid-sanitize.rs:26:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | return (); - | --------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:23:5 +error: `#[sanitize]` attribute cannot be used on required trait methods + --> $DIR/valid-sanitize.rs:29:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | const TRAIT_ASSOC_CONST: u32; - | ----------------------------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to closures, crates, functions, impl blocks, inherent methods, modules, provided trait methods, statics, and trait methods in impl blocks -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:26:5 +error: `#[sanitize]` attribute cannot be used on required trait methods + --> $DIR/valid-sanitize.rs:35:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | type TraitAssocType; - | -------------------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to closures, crates, functions, impl blocks, inherent methods, modules, provided trait methods, statics, and trait methods in impl blocks -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:29:5 +error: `#[sanitize]` attribute cannot be used on associated types + --> $DIR/valid-sanitize.rs:43:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn trait_method(&self); - | ----------------------- function has no body | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:35:5 +error: `#[sanitize]` attribute cannot be used on associated types + --> $DIR/valid-sanitize.rs:60:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn trait_assoc_fn(); - | -------------------- function has no body | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:43:5 +error: `#[sanitize]` attribute cannot be used on structs + --> $DIR/valid-sanitize.rs:65:1 | -LL | #[sanitize(address = "off")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | type TraitAssocType = Self; - | --------------------------- not a function, impl block, or module +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here - --> $DIR/valid-sanitize.rs:60:5 +error: `#[sanitize]` attribute cannot be used on struct fields + --> $DIR/valid-sanitize.rs:67:5 | LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | type T = impl Copy; - | ------------------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here +error: `#[sanitize]` attribute cannot be used on foreign statics --> $DIR/valid-sanitize.rs:80:5 | LL | #[sanitize(address = "off", thread = "on")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | static X: u32; - | -------------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here +error: `#[sanitize]` attribute cannot be used on foreign types --> $DIR/valid-sanitize.rs:83:5 | LL | #[sanitize(address = "off", thread = "on")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | type T; - | ------- not a function, impl block, or module | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics -error: sanitize attribute not allowed here +error: `#[sanitize]` attribute cannot be used on foreign functions --> $DIR/valid-sanitize.rs:86:5 | LL | #[sanitize(address = "off", thread = "on")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn foreign_fn(); - | ---------------- function has no body | - = help: sanitize attribute can be applied to a function (with body), impl block, or module + = help: `#[sanitize]` can be applied to closures, crates, functions, impl blocks, methods, modules, and statics + +error: `#[sanitize]` attribute cannot be used on statements + --> $DIR/valid-sanitize.rs:92:5 + | +LL | #[sanitize(address = "off", thread = "on")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics + +error: `#[sanitize]` attribute cannot be used on statements + --> $DIR/valid-sanitize.rs:98:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics + +error: `#[sanitize]` attribute cannot be used on match arms + --> $DIR/valid-sanitize.rs:109:9 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics + +error: `#[sanitize]` attribute cannot be used on expressions + --> $DIR/valid-sanitize.rs:113:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics error: aborting due to 18 previous errors From dd28618616135ca3086287f6b05ea965990aa822 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 3 Jun 2026 08:43:21 +0200 Subject: [PATCH 22/26] Add `attr-on-mac-call` test --- tests/ui/attributes/attr-on-mac-call.rs | 5 +- tests/ui/attributes/attr-on-mac-call.stderr | 70 ++++++++++++--------- 2 files changed, 43 insertions(+), 32 deletions(-) diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs index 2498682503e6b..6eae9dd958195 100644 --- a/tests/ui/attributes/attr-on-mac-call.rs +++ b/tests/ui/attributes/attr-on-mac-call.rs @@ -1,6 +1,7 @@ -//@ check-pass +//@ check-fail // Regression test for https://github.com/rust-lang/rust/issues/145779 #![warn(unused_attributes)] +#![feature(sanitize)] fn main() { #[export_name = "x"] @@ -69,6 +70,8 @@ fn main() { #[should_panic] //~^ WARN attribute cannot be used on macro calls //~| WARN previously accepted + #[sanitize(address = "off")] + //~^ ERROR attribute cannot be used on macro calls unreachable!(); #[repr()] diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 5881685313e96..2fab4f99e8e1d 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -1,5 +1,13 @@ +error: `#[sanitize]` attribute cannot be used on macro calls + --> $DIR/attr-on-mac-call.rs:73:5 + | +LL | #[sanitize(address = "off")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics + warning: `#[export_name]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:6:5 + --> $DIR/attr-on-mac-call.rs:7:5 | LL | #[export_name = "x"] | ^^^^^^^^^^^^^^^^^^^^ @@ -13,7 +21,7 @@ LL | #![warn(unused_attributes)] | ^^^^^^^^^^^^^^^^^ warning: `#[naked]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:9:5 + --> $DIR/attr-on-mac-call.rs:10:5 | LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ @@ -22,7 +30,7 @@ LL | #[unsafe(naked)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[track_caller]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:12:5 + --> $DIR/attr-on-mac-call.rs:13:5 | LL | #[track_caller] | ^^^^^^^^^^^^^^^ @@ -31,7 +39,7 @@ LL | #[track_caller] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[used]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:15:5 + --> $DIR/attr-on-mac-call.rs:16:5 | LL | #[used] | ^^^^^^^ @@ -40,7 +48,7 @@ LL | #[used] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[target_feature]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:18:5 + --> $DIR/attr-on-mac-call.rs:19:5 | LL | #[target_feature(enable = "x")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -49,7 +57,7 @@ LL | #[target_feature(enable = "x")] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[deprecated]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:21:5 + --> $DIR/attr-on-mac-call.rs:22:5 | LL | #[deprecated] | ^^^^^^^^^^^^^ @@ -58,7 +66,7 @@ LL | #[deprecated] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[inline]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:24:5 + --> $DIR/attr-on-mac-call.rs:25:5 | LL | #[inline] | ^^^^^^^^^ @@ -67,7 +75,7 @@ LL | #[inline] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[link_name]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:27:5 + --> $DIR/attr-on-mac-call.rs:28:5 | LL | #[link_name = "x"] | ^^^^^^^^^^^^^^^^^^ @@ -76,7 +84,7 @@ LL | #[link_name = "x"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[link_section]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:30:5 + --> $DIR/attr-on-mac-call.rs:31:5 | LL | #[link_section = "__TEXT,__text"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,7 +93,7 @@ LL | #[link_section = "__TEXT,__text"] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[link_ordinal]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:33:5 + --> $DIR/attr-on-mac-call.rs:34:5 | LL | #[link_ordinal(42)] | ^^^^^^^^^^^^^^^^^^^ @@ -94,7 +102,7 @@ LL | #[link_ordinal(42)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[non_exhaustive]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:36:5 + --> $DIR/attr-on-mac-call.rs:37:5 | LL | #[non_exhaustive] | ^^^^^^^^^^^^^^^^^ @@ -103,7 +111,7 @@ LL | #[non_exhaustive] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[proc_macro]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:39:5 + --> $DIR/attr-on-mac-call.rs:40:5 | LL | #[proc_macro] | ^^^^^^^^^^^^^ @@ -112,7 +120,7 @@ LL | #[proc_macro] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[cold]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:42:5 + --> $DIR/attr-on-mac-call.rs:43:5 | LL | #[cold] | ^^^^^^^ @@ -121,7 +129,7 @@ LL | #[cold] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[no_mangle]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:45:5 + --> $DIR/attr-on-mac-call.rs:46:5 | LL | #[no_mangle] | ^^^^^^^^^^^^ @@ -130,7 +138,7 @@ LL | #[no_mangle] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[deprecated]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:48:5 + --> $DIR/attr-on-mac-call.rs:49:5 | LL | #[deprecated] | ^^^^^^^^^^^^^ @@ -139,7 +147,7 @@ LL | #[deprecated] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[automatically_derived]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:51:5 + --> $DIR/attr-on-mac-call.rs:52:5 | LL | #[automatically_derived] | ^^^^^^^^^^^^^^^^^^^^^^^^ @@ -148,7 +156,7 @@ LL | #[automatically_derived] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[macro_use]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:54:5 + --> $DIR/attr-on-mac-call.rs:55:5 | LL | #[macro_use] | ^^^^^^^^^^^^ @@ -157,7 +165,7 @@ LL | #[macro_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[must_use]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:57:5 + --> $DIR/attr-on-mac-call.rs:58:5 | LL | #[must_use] | ^^^^^^^^^^^ @@ -166,7 +174,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[no_implicit_prelude]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:60:5 + --> $DIR/attr-on-mac-call.rs:61:5 | LL | #[no_implicit_prelude] | ^^^^^^^^^^^^^^^^^^^^^^ @@ -175,7 +183,7 @@ LL | #[no_implicit_prelude] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[path]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:63:5 + --> $DIR/attr-on-mac-call.rs:64:5 | LL | #[path = ""] | ^^^^^^^^^^^^ @@ -184,7 +192,7 @@ LL | #[path = ""] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[ignore]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:66:5 + --> $DIR/attr-on-mac-call.rs:67:5 | LL | #[ignore] | ^^^^^^^^^ @@ -193,7 +201,7 @@ LL | #[ignore] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[should_panic]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:69:5 + --> $DIR/attr-on-mac-call.rs:70:5 | LL | #[should_panic] | ^^^^^^^^^^^^^^^ @@ -202,7 +210,7 @@ LL | #[should_panic] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[repr()]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:74:5 + --> $DIR/attr-on-mac-call.rs:77:5 | LL | #[repr()] | ^^^^^^^^^ @@ -211,7 +219,7 @@ LL | #[repr()] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: unused attribute - --> $DIR/attr-on-mac-call.rs:74:5 + --> $DIR/attr-on-mac-call.rs:77:5 | LL | #[repr()] | ^^^^^^^^^ help: remove this attribute @@ -219,7 +227,7 @@ LL | #[repr()] = note: using `repr` with an empty list has no effect warning: `#[repr(u8)]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:79:5 + --> $DIR/attr-on-mac-call.rs:82:5 | LL | #[repr(u8)] | ^^^^^^^^^^^ @@ -228,7 +236,7 @@ LL | #[repr(u8)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[repr(align(...))]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:83:5 + --> $DIR/attr-on-mac-call.rs:86:5 | LL | #[repr(align(8))] | ^^^^^^^^^^^^^^^^^ @@ -237,7 +245,7 @@ LL | #[repr(align(8))] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[repr(packed)]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:87:5 + --> $DIR/attr-on-mac-call.rs:90:5 | LL | #[repr(packed)] | ^^^^^^^^^^^^^^^ @@ -246,7 +254,7 @@ LL | #[repr(packed)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[repr(C)]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:91:5 + --> $DIR/attr-on-mac-call.rs:94:5 | LL | #[repr(C)] | ^^^^^^^^^^ @@ -255,7 +263,7 @@ LL | #[repr(C)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[repr(Rust)]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:95:5 + --> $DIR/attr-on-mac-call.rs:98:5 | LL | #[repr(Rust)] | ^^^^^^^^^^^^^ @@ -264,7 +272,7 @@ LL | #[repr(Rust)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[repr(simd)]` attribute cannot be used on macro calls - --> $DIR/attr-on-mac-call.rs:99:5 + --> $DIR/attr-on-mac-call.rs:102:5 | LL | #[repr(simd)] | ^^^^^^^^^^^^^ @@ -272,5 +280,5 @@ LL | #[repr(simd)] = help: `#[repr(simd)]` can only be applied to structs = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: 30 warnings emitted +error: aborting due to 1 previous error; 30 warnings emitted From b0ccb014b77ce296d7019a49b8bb2eee3dfd090d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Wed, 3 Jun 2026 09:53:10 +0200 Subject: [PATCH 23/26] Add "functions with a body" target group --- compiler/rustc_attr_parsing/src/target_checking.rs | 14 ++++++++++++++ tests/ui/asm/naked-invalid-attr.stderr | 4 ++-- .../codegen_attr_on_required_trait_method.stderr | 6 +++--- tests/ui/coverage-attr/allowed-positions.stderr | 6 +++--- tests/ui/extern/extern-no-mangle.stderr | 2 +- ...ssue-43106-gating-of-builtin-attrs-error.stderr | 2 +- .../issue-43106-gating-of-builtin-attrs.stderr | 4 ++-- tests/ui/force-inlining/invalid.stderr | 2 +- .../warn-unused-inline-on-fn-prototypes.stderr | 4 ++-- tests/ui/sanitize-attr/valid-sanitize.stderr | 6 +++--- 10 files changed, 32 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index bd592b68dc79e..90d45f221ea44 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -361,6 +361,13 @@ pub(crate) fn allowed_targets_applied( Target::Method(MethodKind::Trait { body: true }), Target::Method(MethodKind::TraitImpl), ]; + const FUNCTION_WITH_BODY_LIKE: &[Target] = &[ + Target::Fn, + Target::Closure, + Target::Method(MethodKind::Inherent), + Target::Method(MethodKind::Trait { body: true }), + Target::Method(MethodKind::TraitImpl), + ]; const METHOD_LIKE: &[Target] = &[ Target::Method(MethodKind::Inherent), Target::Method(MethodKind::Trait { body: false }), @@ -379,6 +386,13 @@ pub(crate) fn allowed_targets_applied( target, &mut added_fake_targets, ); + filter_targets( + &mut allowed_targets, + FUNCTION_WITH_BODY_LIKE, + "functions with a body", + target, + &mut added_fake_targets, + ); filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets); filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets); filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets); diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr index 9962cbafc37f6..70c7168a8c960 100644 --- a/tests/ui/asm/naked-invalid-attr.stderr +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -18,7 +18,7 @@ error: `#[naked]` attribute cannot be used on foreign functions LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ | - = help: `#[naked]` can be applied to functions and methods + = help: `#[naked]` can only be applied to functions with a body error: `#[naked]` attribute cannot be used on structs --> $DIR/naked-invalid-attr.rs:14:1 @@ -42,7 +42,7 @@ error: `#[naked]` attribute cannot be used on required trait methods LL | #[unsafe(naked)] | ^^^^^^^^^^^^^^^^ | - = help: `#[naked]` can be applied to functions, inherent methods, provided trait methods, and trait methods in impl blocks + = help: `#[naked]` can only be applied to functions with a body error: `#[naked]` attribute cannot be used on closures --> $DIR/naked-invalid-attr.rs:52:5 diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr index 8d0ded5427ad8..7f0b0f0327e4e 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr @@ -4,7 +4,7 @@ error: `#[cold]` attribute cannot be used on required trait methods LL | #[cold] | ^^^^^^^ | - = help: `#[cold]` can be applied to closures, foreign functions, functions, inherent methods, provided trait methods, and trait methods in impl blocks + = help: `#[cold]` can be applied to foreign functions and functions with a body = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! note: the lint level is defined here --> $DIR/codegen_attr_on_required_trait_method.rs:1:9 @@ -18,7 +18,7 @@ error: `#[link_section]` attribute cannot be used on required trait methods LL | #[link_section = "__TEXT,__text"] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + = help: `#[link_section]` can be applied to functions with a body and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: `#[linkage]` attribute cannot be used on required trait methods @@ -27,7 +27,7 @@ error: `#[linkage]` attribute cannot be used on required trait methods LL | #[linkage = "common"] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[linkage]` can be applied to foreign functions, foreign statics, functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + = help: `#[linkage]` can be applied to foreign functions, foreign statics, functions with a body, and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: aborting due to 3 previous errors diff --git a/tests/ui/coverage-attr/allowed-positions.stderr b/tests/ui/coverage-attr/allowed-positions.stderr index 09d6bac497d21..ae7e1d2fea980 100644 --- a/tests/ui/coverage-attr/allowed-positions.stderr +++ b/tests/ui/coverage-attr/allowed-positions.stderr @@ -46,7 +46,7 @@ error: `#[coverage]` attribute cannot be used on required trait methods LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ | - = help: `#[coverage]` can be applied to closures, crates, functions, impl blocks, inherent methods, modules, provided trait methods, and trait methods in impl blocks + = help: `#[coverage]` can be applied to crates, functions with a body, impl blocks, and modules error: `#[coverage]` attribute cannot be used on required trait methods --> $DIR/allowed-positions.rs:31:5 @@ -54,7 +54,7 @@ error: `#[coverage]` attribute cannot be used on required trait methods LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ | - = help: `#[coverage]` can be applied to closures, crates, functions, impl blocks, inherent methods, modules, provided trait methods, and trait methods in impl blocks + = help: `#[coverage]` can be applied to crates, functions with a body, impl blocks, and modules error: `#[coverage]` attribute cannot be used on associated types --> $DIR/allowed-positions.rs:39:5 @@ -110,7 +110,7 @@ error: `#[coverage]` attribute cannot be used on foreign functions LL | #[coverage(off)] | ^^^^^^^^^^^^^^^^ | - = help: `#[coverage]` can be applied to closures, crates, functions, impl blocks, methods, and modules + = help: `#[coverage]` can be applied to crates, functions with a body, impl blocks, and modules error: `#[coverage]` attribute cannot be used on statements --> $DIR/allowed-positions.rs:88:5 diff --git a/tests/ui/extern/extern-no-mangle.stderr b/tests/ui/extern/extern-no-mangle.stderr index 62518fa8d0d97..15ed08123dab7 100644 --- a/tests/ui/extern/extern-no-mangle.stderr +++ b/tests/ui/extern/extern-no-mangle.stderr @@ -18,7 +18,7 @@ warning: `#[no_mangle]` attribute cannot be used on foreign functions LL | #[no_mangle] | ^^^^^^^^^^^^ | - = help: `#[no_mangle]` can be applied to functions, methods, and statics + = help: `#[no_mangle]` can be applied to functions with a body and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[no_mangle]` attribute cannot be used on statements diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr index 7d252af4f94fe..da8c9095a8163 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr @@ -206,7 +206,7 @@ error: `#[export_name]` attribute cannot be used on required trait methods LL | #[export_name = "2200"] fn foo(); | ^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[export_name]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + = help: `#[export_name]` can be applied to functions with a body and statics error: `#[repr(C)]` attribute cannot be used on modules --> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:121:1 diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index c2d4effb4b57e..63d045fe6dfc6 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -511,7 +511,7 @@ warning: `#[no_mangle]` attribute cannot be used on required trait methods LL | #[no_mangle] fn foo(); | ^^^^^^^^^^^^ | - = help: `#[no_mangle]` can be applied to functions, inherent methods, statics, and trait methods in impl blocks + = help: `#[no_mangle]` can be applied to functions with a body and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[no_mangle]` attribute cannot be used on provided trait methods @@ -923,7 +923,7 @@ warning: `#[link_section]` attribute cannot be used on required trait methods LL | #[link_section = ",1800"] | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[link_section]` can be applied to functions, inherent methods, provided trait methods, statics, and trait methods in impl blocks + = help: `#[link_section]` can be applied to functions with a body and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: `#[must_use]` attribute cannot be used on modules diff --git a/tests/ui/force-inlining/invalid.stderr b/tests/ui/force-inlining/invalid.stderr index ce4f1d77ad2d2..3b9975e19a1b1 100644 --- a/tests/ui/force-inlining/invalid.stderr +++ b/tests/ui/force-inlining/invalid.stderr @@ -134,7 +134,7 @@ error: `#[rustc_force_inline]` attribute cannot be used on foreign functions LL | #[rustc_force_inline] | ^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[rustc_force_inline]` can be applied to functions and inherent methods + = help: `#[rustc_force_inline]` can only be applied to functions with a body error: `#[rustc_force_inline]` attribute cannot be used on type aliases --> $DIR/invalid.rs:66:1 diff --git a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr index 9b625172a7590..d3cad7c0c4775 100644 --- a/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr +++ b/tests/ui/lint/warn-unused-inline-on-fn-prototypes.stderr @@ -4,7 +4,7 @@ error: `#[inline]` attribute cannot be used on required trait methods LL | #[inline] | ^^^^^^^^^ | - = help: `#[inline]` can be applied to closures, functions, inherent methods, provided trait methods, and trait methods in impl blocks + = help: `#[inline]` can only be applied to functions with a body = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! note: the lint level is defined here --> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9 @@ -18,7 +18,7 @@ error: `#[inline]` attribute cannot be used on foreign functions LL | #[inline] | ^^^^^^^^^ | - = help: `#[inline]` can be applied to closures, functions, and methods + = help: `#[inline]` can only be applied to functions with a body = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! error: aborting due to 2 previous errors diff --git a/tests/ui/sanitize-attr/valid-sanitize.stderr b/tests/ui/sanitize-attr/valid-sanitize.stderr index 9ca2457353f32..e1d6c0e187fdc 100644 --- a/tests/ui/sanitize-attr/valid-sanitize.stderr +++ b/tests/ui/sanitize-attr/valid-sanitize.stderr @@ -44,7 +44,7 @@ error: `#[sanitize]` attribute cannot be used on required trait methods LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[sanitize]` can be applied to closures, crates, functions, impl blocks, inherent methods, modules, provided trait methods, statics, and trait methods in impl blocks + = help: `#[sanitize]` can be applied to crates, functions with a body, impl blocks, modules, and statics error: `#[sanitize]` attribute cannot be used on required trait methods --> $DIR/valid-sanitize.rs:35:5 @@ -52,7 +52,7 @@ error: `#[sanitize]` attribute cannot be used on required trait methods LL | #[sanitize(address = "off")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[sanitize]` can be applied to closures, crates, functions, impl blocks, inherent methods, modules, provided trait methods, statics, and trait methods in impl blocks + = help: `#[sanitize]` can be applied to crates, functions with a body, impl blocks, modules, and statics error: `#[sanitize]` attribute cannot be used on associated types --> $DIR/valid-sanitize.rs:43:5 @@ -108,7 +108,7 @@ error: `#[sanitize]` attribute cannot be used on foreign functions LL | #[sanitize(address = "off", thread = "on")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = help: `#[sanitize]` can be applied to closures, crates, functions, impl blocks, methods, modules, and statics + = help: `#[sanitize]` can be applied to crates, functions with a body, impl blocks, modules, and statics error: `#[sanitize]` attribute cannot be used on statements --> $DIR/valid-sanitize.rs:92:5 From 9bc4e33f4ccdfa77c027071d8a5683d51f512d0f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Tue, 2 Jun 2026 21:41:05 +0200 Subject: [PATCH 24/26] Rewrite target checking of `rustc_dummy` --- compiler/rustc_attr_parsing/src/attributes/dummy.rs | 7 ++++--- compiler/rustc_attr_parsing/src/target_checking.rs | 6 +++++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/dummy.rs b/compiler/rustc_attr_parsing/src/attributes/dummy.rs index c192986a953cc..9e2c642d1bbb6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/dummy.rs +++ b/compiler/rustc_attr_parsing/src/attributes/dummy.rs @@ -5,20 +5,21 @@ use rustc_span::{Symbol, sym}; use crate::attributes::{OnDuplicate, SingleAttributeParser}; use crate::context::AcceptContext; use crate::parser::ArgParser; -use crate::target_checking::{ALL_TARGETS, AllowedTargets}; +use crate::target_checking::AllowedTargets; use crate::unstable; pub(crate) struct RustcDummyParser; impl SingleAttributeParser for RustcDummyParser { const PATH: &[Symbol] = &[sym::rustc_dummy]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::ManuallyChecked; const TEMPLATE: AttributeTemplate = template!(Word); // Anything, really const STABILITY: AttributeStability = unstable!(rustc_attrs, "the `#[rustc_dummy]` attribute is used for rustc unit tests"); - fn convert(_: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { + fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { args.ignore_args(); + cx.ignore_target_checks(); Some(AttributeKind::RustcDummy) } } diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index bd592b68dc79e..6d1b06cc7dfcb 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -422,11 +422,15 @@ impl<'f, 'sess> AcceptContext<'f, 'sess> { attribute_args: &'static str, allowed_targets: &AllowedTargets, ) { + self.ignore_target_checks(); + AttributeParser::check_target(allowed_targets, attribute_args, self); + } + + pub(crate) fn ignore_target_checks(&mut self) { #[cfg(debug_assertions)] { self.has_target_been_checked = true; } - AttributeParser::check_target(allowed_targets, attribute_args, self); } } From a10c598e864e7c837486b44362434f8a23bd0d4e Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 3 Jun 2026 14:04:49 +0300 Subject: [PATCH 25/26] Emit error when there is an infer lifetime in user-specified args in delegation --- compiler/rustc_hir_analysis/src/collect.rs | 31 ++- compiler/rustc_hir_analysis/src/delegation.rs | 12 +- compiler/rustc_hir_analysis/src/errors.rs | 7 + compiler/rustc_hir_analysis/src/lib.rs | 1 + compiler/rustc_middle/src/queries.rs | 4 + compiler/rustc_middle/src/query/erase.rs | 4 + .../generics/generics-gen-args-errors.rs | 19 ++ .../generics/generics-gen-args-errors.stderr | 248 +++++++++++++----- .../generics/unelided-lifetime-ice-154178.rs | 1 + .../unelided-lifetime-ice-154178.stderr | 8 +- .../unelided-lifetime-in-sig-ice-156848.rs | 22 ++ ...unelided-lifetime-in-sig-ice-156848.stderr | 27 ++ tests/ui/delegation/wrong-lifetime-rib.rs | 13 + tests/ui/delegation/wrong-lifetime-rib.stderr | 88 ++++++- 14 files changed, 400 insertions(+), 85 deletions(-) create mode 100644 tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs create mode 100644 tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8c182f9165e13..46efb6a90b4be 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -46,7 +46,7 @@ use rustc_trait_selection::traits::{ }; use tracing::{debug, instrument}; -use crate::errors; +use crate::errors::{self, ElidedLifetimesAreNotAllowedInDelegations}; use crate::hir_ty_lowering::{HirTyLowerer, InherentAssocCandidate, RegionInferReason}; pub(crate) mod dump; @@ -131,6 +131,7 @@ pub(crate) struct ItemCtxt<'tcx> { tcx: TyCtxt<'tcx>, item_def_id: LocalDefId, tainted_by_errors: Cell>, + lowering_delegation_segment: bool, } /////////////////////////////////////////////////////////////////////////// @@ -241,7 +242,24 @@ fn bad_placeholder<'cx, 'tcx>( impl<'tcx> ItemCtxt<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> { - ItemCtxt { tcx, item_def_id, tainted_by_errors: Cell::new(None) } + ItemCtxt::new_internal(tcx, item_def_id, false) + } + + fn new_internal( + tcx: TyCtxt<'tcx>, + item_def_id: LocalDefId, + delegation: bool, + ) -> ItemCtxt<'tcx> { + ItemCtxt { + tcx, + item_def_id, + tainted_by_errors: Cell::new(None), + lowering_delegation_segment: delegation, + } + } + + pub(crate) fn new_for_delegation(tcx: TyCtxt<'tcx>, item_def_id: LocalDefId) -> ItemCtxt<'tcx> { + ItemCtxt::new_internal(tcx, item_def_id, true) } pub(crate) fn lower_ty(&self, hir_ty: &hir::Ty<'tcx>) -> Ty<'tcx> { @@ -335,8 +353,15 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { .emit(); ty::Region::new_error(self.tcx(), guar) } else { + // If we found elided lifetime during lowering of delegation parent or child + // segment then emit an error, as we need a named lifetime for proper signature + // inheritance (#156848). + if self.lowering_delegation_segment { + self.tcx.dcx().emit_err(ElidedLifetimesAreNotAllowedInDelegations { span }); + } + // This indicates an illegal lifetime in a non-assoc-trait position - ty::Region::new_error_with_message(self.tcx(), span, "unelided lifetime in signature") + ty::Region::new_error_with_message(self.tcx(), span, "inferred lifetime in signature") } } diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index f67181a4655b9..4e5908c4d8885 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -7,7 +7,7 @@ use std::debug_assert_matches; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{DelegationInfo, HirId, PathSegment}; +use rustc_hir::{DelegationInfo, PathSegment}; use rustc_middle::ty::{ self, EarlyBinder, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -551,7 +551,7 @@ pub(crate) fn inherit_predicates_for_delegation_item<'tcx>( } } - let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id); + let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id); let (folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); let self_pos_kind = create_self_position_kind(tcx, def_id, sig_id); let filter_self_preds = matches!(self_pos_kind, SelfPositionKind::AfterLifetimes(true)); @@ -627,7 +627,7 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type)); } - let (parent_args, child_args) = get_delegation_user_specified_args(tcx, def_id); + let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id); let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); let caller_sig = EarlyBinder::bind(caller_sig.skip_binder().fold_with(&mut folder)); @@ -640,18 +640,18 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( // they will be used during delegation signature and predicates inheritance. // Example: reuse Trait::<'static, i32, 1>::foo:: // we want to extract [Self, 'static, i32, 1] for parent and [A, B] for child. -fn get_delegation_user_specified_args<'tcx>( +pub(crate) fn delegation_user_specified_args<'tcx>( tcx: TyCtxt<'tcx>, delegation_id: LocalDefId, ) -> (&'tcx [ty::GenericArg<'tcx>], &'tcx [ty::GenericArg<'tcx>]) { let info = get_delegation_info(tcx, delegation_id); - let get_segment = |hir_id: HirId| -> Option<(&'tcx PathSegment<'tcx>, DefId)> { + let get_segment = |hir_id| -> Option<(&'tcx PathSegment<'tcx>, DefId)> { let segment = tcx.hir_node(hir_id).expect_path_segment(); segment.res.opt_def_id().map(|def_id| (segment, def_id)) }; - let ctx = ItemCtxt::new(tcx, delegation_id); + let ctx = ItemCtxt::new_for_delegation(tcx, delegation_id); let lowerer = ctx.lowerer(); let parent_args = info.parent_args_segment_id.and_then(get_segment).map(|(segment, def_id)| { diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs index 0f549e157c280..b968a626d398f 100644 --- a/compiler/rustc_hir_analysis/src/errors.rs +++ b/compiler/rustc_hir_analysis/src/errors.rs @@ -1680,6 +1680,13 @@ pub(crate) struct DelegationSelfTypeNotSpecified { pub span: Span, } +#[derive(Diagnostic)] +#[diag("inferred lifetimes are not allowed in delegations as we need to inherit signature")] +pub(crate) struct ElidedLifetimesAreNotAllowedInDelegations { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag("method should be `async` or return a future, but it is synchronous")] pub(crate) struct MethodShouldReturnFuture { diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index 1e9bc80749881..4d60f878c6fc4 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -137,6 +137,7 @@ pub fn provide(providers: &mut Providers) { inferred_outlives_crate: outlives::inferred_outlives_crate, inferred_outlives_of: outlives::inferred_outlives_of, inherit_sig_for_delegation_item: delegation::inherit_sig_for_delegation_item, + delegation_user_specified_args: delegation::delegation_user_specified_args, enforce_impl_non_lifetime_params_are_constrained: impl_wf_check::enforce_impl_non_lifetime_params_are_constrained, crate_variances: variance::crate_variances, diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 5add2cf09b7b8..3888916a9420a 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2065,6 +2065,10 @@ rustc_queries! { desc { "inheriting delegation signature" } } + query delegation_user_specified_args(def_id: LocalDefId) -> (&'tcx [GenericArg<'tcx>], &'tcx [GenericArg<'tcx>]) { + desc { "getting delegation user-specified args" } + } + /// Does lifetime resolution on items. Importantly, we can't resolve /// lifetimes directly on things like trait methods, because of trait params. /// See `rustc_resolve::late::lifetimes` for details. diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 2dacf64f8cf85..239451262ac42 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -147,6 +147,10 @@ impl Erasable for (&'_ T0, &'_ T1) { type Storage = [u8; size_of::<(&'_ (), &'_ ())>()]; } +impl Erasable for (&'_ [T0], &'_ [T1]) { + type Storage = [u8; size_of::<(&'_ [()], &'_ [()])>()]; +} + macro_rules! impl_erasable_for_types_with_no_type_params { ($($ty:ty),+ $(,)?) => { $( diff --git a/tests/ui/delegation/generics/generics-gen-args-errors.rs b/tests/ui/delegation/generics/generics-gen-args-errors.rs index 33ce84c024773..4e1ac0a5e4176 100644 --- a/tests/ui/delegation/generics/generics-gen-args-errors.rs +++ b/tests/ui/delegation/generics/generics-gen-args-errors.rs @@ -36,6 +36,7 @@ mod test_1 { //~| ERROR can't use generic parameters from outer item //~| ERROR: unresolved item provided when a constant was expected //~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature } } @@ -44,36 +45,45 @@ mod test_2 { reuse foo::<> as bar1; //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for functions + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo:: as bar2; //~^ ERROR: function takes 3 generic arguments but 2 generic arguments were supplied //~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; //~^ ERROR: use of undeclared lifetime name `'asdasd` //~| ERROR: function takes 2 lifetime arguments but 5 lifetime arguments were supplied //~| ERROR: function takes 3 generic arguments but 2 generic arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + reuse foo:: as bar4; //~^ ERROR: cannot find type `asdasd` in this scope //~| ERROR: function takes 2 lifetime arguments but 1 lifetime argument was supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo::<1, 2, _, 4, 5, _> as bar5; //~^ ERROR: function takes 3 generic arguments but 6 generic arguments were supplied //~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; //~^ ERROR: cannot find type `asd` in this scope //~| ERROR: function takes 3 generic arguments but 5 generic arguments were supplied //~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; //~^ ERROR: use of undeclared lifetime name `'a` //~| ERROR: cannot find type `asd` in this scope //~| ERROR: constant provided when a type was expected + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo::<{}, {}, {}> as bar8; //~^ ERROR: constant provided when a type was expected //~| ERROR: function takes 2 lifetime arguments but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature } mod test_3 { @@ -90,21 +100,26 @@ mod test_3 { //~| ERROR: cannot find type `asdasa` in this scope //~| ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied //~| ERROR: trait takes 2 generic arguments but 6 generic arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::<'static, 'static>::foo as bar2; //~^ ERROR: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; //~^ ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied //~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::<1, 2, true>::foo as bar4; //~^ ERROR: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied //~| ERROR: trait takes 2 generic arguments but 3 generic arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::<'static>::foo as bar5; //~^ ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied //~| ERROR: the placeholder `_` is not allowed within types on item signatures for functions + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; //~^ ERROR: cannot find type `DDDD` in this scope [E0425] @@ -112,12 +127,16 @@ mod test_3 { //~| ERROR: trait takes 2 generic arguments but 3 generic arguments were supplied //~| ERROR: method takes 2 generic arguments but 6 generic arguments were supplied //~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; //~^ ERROR: trait takes 3 lifetime arguments but 1 lifetime argument was supplied //~| ERROR: trait takes 2 generic arguments but 5 generic arguments were supplied //~| ERROR: method takes 2 generic arguments but 5 generic arguments were supplied //~| ERROR: method takes 1 lifetime argument but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature } fn main() {} diff --git a/tests/ui/delegation/generics/generics-gen-args-errors.stderr b/tests/ui/delegation/generics/generics-gen-args-errors.stderr index e17499a0a5031..7aa1766dfef89 100644 --- a/tests/ui/delegation/generics/generics-gen-args-errors.stderr +++ b/tests/ui/delegation/generics/generics-gen-args-errors.stderr @@ -38,7 +38,7 @@ LL | reuse foo:: as xd; = note: nested items are independent from their parent item for everything except for privacy and name resolution error[E0261]: use of undeclared lifetime name `'asdasd` - --> $DIR/generics-gen-args-errors.rs:52:29 + --> $DIR/generics-gen-args-errors.rs:55:29 | LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; | ^^^^^^^ undeclared lifetime @@ -49,7 +49,7 @@ LL | reuse foo'asdasd, ::<'static, _, 'asdasd, 'static, 'static, 'static, _> | ++++++++ error[E0261]: use of undeclared lifetime name `'a` - --> $DIR/generics-gen-args-errors.rs:69:50 + --> $DIR/generics-gen-args-errors.rs:77:50 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^ undeclared lifetime @@ -103,61 +103,61 @@ LL | fn check() { | +++++ error[E0425]: cannot find type `asdasd` in this scope - --> $DIR/generics-gen-args-errors.rs:56:39 + --> $DIR/generics-gen-args-errors.rs:61:39 | LL | reuse foo:: as bar4; | ^^^^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:64:22 + --> $DIR/generics-gen-args-errors.rs:71:22 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:69:27 + --> $DIR/generics-gen-args-errors.rs:77:27 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:84:19 + --> $DIR/generics-gen-args-errors.rs:94:19 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:84:24 + --> $DIR/generics-gen-args-errors.rs:94:24 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:84:29 + --> $DIR/generics-gen-args-errors.rs:94:29 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:84:34 + --> $DIR/generics-gen-args-errors.rs:94:34 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asd` in this scope - --> $DIR/generics-gen-args-errors.rs:84:39 + --> $DIR/generics-gen-args-errors.rs:94:39 | LL | reuse Trait::::foo as bar1; | ^^^ not found in this scope error[E0425]: cannot find type `asdasa` in this scope - --> $DIR/generics-gen-args-errors.rs:84:44 + --> $DIR/generics-gen-args-errors.rs:94:44 | LL | reuse Trait::::foo as bar1; | ^^^^^^ not found in this scope error[E0425]: cannot find type `DDDD` in this scope - --> $DIR/generics-gen-args-errors.rs:109:34 + --> $DIR/generics-gen-args-errors.rs:124:34 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^ not found in this scope @@ -178,20 +178,32 @@ help: add missing lifetime arguments LL | reuse foo::<'a, 'b, A, B, C> as xd; | +++++++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:33:15 + | +LL | reuse foo:: as xd; + | ^^^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:46:11 + | +LL | reuse foo::<> as bar1; + | ^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/generics-gen-args-errors.rs:45:11 + --> $DIR/generics-gen-args-errors.rs:46:11 | LL | reuse foo::<> as bar1; | ^^^ not allowed in type signatures error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:48:11 + --> $DIR/generics-gen-args-errors.rs:50:11 | LL | reuse foo:: as bar2; | ^^^ expected 2 lifetime arguments | note: function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- @@ -201,7 +213,7 @@ LL | reuse foo::<'a, 'b, String, String> as bar2; | +++++++ error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:48:11 + --> $DIR/generics-gen-args-errors.rs:50:11 | LL | reuse foo:: as bar2; | ^^^ ------ ------ supplied 2 generic arguments @@ -209,7 +221,7 @@ LL | reuse foo:: as bar2; | expected 3 generic arguments | note: function defined here, with 3 generic parameters: `T`, `U`, `N` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- @@ -218,8 +230,14 @@ help: add missing generic argument LL | reuse foo:: as bar2; | +++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:50:11 + | +LL | reuse foo:: as bar2; + | ^^^ + error[E0107]: function takes 2 lifetime arguments but 5 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:52:11 + --> $DIR/generics-gen-args-errors.rs:55:11 | LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; | ^^^ --------------------------- help: remove the lifetime arguments @@ -227,19 +245,19 @@ LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; | expected 2 lifetime arguments | note: function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- error[E0107]: function takes 3 generic arguments but 2 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:52:11 + --> $DIR/generics-gen-args-errors.rs:55:11 | LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; | ^^^ expected 3 generic arguments ------- - supplied 2 generic arguments | note: function defined here, with 3 generic parameters: `T`, `U`, `N` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- @@ -248,8 +266,14 @@ help: add missing generic argument LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _, N> as bar3; | +++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:55:11 + | +LL | reuse foo::<'static, _, 'asdasd, 'static, 'static, 'static, _> as bar3; + | ^^^ + error[E0107]: function takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:56:11 + --> $DIR/generics-gen-args-errors.rs:61:11 | LL | reuse foo:: as bar4; | ^^^ ------ supplied 1 lifetime argument @@ -257,7 +281,7 @@ LL | reuse foo:: as bar4; | expected 2 lifetime arguments | note: function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- @@ -266,14 +290,20 @@ help: add missing lifetime argument LL | reuse foo:: as bar4; | +++++++++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:61:11 + | +LL | reuse foo:: as bar4; + | ^^^ + error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:60:11 + --> $DIR/generics-gen-args-errors.rs:66:11 | LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; | ^^^ expected 2 lifetime arguments | note: function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- @@ -283,7 +313,7 @@ LL | reuse foo::<'a, 'b, 1, 2, _, 4, 5, _> as bar5; | +++++++ error[E0107]: function takes 3 generic arguments but 6 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:60:11 + --> $DIR/generics-gen-args-errors.rs:66:11 | LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; | ^^^ --------- help: remove the unnecessary generic arguments @@ -291,19 +321,25 @@ LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; | expected 3 generic arguments | note: function defined here, with 3 generic parameters: `T`, `U`, `N` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:66:11 + | +LL | reuse foo::<1, 2, _, 4, 5, _> as bar5; + | ^^^ + error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:64:11 + --> $DIR/generics-gen-args-errors.rs:71:11 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ expected 2 lifetime arguments | note: function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- @@ -313,7 +349,7 @@ LL | reuse foo::<'a, 'b, 1, 2,asd,String, { let x = 0; }> as bar6; | +++++++ error[E0107]: function takes 3 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:64:11 + --> $DIR/generics-gen-args-errors.rs:71:11 | LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | ^^^ ----------------------- help: remove the unnecessary generic arguments @@ -321,25 +357,37 @@ LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; | expected 3 generic arguments | note: function defined here, with 3 generic parameters: `T`, `U`, `N` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ - - -------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:71:11 + | +LL | reuse foo::<1, 2,asd,String, { let x = 0; }> as bar6; + | ^^^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:77:11 + | +LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; + | ^^^ + error[E0747]: constant provided when a type was expected - --> $DIR/generics-gen-args-errors.rs:69:17 + --> $DIR/generics-gen-args-errors.rs:77:17 | LL | reuse foo::<"asdasd", asd, "askdn", 'static, 'a> as bar7; | ^^^^^^^^ error[E0107]: function takes 2 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:74:11 + --> $DIR/generics-gen-args-errors.rs:83:11 | LL | reuse foo::<{}, {}, {}> as bar8; | ^^^ expected 2 lifetime arguments | note: function defined here, with 2 lifetime parameters: `'a`, `'b` - --> $DIR/generics-gen-args-errors.rs:43:8 + --> $DIR/generics-gen-args-errors.rs:44:8 | LL | fn foo<'a: 'a, 'b: 'b, T: Clone, U: Clone, const N: usize>() {} | ^^^ -- -- @@ -348,14 +396,20 @@ help: add missing lifetime arguments LL | reuse foo::<'a, 'b, {}, {}, {}> as bar8; | +++++++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:83:11 + | +LL | reuse foo::<{}, {}, {}> as bar8; + | ^^^ + error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:84:11 + --> $DIR/generics-gen-args-errors.rs:94:11 | LL | reuse Trait::::foo as bar1; | ^^^^^ expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -365,7 +419,7 @@ LL | reuse Trait::<'b, 'c, 'a, asd, asd, asd, asd, asd, asdasa>::foo as bar1 | +++++++++++ error[E0107]: trait takes 2 generic arguments but 6 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:84:11 + --> $DIR/generics-gen-args-errors.rs:94:11 | LL | reuse Trait::::foo as bar1; | ^^^^^ ----------------------- help: remove the unnecessary generic arguments @@ -373,21 +427,27 @@ LL | reuse Trait::::foo as bar1; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- -error[E0107]: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied +error: inferred lifetimes are not allowed in delegations as we need to inherit signature --> $DIR/generics-gen-args-errors.rs:94:11 | +LL | reuse Trait::::foo as bar1; + | ^^^^^ + +error[E0107]: trait takes 3 lifetime arguments but 2 lifetime arguments were supplied + --> $DIR/generics-gen-args-errors.rs:105:11 + | LL | reuse Trait::<'static, 'static>::foo as bar2; | ^^^^^ ------- ------- supplied 2 lifetime arguments | | | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -396,20 +456,26 @@ help: add missing lifetime argument LL | reuse Trait::<'static, 'static, 'static>::foo as bar2; | +++++++++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:105:11 + | +LL | reuse Trait::<'static, 'static>::foo as bar2; + | ^^^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/generics-gen-args-errors.rs:94:11 + --> $DIR/generics-gen-args-errors.rs:105:11 | LL | reuse Trait::<'static, 'static>::foo as bar2; | ^^^^^ not allowed in type signatures error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:97:11 + --> $DIR/generics-gen-args-errors.rs:109:11 | LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | ^^^^^ expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -419,7 +485,7 @@ LL | reuse Trait::<'b, 'c, 'a, 1, 2, 3, 4, 5>::foo as bar3; | +++++++++++ error[E0107]: trait takes 2 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:97:11 + --> $DIR/generics-gen-args-errors.rs:109:11 | LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | ^^^^^ --------- help: remove the unnecessary generic arguments @@ -427,19 +493,25 @@ LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:109:11 + | +LL | reuse Trait::<1, 2, 3, 4, 5>::foo as bar3; + | ^^^^^ + error[E0107]: trait takes 3 lifetime arguments but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:101:11 + --> $DIR/generics-gen-args-errors.rs:114:11 | LL | reuse Trait::<1, 2, true>::foo as bar4; | ^^^^^ expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -449,7 +521,7 @@ LL | reuse Trait::<'b, 'c, 'a, 1, 2, true>::foo as bar4; | +++++++++++ error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:101:11 + --> $DIR/generics-gen-args-errors.rs:114:11 | LL | reuse Trait::<1, 2, true>::foo as bar4; | ^^^^^ ------ help: remove the unnecessary generic argument @@ -457,13 +529,19 @@ LL | reuse Trait::<1, 2, true>::foo as bar4; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:114:11 + | +LL | reuse Trait::<1, 2, true>::foo as bar4; + | ^^^^^ + error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:105:11 + --> $DIR/generics-gen-args-errors.rs:119:11 | LL | reuse Trait::<'static>::foo as bar5; | ^^^^^ ------- supplied 1 lifetime argument @@ -471,7 +549,7 @@ LL | reuse Trait::<'static>::foo as bar5; | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -480,14 +558,20 @@ help: add missing lifetime arguments LL | reuse Trait::<'static, 'static, 'static>::foo as bar5; | ++++++++++++++++++ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:119:11 + | +LL | reuse Trait::<'static>::foo as bar5; + | ^^^^^ + error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions - --> $DIR/generics-gen-args-errors.rs:105:11 + --> $DIR/generics-gen-args-errors.rs:119:11 | LL | reuse Trait::<'static>::foo as bar5; | ^^^^^ not allowed in type signatures error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:109:11 + --> $DIR/generics-gen-args-errors.rs:124:11 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^^ - supplied 1 lifetime argument @@ -495,7 +579,7 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -505,7 +589,7 @@ LL | reuse Trait::<1, 'static, 'static, 2, 'static, DDDD>::foo::<1, 2, 3, 4, | ++++++++++++++++++ error[E0107]: trait takes 2 generic arguments but 3 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:109:11 + --> $DIR/generics-gen-args-errors.rs:124:11 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^^^ --------------- help: remove the unnecessary generic argument @@ -513,19 +597,25 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:124:11 + | +LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ^^^^^ + error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:109:41 + --> $DIR/generics-gen-args-errors.rs:124:41 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^ expected 1 lifetime argument | note: method defined here, with 1 lifetime parameter: `'d` - --> $DIR/generics-gen-args-errors.rs:81:12 + --> $DIR/generics-gen-args-errors.rs:91:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ -- @@ -535,7 +625,7 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<'d, 1, 2, 3, 4, 5, 6> as bar6 | +++ error[E0107]: method takes 2 generic arguments but 6 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:109:41 + --> $DIR/generics-gen-args-errors.rs:124:41 | LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | ^^^ ------------ help: remove the unnecessary generic arguments @@ -543,13 +633,19 @@ LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; | expected 2 generic arguments | note: method defined here, with 2 generic parameters: `U`, `M` - --> $DIR/generics-gen-args-errors.rs:81:12 + --> $DIR/generics-gen-args-errors.rs:91:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ - ------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:124:41 + | +LL | reuse Trait::<1, 2, 'static, DDDD>::foo::<1, 2, 3, 4, 5, 6> as bar6; + | ^^^ + error[E0107]: trait takes 3 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/generics-gen-args-errors.rs:116:11 + --> $DIR/generics-gen-args-errors.rs:133:11 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^^^ ----- supplied 1 lifetime argument @@ -557,7 +653,7 @@ LL | reuse Trait::::foo::<1, 2, 3, _, | expected 3 lifetime arguments | note: trait defined here, with 3 lifetime parameters: `'b`, `'c`, `'a` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ -- -- -- @@ -567,7 +663,7 @@ LL | reuse Trait::: | ++++++++++++++++++ error[E0107]: trait takes 2 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:116:11 + --> $DIR/generics-gen-args-errors.rs:133:11 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^^^ --- help: remove the unnecessary generic argument @@ -575,19 +671,25 @@ LL | reuse Trait::::foo::<1, 2, 3, _, | expected 2 generic arguments | note: trait defined here, with 2 generic parameters: `T`, `N` - --> $DIR/generics-gen-args-errors.rs:80:11 + --> $DIR/generics-gen-args-errors.rs:90:11 | LL | trait Trait<'b, 'c, 'a, T, const N: usize>: Sized { | ^^^^^ - -------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:133:11 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^^^^^ + error[E0107]: method takes 1 lifetime argument but 0 lifetime arguments were supplied - --> $DIR/generics-gen-args-errors.rs:116:59 + --> $DIR/generics-gen-args-errors.rs:133:59 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^ expected 1 lifetime argument | note: method defined here, with 1 lifetime parameter: `'d` - --> $DIR/generics-gen-args-errors.rs:81:12 + --> $DIR/generics-gen-args-errors.rs:91:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ -- @@ -597,7 +699,7 @@ LL | reuse Trait::::foo::<'d, 1, 2, 3 | +++ error[E0107]: method takes 2 generic arguments but 5 generic arguments were supplied - --> $DIR/generics-gen-args-errors.rs:116:59 + --> $DIR/generics-gen-args-errors.rs:133:59 | LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; | ^^^ --------- help: remove the unnecessary generic arguments @@ -605,11 +707,17 @@ LL | reuse Trait::::foo::<1, 2, 3, _, | expected 2 generic arguments | note: method defined here, with 2 generic parameters: `U`, `M` - --> $DIR/generics-gen-args-errors.rs:81:12 + --> $DIR/generics-gen-args-errors.rs:91:12 | LL | fn foo<'d: 'd, U, const M: bool>(self) {} | ^^^ - ------------- +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/generics-gen-args-errors.rs:133:59 + | +LL | reuse Trait::::foo::<1, 2, 3, _, 6> as bar7; + | ^^^ + error[E0107]: function takes 3 generic arguments but 6 generic arguments were supplied --> $DIR/generics-gen-args-errors.rs:10:9 | @@ -681,12 +789,12 @@ LL | reuse foo:: as xd; | + + error[E0747]: constant provided when a type was expected - --> $DIR/generics-gen-args-errors.rs:74:17 + --> $DIR/generics-gen-args-errors.rs:83:17 | LL | reuse foo::<{}, {}, {}> as bar8; | ^^ -error: aborting due to 57 previous errors +error: aborting due to 75 previous errors Some errors have detailed explanations: E0107, E0121, E0261, E0401, E0423, E0425, E0747. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/delegation/generics/unelided-lifetime-ice-154178.rs b/tests/ui/delegation/generics/unelided-lifetime-ice-154178.rs index 3a53aad7132a5..e30b7ad624d42 100644 --- a/tests/ui/delegation/generics/unelided-lifetime-ice-154178.rs +++ b/tests/ui/delegation/generics/unelided-lifetime-ice-154178.rs @@ -7,6 +7,7 @@ fn foo<'b: 'b, const N: usize>() {} trait Trait { reuse foo::<1>; //~^ ERROR: function takes 1 lifetime argument but 0 lifetime arguments were supplied + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature } fn main() {} diff --git a/tests/ui/delegation/generics/unelided-lifetime-ice-154178.stderr b/tests/ui/delegation/generics/unelided-lifetime-ice-154178.stderr index 3938e66d71c95..c70cb1c7d7519 100644 --- a/tests/ui/delegation/generics/unelided-lifetime-ice-154178.stderr +++ b/tests/ui/delegation/generics/unelided-lifetime-ice-154178.stderr @@ -14,6 +14,12 @@ help: add missing lifetime argument LL | reuse foo::<'b, 1>; | +++ -error: aborting due to 1 previous error +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/unelided-lifetime-ice-154178.rs:8:11 + | +LL | reuse foo::<1>; + | ^^^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0107`. diff --git a/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs new file mode 100644 index 0000000000000..fad06b37ae416 --- /dev/null +++ b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Z deduplicate-diagnostics=yes + +#![feature(fn_delegation)] + +trait Trait { + fn foo<'a: 'a>(&self) {} +} + +struct F; +impl Trait for F {} + +struct S(F); +impl S { + reuse Trait::foo::<> { self.0 } + //~^ ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + reuse Trait::foo::<'_> as bar { self.0 } + //~^ ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| WARN: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + //~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +} + +fn main() {} diff --git a/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr new file mode 100644 index 0000000000000..464b6a3a76819 --- /dev/null +++ b/tests/ui/delegation/generics/unelided-lifetime-in-sig-ice-156848.stderr @@ -0,0 +1,27 @@ +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/unelided-lifetime-in-sig-ice-156848.rs:14:18 + | +LL | reuse Trait::foo::<> { self.0 } + | ^^^ + +warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present + --> $DIR/unelided-lifetime-in-sig-ice-156848.rs:16:24 + | +LL | fn foo<'a: 'a>(&self) {} + | - the late bound lifetime parameter is introduced here +... +LL | reuse Trait::foo::<'_> as bar { self.0 } + | ^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #42868 + = note: `#[warn(late_bound_lifetime_arguments)]` (part of `#[warn(future_incompatible)]`) on by default + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/unelided-lifetime-in-sig-ice-156848.rs:16:24 + | +LL | reuse Trait::foo::<'_> as bar { self.0 } + | ^^ + +error: aborting due to 2 previous errors; 1 warning emitted + diff --git a/tests/ui/delegation/wrong-lifetime-rib.rs b/tests/ui/delegation/wrong-lifetime-rib.rs index 01645f20bf7b1..e9214b7c42260 100644 --- a/tests/ui/delegation/wrong-lifetime-rib.rs +++ b/tests/ui/delegation/wrong-lifetime-rib.rs @@ -15,7 +15,20 @@ mod ice_156342 { fn foo() {} reuse foo::<&&&&&&&&&&()> as foo1; + //~^ ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature reuse foo::<&std::borrow::Cow<'_, &()>> as foo2; + //~^ ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature + //~| ERROR: inferred lifetimes are not allowed in delegations as we need to inherit signature } mod ice_156758 { diff --git a/tests/ui/delegation/wrong-lifetime-rib.stderr b/tests/ui/delegation/wrong-lifetime-rib.stderr index 0c4499eec192d..ca759995fec42 100644 --- a/tests/ui/delegation/wrong-lifetime-rib.stderr +++ b/tests/ui/delegation/wrong-lifetime-rib.stderr @@ -4,8 +4,86 @@ error[E0423]: expected function, found unit variant `None` LL | reuse None::<&()>; | ^^^^^^^^^^^ not a function +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:18 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:19 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:20 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:21 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:22 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:23 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:24 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:25 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:26 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:17:27 + | +LL | reuse foo::<&&&&&&&&&&()> as foo1; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:28:18 + | +LL | reuse foo::<&std::borrow::Cow<'_, &()>> as foo2; + | ^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:28:35 + | +LL | reuse foo::<&std::borrow::Cow<'_, &()>> as foo2; + | ^^ + +error: inferred lifetimes are not allowed in delegations as we need to inherit signature + --> $DIR/wrong-lifetime-rib.rs:28:40 + | +LL | reuse foo::<&std::borrow::Cow<'_, &()>> as foo2; + | ^ + error[E0782]: expected a type, found a trait - --> $DIR/wrong-lifetime-rib.rs:26:10 + --> $DIR/wrong-lifetime-rib.rs:39:10 | LL | impl X { | ^ @@ -20,7 +98,7 @@ LL | impl X for /* Type */ { | ++++++++++++++ error[E0782]: expected a type, found a trait - --> $DIR/wrong-lifetime-rib.rs:35:10 + --> $DIR/wrong-lifetime-rib.rs:48:10 | LL | impl X { | ^ @@ -44,7 +122,7 @@ LL | impl Trait { = note: for more details about the orphan rules, see error[E0223]: ambiguous associated type - --> $DIR/wrong-lifetime-rib.rs:27:16 + --> $DIR/wrong-lifetime-rib.rs:40:16 | LL | reuse<<<&Project> :: Ty> :: Ty as Iterator>::next; | ^^^^^^^^^^^^^^^^ @@ -56,7 +134,7 @@ LL + reuse<<<&() as Example>::Ty> :: Ty as Iterator>::next; | error[E0782]: expected a type, found a trait - --> $DIR/wrong-lifetime-rib.rs:37:21 + --> $DIR/wrong-lifetime-rib.rs:50:21 | LL | let _: &X; | ^ @@ -66,7 +144,7 @@ help: you can add the `dyn` keyword if you want a trait object LL | let _: &dyn X; | +++ -error: aborting due to 6 previous errors +error: aborting due to 19 previous errors Some errors have detailed explanations: E0116, E0223, E0423, E0782. For more information about an error, try `rustc --explain E0116`. From 28cfce7e7d02886e09dff8a92529971fe9909758 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 3 Jun 2026 14:09:22 +0300 Subject: [PATCH 26/26] Move out statements out of delegation's callee first arg --- compiler/rustc_ast_lowering/src/delegation.rs | 44 +-- tests/pretty/delegation-inline-attribute.pp | 54 ++-- tests/pretty/hir-delegation.pp | 2 +- tests/ui/delegation/ice-issue-124347.stderr | 4 +- tests/ui/delegation/inner-attr.stderr | 4 +- .../delegation/self-coercion-block-errors.rs | 58 ++++ .../self-coercion-block-errors.stderr | 239 +++++++++++++++ tests/ui/delegation/self-coercion-errors.rs | 7 +- .../ui/delegation/self-coercion-errors.stderr | 271 +++++++++--------- .../self-coercion-static-free.stderr | 32 +++ tests/ui/delegation/target-expr-pass.rs | 10 +- tests/ui/delegation/target-expr-pass.stderr | 6 +- tests/ui/delegation/target-expr.rs | 3 +- tests/ui/delegation/target-expr.stderr | 30 +- .../zero-args-delegations-ice-154332.stderr | 4 +- 15 files changed, 546 insertions(+), 222 deletions(-) create mode 100644 tests/ui/delegation/self-coercion-block-errors.rs create mode 100644 tests/ui/delegation/self-coercion-block-errors.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index 5ea62010c3135..4a5363b379f8c 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -408,11 +408,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let block_id = self.lower_body(|this| { let mut parameters: Vec> = Vec::with_capacity(param_count); let mut args: Vec> = Vec::with_capacity(param_count); + let mut stmts: &[hir::Stmt<'hir>] = &[]; for idx in 0..param_count { let (param, pat_node_id) = this.generate_param(is_method, idx, span); parameters.push(param); + let generate_arg = + |this: &mut Self| this.generate_arg(is_method, idx, param.pat.hir_id, span); + let arg = if let Some(block) = block && idx == 0 { @@ -424,10 +428,24 @@ impl<'hir> LoweringContext<'_, 'hir> { self_resolver.visit_block(block); // Target expr needs to lower `self` path. this.ident_and_label_to_local_id.insert(pat_node_id, param.pat.hir_id.local_id); - this.lower_target_expr(&block) + + // Lower with `HirId::INVALID` as we will use only expr and stmts. + // FIXME(fn_delegation): Alternatives for target expression lowering: + // https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600. + let block = this.lower_block_noalloc(HirId::INVALID, block, false); + + stmts = block.stmts; + + // The behavior of the delegation's target expression differs from the + // behavior of the usual block, where if there is no final expression + // the `()` is returned. In case of the similar situation in delegation + // (no final expression) we propagate first argument instead of replacing + // it with `()`. + if let Some(&expr) = block.expr { expr } else { generate_arg(this) } } else { - this.generate_arg(is_method, idx, param.pat.hir_id, span) + generate_arg(this) }; + args.push(arg); } @@ -439,11 +457,11 @@ impl<'hir> LoweringContext<'_, 'hir> { if param_count == 0 && let Some(block) = block { - args.push(this.lower_target_expr(&block)); + args.push(this.lower_block_expr(&block)); } let (final_expr, hir_id) = - this.finalize_body_lowering(delegation, args, generics, span); + this.finalize_body_lowering(delegation, stmts, args, generics, span); call_expr_id = hir_id; @@ -455,22 +473,10 @@ impl<'hir> LoweringContext<'_, 'hir> { (block_id, call_expr_id) } - // FIXME(fn_delegation): Alternatives for target expression lowering: - // https://github.com/rust-lang/rfcs/pull/3530#issuecomment-2197170600. - fn lower_target_expr(&mut self, block: &Block) -> hir::Expr<'hir> { - if let [stmt] = block.stmts.as_slice() - && let StmtKind::Expr(expr) = &stmt.kind - { - return self.lower_expr_mut(expr); - } - - let block = self.lower_block(block, false); - self.mk_expr(hir::ExprKind::Block(block, None), block.span) - } - fn finalize_body_lowering( &mut self, delegation: &Delegation, + stmts: &'hir [hir::Stmt<'hir>], args: Vec>, generics: &mut GenericsGenerationResults<'hir>, span: Span, @@ -522,7 +528,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let call = self.arena.alloc(self.mk_expr(hir::ExprKind::Call(callee_path, args), span)); let block = self.arena.alloc(hir::Block { - stmts: &[], + stmts, expr: Some(call), hir_id: self.next_id(), rules: hir::BlockCheckMode::DefaultBlock, @@ -587,7 +593,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let callee_path = this.arena.alloc(this.mk_expr(hir::ExprKind::Path(path), span)); let args = if let Some(block) = delegation.body.as_ref() { - this.arena.alloc_slice(&[this.lower_target_expr(block)]) + this.arena.alloc_slice(&[this.lower_block_expr(block)]) } else { &mut [] }; diff --git a/tests/pretty/delegation-inline-attribute.pp b/tests/pretty/delegation-inline-attribute.pp index fc409aa636d5c..8cf2d98eeb412 100644 --- a/tests/pretty/delegation-inline-attribute.pp +++ b/tests/pretty/delegation-inline-attribute.pp @@ -38,34 +38,32 @@ fn foo(self: _) -> _ { - Trait::foo( - // Check that #[inline(hint)] is added to foo0 reuse inside another reuse - - // Check that #[inline(hint)] is added when other attributes present in inner reuse - - // Check that #[inline(never)] is preserved in inner reuse - - // Check that #[inline(always)] is preserved in inner reuse - - // Check that #[inline(never)] is preserved when there are other attributes in inner reuse - { - #[attr = Inline(Hint)] - fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) } - #[attr = Cold] - #[attr = MustUse] - #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}] - #[attr = Inline(Hint)] - fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) } - #[attr = Inline(Never)] - fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) } - #[attr = Inline(Always)] - fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) } - #[attr = Cold] - #[attr = MustUse] - #[attr = Inline(Never)] - #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}] - fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) } - }) + // Check that #[inline(hint)] is added to foo0 reuse inside another reuse + #[attr = Inline(Hint)] + fn foo0(arg0: _) -> _ { to_reuse::foo(self + 1) } + + // Check that #[inline(hint)] is added when other attributes present in inner reuse + #[attr = Cold] + #[attr = MustUse] + #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}] + #[attr = Inline(Hint)] + fn foo1(arg0: _) -> _ { to_reuse::foo(self / 2) } + + // Check that #[inline(never)] is preserved in inner reuse + #[attr = Inline(Never)] + fn foo2(arg0: _) -> _ { to_reuse::foo(self / 2) } + + // Check that #[inline(always)] is preserved in inner reuse + #[attr = Inline(Always)] + fn foo3(arg0: _) -> _ { to_reuse::foo(self / 2) } + + // Check that #[inline(never)] is preserved when there are other attributes in inner reuse + #[attr = Cold] + #[attr = MustUse] + #[attr = Inline(Never)] + #[attr = Deprecated {deprecation: Deprecation {since: Unspecified}}] + fn foo4(arg0: _) -> _ { to_reuse::foo(self / 2) } + Trait::foo(self) } // Check that #[inline(hint)] is added when there are other attributes present in trait reuse diff --git a/tests/pretty/hir-delegation.pp b/tests/pretty/hir-delegation.pp index 28bb49458ce1d..375460e86542b 100644 --- a/tests/pretty/hir-delegation.pp +++ b/tests/pretty/hir-delegation.pp @@ -12,7 +12,7 @@ trait G { #[attr = Inline(Hint)] - fn b(arg0: _) -> _ { b::({ }) } + fn b(arg0: _) -> _ { b::(arg0) } } mod m { diff --git a/tests/ui/delegation/ice-issue-124347.stderr b/tests/ui/delegation/ice-issue-124347.stderr index 9c0125d3a0852..dc279409d7b62 100644 --- a/tests/ui/delegation/ice-issue-124347.stderr +++ b/tests/ui/delegation/ice-issue-124347.stderr @@ -14,7 +14,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/ice-issue-124347.rs:4:18 | LL | reuse Trait::foo { &self.0 } - | ^^^ ------- unexpected argument + | ^^^ ----------- unexpected argument | note: associated function defined here --> $DIR/ice-issue-124347.rs:4:18 @@ -24,7 +24,7 @@ LL | reuse Trait::foo { &self.0 } help: remove the extra argument | LL - reuse Trait::foo { &self.0 } -LL + reuse Trait::fo&self.0 } +LL + reuse Trait::fo{ &self.0 } | warning: function cannot return without recursing diff --git a/tests/ui/delegation/inner-attr.stderr b/tests/ui/delegation/inner-attr.stderr index 307586ccef93d..9f4b66818062e 100644 --- a/tests/ui/delegation/inner-attr.stderr +++ b/tests/ui/delegation/inner-attr.stderr @@ -13,7 +13,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/inner-attr.rs:5:7 | LL | reuse a as b { #![rustc_dummy] self } - | ^ ---- unexpected argument + | ^ ------------------------ unexpected argument | note: function defined here --> $DIR/inner-attr.rs:3:4 @@ -23,7 +23,7 @@ LL | fn a() {} help: remove the extra argument | LL - reuse a as b { #![rustc_dummy] self } -LL + reuse self } +LL + reuse { #![rustc_dummy] self } | error: aborting due to 2 previous errors diff --git a/tests/ui/delegation/self-coercion-block-errors.rs b/tests/ui/delegation/self-coercion-block-errors.rs new file mode 100644 index 0000000000000..cd8a72b9d8818 --- /dev/null +++ b/tests/ui/delegation/self-coercion-block-errors.rs @@ -0,0 +1,58 @@ +// Test different scenarios with impossible adjustments due to blocks +// or no-op target expressions. + +#![feature(fn_delegation)] + +trait Trait: Sized { + fn by_value(self) -> i32 { 1 } + fn by_mut_ref(&mut self) -> i32 { 2 } + fn by_ref(&self) -> i32 { 3 } +} + +struct F; +impl Trait for F {} + +struct Struct(F); +reuse impl Trait for Struct { self.0 } + +struct S(F); +reuse impl Trait for S { { self.0 } } +//~^ ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a mutable reference + +struct S1(F); +reuse impl Trait for S1 { { { { { { self.0 } } } } } } +//~^ ERROR: cannot move out of `self` which is behind a shared reference +//~| ERROR: cannot move out of `self` which is behind a mutable reference + +struct S2(F); +reuse impl Trait for S2 { } +//~^ WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] + +struct S3(F); +reuse impl Trait for S3 { (); } +//~^ WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] + +struct S4(F); +reuse impl Trait for S4 { println!(); } +//~^ WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] + +struct S5(F); +reuse impl Trait for S5 { fn foo() {} } +//~^ WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] + +struct S6(F); +reuse impl Trait for S6; +//~^ WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] +//~| WARN: function cannot return without recursing [unconditional_recursion] + +fn main() {} diff --git a/tests/ui/delegation/self-coercion-block-errors.stderr b/tests/ui/delegation/self-coercion-block-errors.stderr new file mode 100644 index 0000000000000..50e1aa01d28e6 --- /dev/null +++ b/tests/ui/delegation/self-coercion-block-errors.stderr @@ -0,0 +1,239 @@ +error[E0507]: cannot move out of `self` which is behind a mutable reference + --> $DIR/self-coercion-block-errors.rs:19:28 + | +LL | reuse impl Trait for S { { self.0 } } + | ^^^^^^ move occurs because `self.0` has type `F`, which does not implement the `Copy` trait + | +note: if `F` implemented `Clone`, you could clone the value + --> $DIR/self-coercion-block-errors.rs:12:1 + | +LL | struct F; + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | reuse impl Trait for S { { self.0 } } + | ------ you could clone this value + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/self-coercion-block-errors.rs:19:28 + | +LL | reuse impl Trait for S { { self.0 } } + | ^^^^^^ move occurs because `self.0` has type `F`, which does not implement the `Copy` trait + | +note: if `F` implemented `Clone`, you could clone the value + --> $DIR/self-coercion-block-errors.rs:12:1 + | +LL | struct F; + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | reuse impl Trait for S { { self.0 } } + | ------ you could clone this value + +error[E0507]: cannot move out of `self` which is behind a mutable reference + --> $DIR/self-coercion-block-errors.rs:24:37 + | +LL | reuse impl Trait for S1 { { { { { { self.0 } } } } } } + | ^^^^^^ move occurs because `self.0` has type `F`, which does not implement the `Copy` trait + | +note: if `F` implemented `Clone`, you could clone the value + --> $DIR/self-coercion-block-errors.rs:12:1 + | +LL | struct F; + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | reuse impl Trait for S1 { { { { { { self.0 } } } } } } + | ------ you could clone this value + +error[E0507]: cannot move out of `self` which is behind a shared reference + --> $DIR/self-coercion-block-errors.rs:24:37 + | +LL | reuse impl Trait for S1 { { { { { { self.0 } } } } } } + | ^^^^^^ move occurs because `self.0` has type `F`, which does not implement the `Copy` trait + | +note: if `F` implemented `Clone`, you could clone the value + --> $DIR/self-coercion-block-errors.rs:12:1 + | +LL | struct F; + | ^^^^^^^^ consider implementing `Clone` for this type +... +LL | reuse impl Trait for S1 { { { { { { self.0 } } } } } } + | ------ you could clone this value + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:29:1 + | +LL | reuse impl Trait for S2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:29:1 + | +LL | reuse impl Trait for S2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:29:1 + | +LL | reuse impl Trait for S2 { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:35:1 + | +LL | reuse impl Trait for S3 { (); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:35:1 + | +LL | reuse impl Trait for S3 { (); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:35:1 + | +LL | reuse impl Trait for S3 { (); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:41:1 + | +LL | reuse impl Trait for S4 { println!(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:41:1 + | +LL | reuse impl Trait for S4 { println!(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:41:1 + | +LL | reuse impl Trait for S4 { println!(); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:47:1 + | +LL | reuse impl Trait for S5 { fn foo() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:47:1 + | +LL | reuse impl Trait for S5 { fn foo() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:47:1 + | +LL | reuse impl Trait for S5 { fn foo() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:53:1 + | +LL | reuse impl Trait for S6; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:53:1 + | +LL | reuse impl Trait for S6; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +warning: function cannot return without recursing + --> $DIR/self-coercion-block-errors.rs:53:1 + | +LL | reuse impl Trait for S6; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | cannot return without recursing + | recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors; 15 warnings emitted + +For more information about this error, try `rustc --explain E0507`. diff --git a/tests/ui/delegation/self-coercion-errors.rs b/tests/ui/delegation/self-coercion-errors.rs index 6c8356bd7495b..1d37792d7bba7 100644 --- a/tests/ui/delegation/self-coercion-errors.rs +++ b/tests/ui/delegation/self-coercion-errors.rs @@ -41,12 +41,12 @@ struct S1(F); impl S1 { reuse Trait::{by_value, by_mut_ref, by_ref} { - //~^ ERROR: mismatched types - //~| ERROR: mismatched types - //~| ERROR: the trait bound `fn() -> F {foo}: Trait` is not satisfied println!("123"); let x = &self.0; foo + //~^ ERROR: mismatched types + //~| ERROR: mismatched types + //~| ERROR: the trait bound `fn() -> F {foo}: Trait` is not satisfied } } @@ -59,6 +59,7 @@ impl S2 { let x = foo(); x + //~^ ERROR: cannot borrow `x` as mutable, as it is not declared as mutable } } diff --git a/tests/ui/delegation/self-coercion-errors.stderr b/tests/ui/delegation/self-coercion-errors.stderr index 89308b15d2d84..7941940ddcd4c 100644 --- a/tests/ui/delegation/self-coercion-errors.stderr +++ b/tests/ui/delegation/self-coercion-errors.stderr @@ -1,32 +1,25 @@ error[E0277]: the trait bound `fn() -> F {foo}: Trait` is not satisfied - --> $DIR/self-coercion-errors.rs:43:49 - | -LL | reuse Trait::{by_value, by_mut_ref, by_ref} { - | ___________________--------______________________^ - | | | - | | required by a bound introduced by this call -... | -LL | | foo - | | --- this tail expression is of type `fn() -> F {foo}` -LL | | } - | |_____^ the trait `Trait` is not implemented for fn item `fn() -> F {foo}` + --> $DIR/self-coercion-errors.rs:46:9 + | +LL | reuse Trait::{by_value, by_mut_ref, by_ref} { + | -------- required by a bound introduced by this call +... +LL | foo + | ^^^ the trait `Trait` is not implemented for fn item `fn() -> F {foo}` | help: use parentheses to call this function | -LL | }() - | ++ +LL | foo() + | ++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:43:49 + --> $DIR/self-coercion-errors.rs:46:9 | -LL | reuse Trait::{by_value, by_mut_ref, by_ref} { - | _____________________________----------__________^ - | | | - | | arguments to this function are incorrect -... | -LL | | foo -LL | | } - | |_____^ expected `&mut _`, found fn item +LL | reuse Trait::{by_value, by_mut_ref, by_ref} { + | ---------- arguments to this function are incorrect +... +LL | foo + | ^^^ expected `&mut _`, found fn item | = note: expected mutable reference `&mut _` found fn item `fn() -> F {foo}` @@ -41,16 +34,13 @@ LL | &mut foo | ++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:43:49 + --> $DIR/self-coercion-errors.rs:46:9 | -LL | reuse Trait::{by_value, by_mut_ref, by_ref} { - | _________________________________________------__^ - | | | - | | arguments to this function are incorrect -... | -LL | | foo -LL | | } - | |_____^ expected `&_`, found fn item +LL | reuse Trait::{by_value, by_mut_ref, by_ref} { + | ------ arguments to this function are incorrect +... +LL | foo + | ^^^ expected `&_`, found fn item | = note: expected reference `&_` found fn item `fn() -> F {foo}` @@ -65,7 +55,7 @@ LL | &foo | + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Box<_>`, found `&mut F` @@ -86,7 +76,7 @@ LL | reuse Trait::* { Box::new(&mut self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Arc<_>`, found `&mut F` @@ -106,7 +96,7 @@ LL | reuse Trait::* { (&mut self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Rc<_>`, found `&mut F` @@ -126,7 +116,7 @@ LL | reuse Trait::* { (&mut self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Pin>`, found `&mut F` @@ -146,7 +136,7 @@ LL | reuse Trait::* { Box::pin(&mut self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Pin>`, found `&mut F` @@ -162,7 +152,7 @@ LL | fn pin_rc(self: Pin>) -> i32 { 8 } | ^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Pin>`, found `&mut F` @@ -178,7 +168,7 @@ LL | fn pin_arc(self: Pin>) -> i32 { 9 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ expected `Box>`, found `&mut F` @@ -194,7 +184,7 @@ LL | fn box_box(self: Box>) -> i32 { 10 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Box<_>`, found `&F` @@ -215,7 +205,7 @@ LL | reuse Trait::* { Box::new(&self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Arc<_>`, found `&F` @@ -235,7 +225,7 @@ LL | reuse Trait::* { (&self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Rc<_>`, found `&F` @@ -255,7 +245,7 @@ LL | reuse Trait::* { (&self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Pin>`, found `&F` @@ -275,7 +265,7 @@ LL | reuse Trait::* { Box::pin(&self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Pin>`, found `&F` @@ -291,7 +281,7 @@ LL | fn pin_rc(self: Pin>) -> i32 { 8 } | ^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Pin>`, found `&F` @@ -307,7 +297,7 @@ LL | fn pin_arc(self: Pin>) -> i32 { 9 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ expected `Box>`, found `&F` @@ -323,7 +313,7 @@ LL | fn box_box(self: Box>) -> i32 { 10 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Box<_>`, found `&&&&F` @@ -344,7 +334,7 @@ LL | reuse Trait::* { Box::new(&&&&self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Arc<_>`, found `&&&&F` @@ -364,7 +354,7 @@ LL | reuse Trait::* { (&&&&self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Rc<_>`, found `&&&&F` @@ -384,7 +374,7 @@ LL | reuse Trait::* { (&&&&self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Pin>`, found `&&&&F` @@ -404,7 +394,7 @@ LL | reuse Trait::* { Box::pin(&&&&self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Pin>`, found `&&&&F` @@ -420,7 +410,7 @@ LL | fn pin_rc(self: Pin>) -> i32 { 8 } | ^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Pin>`, found `&&&&F` @@ -436,7 +426,7 @@ LL | fn pin_arc(self: Pin>) -> i32 { 9 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ expected `Box>`, found `&&&&F` @@ -452,7 +442,7 @@ LL | fn box_box(self: Box>) -> i32 { 10 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Box<_>`, found `&F` @@ -473,7 +463,7 @@ LL + reuse Trait::* { self.0 } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Arc<_>`, found `&F` @@ -493,7 +483,7 @@ LL | reuse Trait::* { self.0.as_ref().into() } | +++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Rc<_>`, found `&F` @@ -513,7 +503,7 @@ LL | reuse Trait::* { self.0.as_ref().into() } | +++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Pin>`, found `&F` @@ -533,7 +523,7 @@ LL | reuse Trait::* { Box::pin(self.0.as_ref()) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Pin>`, found `&F` @@ -549,7 +539,7 @@ LL | fn pin_rc(self: Pin>) -> i32 { 8 } | ^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Pin>`, found `&F` @@ -565,7 +555,7 @@ LL | fn pin_arc(self: Pin>) -> i32 { 9 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ expected `Box>`, found `&F` @@ -581,7 +571,7 @@ LL | fn box_box(self: Box>) -> i32 { 10 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Box<_>`, found `&mut &mut &mut F` @@ -602,7 +592,7 @@ LL | reuse Trait::* { Box::new(&mut &mut &mut self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Arc<_>`, found `&mut &mut &mut F` @@ -622,7 +612,7 @@ LL | reuse Trait::* { (&mut &mut &mut self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Rc<_>`, found `&mut &mut &mut F` @@ -642,7 +632,7 @@ LL | reuse Trait::* { (&mut &mut &mut self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Pin>`, found `&mut &mut &mut F` @@ -662,7 +652,7 @@ LL | reuse Trait::* { Box::pin(&mut &mut &mut self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Pin>`, found `&mut &mut &mut F` @@ -678,7 +668,7 @@ LL | fn pin_rc(self: Pin>) -> i32 { 8 } | ^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Pin>`, found `&mut &mut &mut F` @@ -694,7 +684,7 @@ LL | fn pin_arc(self: Pin>) -> i32 { 9 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ expected `Box>`, found `&mut &mut &mut F` @@ -710,7 +700,7 @@ LL | fn box_box(self: Box>) -> i32 { 10 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Box<_>`, found `&&mut F` @@ -731,7 +721,7 @@ LL | reuse Trait::* { Box::new(&&mut self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Arc<_>`, found `&&mut F` @@ -751,7 +741,7 @@ LL | reuse Trait::* { (&&mut self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Rc<_>`, found `&&mut F` @@ -771,7 +761,7 @@ LL | reuse Trait::* { (&&mut self.0).into() } | + ++++++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Pin>`, found `&&mut F` @@ -791,7 +781,7 @@ LL | reuse Trait::* { Box::pin(&&mut self.0) } | +++++++++ + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Pin>`, found `&&mut F` @@ -807,7 +797,7 @@ LL | fn pin_rc(self: Pin>) -> i32 { 8 } | ^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Pin>`, found `&&mut F` @@ -823,7 +813,7 @@ LL | fn pin_arc(self: Pin>) -> i32 { 9 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ expected `Box>`, found `&&mut F` @@ -839,7 +829,7 @@ LL | fn box_box(self: Box>) -> i32 { 10 } | ^^^^^^^ ---- error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:178:22 + --> $DIR/self-coercion-errors.rs:179:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Arc<_>`, found `Box` @@ -860,7 +850,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:178:22 + --> $DIR/self-coercion-errors.rs:179:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Rc<_>`, found `Box` @@ -881,7 +871,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:178:22 + --> $DIR/self-coercion-errors.rs:179:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Box` @@ -902,7 +892,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:178:22 + --> $DIR/self-coercion-errors.rs:179:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Box` @@ -923,7 +913,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:178:22 + --> $DIR/self-coercion-errors.rs:179:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Box` @@ -944,7 +934,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:178:22 + --> $DIR/self-coercion-errors.rs:179:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Box>`, found `Box` @@ -959,7 +949,7 @@ note: there is a field `0` on `Box>` with type `std::ptr::Unique | = note: if this field wasn't private, it would be accessible | - ::: $DIR/self-coercion-errors.rs:175:8 + ::: $DIR/self-coercion-errors.rs:176:8 | LL | struct X6(Box); | -- ------ this is the field that was accessed @@ -979,7 +969,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Arc<_>`, found `Box>>` @@ -999,7 +989,7 @@ LL | reuse Trait::* { *self.0 } | + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Rc<_>`, found `Box>>` @@ -1020,7 +1010,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Box>>` @@ -1041,7 +1031,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Box>>` @@ -1062,7 +1052,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Box>>` @@ -1083,7 +1073,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Box>`, found `Box>>` @@ -1098,7 +1088,7 @@ note: there is a field `0` on `Box>` with type `std::ptr::Unique | = note: if this field wasn't private, it would be accessible | - ::: $DIR/self-coercion-errors.rs:187:8 + ::: $DIR/self-coercion-errors.rs:188:8 | LL | struct X7(Box>>); | -- ---------------- this is the field that was accessed @@ -1118,7 +1108,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Box<_>`, found `Pin>` @@ -1133,7 +1123,7 @@ note: there is a field `0` on `Box` with type `std::ptr::Unique` but it | = note: if this field wasn't private, it would be accessible | - ::: $DIR/self-coercion-errors.rs:202:8 + ::: $DIR/self-coercion-errors.rs:203:8 | LL | struct X8(Pin>); | -- ----------- this is the field that was accessed @@ -1153,7 +1143,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Arc<_>`, found `Pin>` @@ -1174,7 +1164,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Rc<_>`, found `Pin>` @@ -1195,7 +1185,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Pin>` @@ -1216,7 +1206,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `Pin>` @@ -1237,7 +1227,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Box>`, found `Pin>` @@ -1252,7 +1242,7 @@ note: there is a field `0` on `Box>` with type `std::ptr::Unique | = note: if this field wasn't private, it would be accessible | - ::: $DIR/self-coercion-errors.rs:202:8 + ::: $DIR/self-coercion-errors.rs:203:8 | LL | struct X8(Pin>); | -- ----------- this is the field that was accessed @@ -1272,7 +1262,7 @@ LL + reuse Trait::* { self } | error[E0277]: the trait bound `OtherStruct: Trait` is not satisfied - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ unsatisfied trait bound @@ -1280,7 +1270,7 @@ LL | reuse Trait::* { self.0 } | required by a bound introduced by this call | help: the trait `Trait` is not implemented for `OtherStruct` - --> $DIR/self-coercion-errors.rs:217:1 + --> $DIR/self-coercion-errors.rs:218:1 | LL | struct OtherStruct; | ^^^^^^^^^^^^^^^^^^ @@ -1291,7 +1281,7 @@ LL | impl Trait for F {} | ^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `&mut _`, found `OtherStruct` @@ -1311,7 +1301,7 @@ LL | reuse Trait::* { &mut self.0 } | ++++ error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `&_`, found `OtherStruct` @@ -1331,7 +1321,7 @@ LL | reuse Trait::* { &self.0 } | + error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Box<_>`, found `OtherStruct` @@ -1346,7 +1336,7 @@ note: there is a field `0` on `Box` with type `std::ptr::Unique` but it | = note: if this field wasn't private, it would be accessible | - ::: $DIR/self-coercion-errors.rs:218:8 + ::: $DIR/self-coercion-errors.rs:219:8 | LL | struct X9(OtherStruct); | -- ----------- this is the field that was accessed @@ -1366,7 +1356,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Arc<_>`, found `OtherStruct` @@ -1387,7 +1377,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Rc<_>`, found `OtherStruct` @@ -1408,7 +1398,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `OtherStruct` @@ -1429,7 +1419,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `OtherStruct` @@ -1450,7 +1440,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Pin>`, found `OtherStruct` @@ -1471,7 +1461,7 @@ LL + reuse Trait::* { self } | error[E0308]: mismatched types - --> $DIR/self-coercion-errors.rs:221:22 + --> $DIR/self-coercion-errors.rs:222:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ expected `Box>`, found `OtherStruct` @@ -1486,7 +1476,7 @@ note: there is a field `0` on `Box>` with type `std::ptr::Unique | = note: if this field wasn't private, it would be accessible | - ::: $DIR/self-coercion-errors.rs:218:8 + ::: $DIR/self-coercion-errors.rs:219:8 | LL | struct X9(OtherStruct); | -- ----------- this is the field that was accessed @@ -1505,8 +1495,19 @@ LL - reuse Trait::* { self.0 } LL + reuse Trait::* { self } | +error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable + --> $DIR/self-coercion-errors.rs:61:9 + | +LL | x + | ^ cannot borrow as mutable + | +help: consider changing this to be mutable + | +LL | let mut x = foo(); + | +++ + error[E0507]: cannot move out of a mutable reference - --> $DIR/self-coercion-errors.rs:73:9 + --> $DIR/self-coercion-errors.rs:74:9 | LL | reuse Trait::{by_value, by_mut_ref, by_ref} { | -------- value moved due to this method call @@ -1529,7 +1530,7 @@ LL | &mut x | ------ you could clone this value error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/self-coercion-errors.rs:73:9 + --> $DIR/self-coercion-errors.rs:74:9 | LL | &mut x | ^^^^^^ cannot borrow as mutable @@ -1540,7 +1541,7 @@ LL | let mut x = foo(); | +++ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/self-coercion-errors.rs:73:9 + --> $DIR/self-coercion-errors.rs:74:9 | LL | &mut x | ^^^^^^ cannot borrow as mutable @@ -1552,7 +1553,7 @@ LL | let mut x = foo(); | +++ error[E0596]: cannot borrow `x` as mutable, as it is not declared as mutable - --> $DIR/self-coercion-errors.rs:73:9 + --> $DIR/self-coercion-errors.rs:74:9 | LL | &mut x | ^^^^^^ cannot borrow as mutable @@ -1564,7 +1565,7 @@ LL | let mut x = foo(); | +++ error[E0507]: cannot move out of a mutable reference - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | - ^^^^^^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1586,7 +1587,7 @@ LL | reuse Trait::* { &mut self.0 } | ----------- you could clone this value error[E0596]: cannot borrow `self.0` as mutable, as `self` is not declared as mutable - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | ^^^^^^^^^^^ cannot borrow as mutable @@ -1597,7 +1598,7 @@ LL | reuse Trait::mut * { &mut self.0 } | +++ error[E0596]: cannot borrow `self.0` as mutable, as it is behind a `&` reference - --> $DIR/self-coercion-errors.rs:84:22 + --> $DIR/self-coercion-errors.rs:85:22 | LL | reuse Trait::* { &mut self.0 } | ^^^^^^^^^^^ `self` is a `&` reference, so it cannot be borrowed as mutable @@ -1609,7 +1610,7 @@ LL + reuse Trait::&mut self { &mut self.0 } | error[E0507]: cannot move out of a shared reference - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | - ^^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1631,13 +1632,13 @@ LL | reuse Trait::* { &self.0 } | ------- you could clone this value error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/self-coercion-errors.rs:100:22 + --> $DIR/self-coercion-errors.rs:101:22 | LL | reuse Trait::* { &self.0 } | ^^^^^^^ cannot borrow as mutable error[E0507]: cannot move out of a shared reference - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | - ^^^^^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1659,13 +1660,13 @@ LL | reuse Trait::* { &&&&self.0 } | ---------- you could clone this value error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/self-coercion-errors.rs:115:22 + --> $DIR/self-coercion-errors.rs:116:22 | LL | reuse Trait::* { &&&&self.0 } | ^^^^^^^^^^ cannot borrow as mutable error[E0507]: cannot move out of a shared reference - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | - ^^^^^^^^^^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1687,13 +1688,13 @@ LL | reuse Trait::* { self.0.as_ref() } | --------------- you could clone this value error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/self-coercion-errors.rs:130:22 + --> $DIR/self-coercion-errors.rs:131:22 | LL | reuse Trait::* { self.0.as_ref() } | ^^^^^^^^^^^^^^^ cannot borrow as mutable error[E0507]: cannot move out of a mutable reference - --> $DIR/self-coercion-errors.rs:145:22 + --> $DIR/self-coercion-errors.rs:146:22 | LL | reuse Trait::* { &mut &mut &mut self.0 } | - ^^^^^^^^^^^^^^^^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1715,7 +1716,7 @@ LL | reuse Trait::* { &mut &mut &mut self.0 } | --------------------- you could clone this value error[E0596]: cannot borrow `self.0` as mutable, as `self` is not declared as mutable - --> $DIR/self-coercion-errors.rs:145:32 + --> $DIR/self-coercion-errors.rs:146:32 | LL | reuse Trait::* { &mut &mut &mut self.0 } | ^^^^^^^^^^^ cannot borrow as mutable @@ -1726,7 +1727,7 @@ LL | reuse Trait::mut * { &mut &mut &mut self.0 } | +++ error[E0596]: cannot borrow `self.0` as mutable, as it is behind a `&` reference - --> $DIR/self-coercion-errors.rs:145:32 + --> $DIR/self-coercion-errors.rs:146:32 | LL | reuse Trait::* { &mut &mut &mut self.0 } | ^^^^^^^^^^^ `self` is a `&` reference, so it cannot be borrowed as mutable @@ -1738,7 +1739,7 @@ LL + reuse Trait::&mut self { &mut &mut &mut self.0 } | error[E0507]: cannot move out of a shared reference - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | - ^^^^^^^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1760,7 +1761,7 @@ LL | reuse Trait::* { &&mut self.0 } | ------------ you could clone this value error[E0596]: cannot borrow `self.0` as mutable, as `self` is not declared as mutable - --> $DIR/self-coercion-errors.rs:161:23 + --> $DIR/self-coercion-errors.rs:162:23 | LL | reuse Trait::* { &&mut self.0 } | ^^^^^^^^^^^ cannot borrow as mutable @@ -1771,13 +1772,13 @@ LL | reuse Trait::mut * { &&mut self.0 } | +++ error[E0596]: cannot borrow data in a `&` reference as mutable - --> $DIR/self-coercion-errors.rs:161:22 + --> $DIR/self-coercion-errors.rs:162:22 | LL | reuse Trait::* { &&mut self.0 } | ^^^^^^^^^^^^ cannot borrow as mutable error[E0596]: cannot borrow `self.0` as mutable, as it is behind a `&` reference - --> $DIR/self-coercion-errors.rs:161:23 + --> $DIR/self-coercion-errors.rs:162:23 | LL | reuse Trait::* { &&mut self.0 } | ^^^^^^^^^^^ `self` is a `&` reference, so it cannot be borrowed as mutable @@ -1789,7 +1790,7 @@ LL + reuse Trait::&mut self { &&mut self.0 } | error[E0507]: cannot move out of an `Arc` - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1811,7 +1812,7 @@ LL | reuse Trait::* { self.0 } | ------ you could clone this value error[E0596]: cannot borrow data in an `Arc` as mutable - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | ^^^^^^ cannot borrow as mutable @@ -1819,7 +1820,7 @@ LL | reuse Trait::* { self.0 } = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Arc>` error[E0507]: cannot move out of an `Arc` - --> $DIR/self-coercion-errors.rs:190:22 + --> $DIR/self-coercion-errors.rs:191:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ move occurs because value has type `Box`, which does not implement the `Copy` trait @@ -1850,7 +1851,7 @@ LL | struct F; | error[E0507]: cannot move out of dereference of `Pin>` - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ move occurs because value has type `F`, which does not implement the `Copy` trait @@ -1872,7 +1873,7 @@ LL | reuse Trait::* { self.0 } | ------ you could clone this value error[E0596]: cannot borrow data in dereference of `Pin>` as mutable - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | ^^^^^^ cannot borrow as mutable @@ -1880,7 +1881,7 @@ LL | reuse Trait::* { self.0 } = help: trait `DerefMut` is required to modify through a dereference, but it is not implemented for `Pin>` error[E0507]: cannot move out of dereference of `Pin>` - --> $DIR/self-coercion-errors.rs:205:22 + --> $DIR/self-coercion-errors.rs:206:22 | LL | reuse Trait::* { self.0 } | - ^^^^^^ move occurs because value has type `Pin>`, which does not implement the `Copy` trait @@ -1910,7 +1911,7 @@ LL + #[derive(Clone)] LL | struct F; | -error: aborting due to 99 previous errors +error: aborting due to 100 previous errors Some errors have detailed explanations: E0277, E0308, E0507, E0596. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/self-coercion-static-free.stderr b/tests/ui/delegation/self-coercion-static-free.stderr index 5f78272815aa5..d77dcb1fbda58 100644 --- a/tests/ui/delegation/self-coercion-static-free.stderr +++ b/tests/ui/delegation/self-coercion-static-free.stderr @@ -1,9 +1,17 @@ error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:24:9 | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | -------------- arguments to this function are incorrect +LL | let _ = self; LL | S::static_self() | ^^^^^^^^^^^^^^^^ expected `&mut F`, found `F` | +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:11:8 + | +LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } + | ^^^^^^^^^^^^^^ ------------ help: consider mutably borrowing here | LL | &mut S::static_self() @@ -12,9 +20,17 @@ LL | &mut S::static_self() error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:24:9 | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ---------- arguments to this function are incorrect +LL | let _ = self; LL | S::static_self() | ^^^^^^^^^^^^^^^^ expected `&F`, found `F` | +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:12:8 + | +LL | fn static_ref(_: &Self) -> i32 { 3 } + | ^^^^^^^^^^ -------- help: consider borrowing here | LL | &S::static_self() @@ -23,9 +39,17 @@ LL | &S::static_self() error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:35:9 | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | -------------- arguments to this function are incorrect +LL | let _ = self; LL | S1::static_self() | ^^^^^^^^^^^^^^^^^ expected `&mut F`, found `F` | +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:11:8 + | +LL | fn static_mut_ref(_: &mut Self) -> i32 { 2 } + | ^^^^^^^^^^^^^^ ------------ help: consider mutably borrowing here | LL | &mut S1::static_self() @@ -34,9 +58,17 @@ LL | &mut S1::static_self() error[E0308]: mismatched types --> $DIR/self-coercion-static-free.rs:35:9 | +LL | reuse ::{static_value, static_mut_ref, static_ref} { + | ---------- arguments to this function are incorrect +LL | let _ = self; LL | S1::static_self() | ^^^^^^^^^^^^^^^^^ expected `&F`, found `F` | +note: associated function defined here + --> $DIR/self-coercion-static-free.rs:12:8 + | +LL | fn static_ref(_: &Self) -> i32 { 3 } + | ^^^^^^^^^^ -------- help: consider borrowing here | LL | &S1::static_self() diff --git a/tests/ui/delegation/target-expr-pass.rs b/tests/ui/delegation/target-expr-pass.rs index 887a1ee5953dd..e9d4affd9dbb7 100644 --- a/tests/ui/delegation/target-expr-pass.rs +++ b/tests/ui/delegation/target-expr-pass.rs @@ -13,8 +13,10 @@ reuse to_reuse::foo {{ x + self }} -trait Trait { //~ WARN trait `Trait` is never used - fn bar(&self, x: i32) -> i32 { x } +trait Trait: Sized { //~ WARN trait `Trait` is never used + fn by_value(self, x: i32) -> i32 { x } + fn by_ref(&self, x: i32) -> i32 { x } + fn by_mut_ref(&mut self, x: i32) -> i32 { x } } struct F; //~ WARN struct `F` is never constructed @@ -22,12 +24,12 @@ impl Trait for F {} struct S(F); //~ WARN struct `S` is never constructed impl Trait for S { - reuse ::bar { + reuse ::* { #[allow(unused_imports)] use self::to_reuse::{foo, inner::{self}}; let x = foo(12); assert_eq!(x, 12); - &self.0 + self.0 } } diff --git a/tests/ui/delegation/target-expr-pass.stderr b/tests/ui/delegation/target-expr-pass.stderr index d7ca17c9ef86d..0daa457f45f67 100644 --- a/tests/ui/delegation/target-expr-pass.stderr +++ b/tests/ui/delegation/target-expr-pass.stderr @@ -1,19 +1,19 @@ warning: trait `Trait` is never used --> $DIR/target-expr-pass.rs:16:7 | -LL | trait Trait { +LL | trait Trait: Sized { | ^^^^^ | = note: `#[warn(dead_code)]` (part of `#[warn(unused)]`) on by default warning: struct `F` is never constructed - --> $DIR/target-expr-pass.rs:20:8 + --> $DIR/target-expr-pass.rs:22:8 | LL | struct F; | ^ warning: struct `S` is never constructed - --> $DIR/target-expr-pass.rs:23:8 + --> $DIR/target-expr-pass.rs:25:8 | LL | struct S(F); | ^ diff --git a/tests/ui/delegation/target-expr.rs b/tests/ui/delegation/target-expr.rs index 2355decd3d4f7..14232d194a740 100644 --- a/tests/ui/delegation/target-expr.rs +++ b/tests/ui/delegation/target-expr.rs @@ -15,8 +15,7 @@ fn foo(x: i32) -> i32 { x } fn bar(_: T) { reuse Trait::static_method { - //~^ ERROR mismatched types - //~| ERROR: delegation self type is not specified + //~^ ERROR: delegation self type is not specified let _ = T::Default(); //~^ ERROR can't use generic parameters from outer item } diff --git a/tests/ui/delegation/target-expr.stderr b/tests/ui/delegation/target-expr.stderr index 8965a1a060786..9126234a2c3cd 100644 --- a/tests/ui/delegation/target-expr.stderr +++ b/tests/ui/delegation/target-expr.stderr @@ -1,18 +1,18 @@ error[E0401]: can't use generic parameters from outer item - --> $DIR/target-expr.rs:20:17 + --> $DIR/target-expr.rs:19:17 | LL | fn bar(_: T) { | - type parameter from outer item LL | reuse Trait::static_method { | ------------- generic parameter used in this inner delegated function -... +LL | LL | let _ = T::Default(); | ^ use of generic parameter from outer item | = note: nested items are independent from their parent item for everything except for privacy and name resolution error[E0434]: can't capture dynamic environment in a fn item - --> $DIR/target-expr.rs:28:17 + --> $DIR/target-expr.rs:27:17 | LL | let x = y; | ^ @@ -20,7 +20,7 @@ LL | let x = y; = help: use the `|| { ... }` closure form instead error[E0424]: expected value, found module `self` - --> $DIR/target-expr.rs:35:5 + --> $DIR/target-expr.rs:34:5 | LL | fn main() { | ---- this function can't have a `self` parameter @@ -29,13 +29,13 @@ LL | self.0; | ^^^^ `self` value is a keyword only available in methods with a `self` parameter error[E0425]: cannot find value `x` in this scope - --> $DIR/target-expr.rs:37:13 + --> $DIR/target-expr.rs:36:13 | LL | let z = x; | ^ | help: the binding `x` is available in a different scope in the same function - --> $DIR/target-expr.rs:28:13 + --> $DIR/target-expr.rs:27:13 | LL | let x = y; | ^ @@ -48,19 +48,7 @@ LL | reuse Trait::static_method { | = help: consider explicitly specifying self type: `reuse ::function` -error[E0308]: mismatched types - --> $DIR/target-expr.rs:17:32 - | -LL | reuse Trait::static_method { - | ________________________________^ -LL | | -LL | | -LL | | let _ = T::Default(); -LL | | -LL | | } - | |_____^ expected `i32`, found `()` - -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors -Some errors have detailed explanations: E0308, E0401, E0424, E0425, E0434. -For more information about an error, try `rustc --explain E0308`. +Some errors have detailed explanations: E0401, E0424, E0425, E0434. +For more information about an error, try `rustc --explain E0401`. diff --git a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr index 517a01dac6f0e..d2aab756c6d6e 100644 --- a/tests/ui/delegation/zero-args-delegations-ice-154332.stderr +++ b/tests/ui/delegation/zero-args-delegations-ice-154332.stderr @@ -25,7 +25,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/zero-args-delegations-ice-154332.rs:25:21 | LL | reuse to_reuse::zero_args { self } - | ^^^^^^^^^ ---- unexpected argument + | ^^^^^^^^^ -------- unexpected argument | note: function defined here --> $DIR/zero-args-delegations-ice-154332.rs:20:16 @@ -35,7 +35,7 @@ LL | pub fn zero_args() -> i32 { help: remove the extra argument | LL - reuse to_reuse::zero_args { self } -LL + reuse to_reuse::zero_argself } +LL + reuse to_reuse::zero_arg{ self } | error: aborting due to 2 previous errors