From 70af5cf2a3363ee8f37a611a398aec52f567910e Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 7 Apr 2026 15:45:43 +0000 Subject: [PATCH 01/14] Move deref-patterns tests to pattern sub directory --- src/tools/tidy/src/issues.txt | 2 - tests/ui/README.md | 8 ---- tests/ui/deref-patterns/issue-71676-2.rs | 42 ------------------- tests/ui/deref-patterns/issue-71676-2.stderr | 18 -------- .../deref-patterns/deref-non-pointer.rs | 0 .../deref-patterns/deref-non-pointer.stderr | 0 ...deref-pointer-cast-mutability-71676.fixed} | 0 .../deref-pointer-cast-mutability-71676.rs} | 0 ...eref-pointer-cast-mutability-71676.stderr} | 0 9 files changed, 70 deletions(-) delete mode 100644 tests/ui/deref-patterns/issue-71676-2.rs delete mode 100644 tests/ui/deref-patterns/issue-71676-2.stderr rename tests/ui/{ => pattern}/deref-patterns/deref-non-pointer.rs (100%) rename tests/ui/{ => pattern}/deref-patterns/deref-non-pointer.stderr (100%) rename tests/ui/{deref-patterns/issue-71676-1.fixed => pattern/deref-patterns/deref-pointer-cast-mutability-71676.fixed} (100%) rename tests/ui/{deref-patterns/issue-71676-1.rs => pattern/deref-patterns/deref-pointer-cast-mutability-71676.rs} (100%) rename tests/ui/{deref-patterns/issue-71676-1.stderr => pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr} (100%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 3b23fe5d80826..74b2a22451ae0 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -834,8 +834,6 @@ ui/cycle-trait/issue-12511.rs ui/debuginfo/issue-105386-debuginfo-ub.rs ui/deprecation/issue-66340-deprecated-attr-non-meta-grammar.rs ui/deprecation/issue-84637-deprecated-associated-function.rs -ui/deref-patterns/issue-71676-1.rs -ui/deref-patterns/issue-71676-2.rs ui/derived-errors/issue-30580.rs ui/derived-errors/issue-31997-1.rs ui/derived-errors/issue-31997.rs diff --git a/tests/ui/README.md b/tests/ui/README.md index a9e7f022c2b60..afe4ad97aef26 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -398,14 +398,6 @@ Tests for `#[deprecated]` attribute and `deprecated_in_future` internal lint. Tests for `Deref` and `DerefMut` traits. -## `tests/ui/deref-patterns`: `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]` - -Tests for `#![feature(deref_patterns)]` and `#![feature(string_deref_patterns)]`. See [Deref patterns | The Unstable book](https://doc.rust-lang.org/nightly/unstable-book/language-features/deref-patterns.html). - -**FIXME**: May have some overlap with `tests/ui/pattern/deref-patterns`. - -See [`std::ops::Deref`](https://doc.rust-lang.org/std/ops/trait.Deref.html) and [`std::ops::DerefMut`](https://doc.rust-lang.org/std/ops/trait.DerefMut.html) - ## `tests/ui/derived-errors/`: Derived Error Messages Tests for quality of diagnostics involving suppression of cascading errors in some cases to avoid overwhelming the user. diff --git a/tests/ui/deref-patterns/issue-71676-2.rs b/tests/ui/deref-patterns/issue-71676-2.rs deleted file mode 100644 index f3183899dc523..0000000000000 --- a/tests/ui/deref-patterns/issue-71676-2.rs +++ /dev/null @@ -1,42 +0,0 @@ -use std::ops::Deref; -use std::ops::DerefMut; -struct Bar(u8); -struct Foo(Bar); -struct Emm(Foo); -impl Deref for Bar{ - type Target = u8; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl Deref for Foo { - type Target = Bar; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl Deref for Emm { - type Target = Foo; - fn deref(&self) -> &Self::Target { - &self.0 - } -} -impl DerefMut for Bar{ - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl DerefMut for Foo { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -impl DerefMut for Emm { - fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.0 - } -} -fn main() { - let a = Emm(Foo(Bar(0))); - let _: *mut u8 = &a; //~ ERROR mismatched types -} diff --git a/tests/ui/deref-patterns/issue-71676-2.stderr b/tests/ui/deref-patterns/issue-71676-2.stderr deleted file mode 100644 index 6ed318c8768b0..0000000000000 --- a/tests/ui/deref-patterns/issue-71676-2.stderr +++ /dev/null @@ -1,18 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-71676-2.rs:41:22 - | -LL | let _: *mut u8 = &a; - | ------- ^^ types differ in mutability - | | - | expected due to this - | - = note: expected raw pointer `*mut u8` - found reference `&Emm` -help: consider dereferencing - | -LL | let _: *mut u8 = &mut ***a; - | +++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/deref-patterns/deref-non-pointer.rs b/tests/ui/pattern/deref-patterns/deref-non-pointer.rs similarity index 100% rename from tests/ui/deref-patterns/deref-non-pointer.rs rename to tests/ui/pattern/deref-patterns/deref-non-pointer.rs diff --git a/tests/ui/deref-patterns/deref-non-pointer.stderr b/tests/ui/pattern/deref-patterns/deref-non-pointer.stderr similarity index 100% rename from tests/ui/deref-patterns/deref-non-pointer.stderr rename to tests/ui/pattern/deref-patterns/deref-non-pointer.stderr diff --git a/tests/ui/deref-patterns/issue-71676-1.fixed b/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.fixed similarity index 100% rename from tests/ui/deref-patterns/issue-71676-1.fixed rename to tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.fixed diff --git a/tests/ui/deref-patterns/issue-71676-1.rs b/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.rs similarity index 100% rename from tests/ui/deref-patterns/issue-71676-1.rs rename to tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.rs diff --git a/tests/ui/deref-patterns/issue-71676-1.stderr b/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr similarity index 100% rename from tests/ui/deref-patterns/issue-71676-1.stderr rename to tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr From df2fe313d44bcc008331a0b01662cfdcaa0ecc90 Mon Sep 17 00:00:00 2001 From: Redddy Date: Tue, 7 Apr 2026 15:53:03 +0000 Subject: [PATCH 02/14] Fix format and bless test --- tests/ui/pattern/deref-patterns/deref-non-pointer.rs | 6 +++--- tests/ui/pattern/deref-patterns/deref-non-pointer.stderr | 6 +++--- .../deref-pointer-cast-mutability-71676.stderr | 8 ++++---- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/tests/ui/pattern/deref-patterns/deref-non-pointer.rs b/tests/ui/pattern/deref-patterns/deref-non-pointer.rs index 82ab355e697b2..af9802481a6d0 100644 --- a/tests/ui/pattern/deref-patterns/deref-non-pointer.rs +++ b/tests/ui/pattern/deref-patterns/deref-non-pointer.rs @@ -1,5 +1,5 @@ fn main() { - match *1 { //~ ERROR: cannot be dereferenced - _ => { panic!(); } - } + match *1 { //~ ERROR: cannot be dereferenced + _ => {} + } } diff --git a/tests/ui/pattern/deref-patterns/deref-non-pointer.stderr b/tests/ui/pattern/deref-patterns/deref-non-pointer.stderr index 3ee354819e5d6..eae6c56a5e793 100644 --- a/tests/ui/pattern/deref-patterns/deref-non-pointer.stderr +++ b/tests/ui/pattern/deref-patterns/deref-non-pointer.stderr @@ -1,8 +1,8 @@ error[E0614]: type `{integer}` cannot be dereferenced - --> $DIR/deref-non-pointer.rs:2:9 + --> $DIR/deref-non-pointer.rs:2:11 | -LL | match *1 { - | ^^ can't be dereferenced +LL | match *1 { + | ^^ can't be dereferenced error: aborting due to 1 previous error diff --git a/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr b/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr index 348a2c12ec491..90675d1660f26 100644 --- a/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr +++ b/tests/ui/pattern/deref-patterns/deref-pointer-cast-mutability-71676.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-71676-1.rs:43:24 + --> $DIR/deref-pointer-cast-mutability-71676.rs:43:24 | LL | let _: *const u8 = &a; | --------- ^^ expected `*const u8`, found `&Emm` @@ -14,7 +14,7 @@ LL | let _: *const u8 = &***a; | +++ error[E0308]: mismatched types - --> $DIR/issue-71676-1.rs:46:22 + --> $DIR/deref-pointer-cast-mutability-71676.rs:46:22 | LL | let _: *mut u8 = &a; | ------- ^^ types differ in mutability @@ -29,7 +29,7 @@ LL | let _: *mut u8 = &mut ***a; | +++++++ error[E0308]: mismatched types - --> $DIR/issue-71676-1.rs:49:24 + --> $DIR/deref-pointer-cast-mutability-71676.rs:49:24 | LL | let _: *const u8 = &mut a; | --------- ^^^^^^ expected `*const u8`, found `&mut Emm` @@ -45,7 +45,7 @@ LL + let _: *const u8 = &***a; | error[E0308]: mismatched types - --> $DIR/issue-71676-1.rs:52:22 + --> $DIR/deref-pointer-cast-mutability-71676.rs:52:22 | LL | let _: *mut u8 = &mut a; | ------- ^^^^^^ expected `*mut u8`, found `&mut Emm` From d2e978ea74a4b635e8496e323a4cff8c206b3f08 Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 10 Apr 2026 03:38:21 +0000 Subject: [PATCH 03/14] Move unknown_lints tests into lint/unknown-lints dir --- src/tools/tidy/src/issues.txt | 2 -- tests/ui/README.md | 6 ------ .../allow-unknown-unstable-lint-command-line.rs | 0 .../allow-unknown-unstable-lint-inline.rs | 0 .../cli-unknown-force-warn.rs | 0 .../cli-unknown-force-warn.stderr | 0 .../deny-unstable-lint-command-line.rs | 1 - .../deny-unstable-lint-command-line.stderr | 0 .../unknown-lints}/deny-unstable-lint-inline.rs | 2 -- .../deny-unstable-lint-inline.stderr | 4 ++-- .../redundant-path-83477.rs} | 0 .../redundant-path-83477.stderr} | 8 ++++---- .../suggestions.rs} | 3 +++ .../suggestions.stderr} | 14 ++++++++++---- .../unknown-lints-in-cfg-attr-97094.rs} | 0 .../unknown-lints-in-cfg-attr-97094.stderr} | 16 ++++++++-------- .../warn-unknown-unstable-lint-command-line.rs | 0 ...arn-unknown-unstable-lint-command-line.stderr | 0 .../warn-unknown-unstable-lint-inline.rs | 0 .../warn-unknown-unstable-lint-inline.stderr | 0 20 files changed, 27 insertions(+), 29 deletions(-) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/allow-unknown-unstable-lint-command-line.rs (100%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/allow-unknown-unstable-lint-inline.rs (100%) rename tests/ui/lint/{ => unknown-lints}/cli-unknown-force-warn.rs (100%) rename tests/ui/lint/{ => unknown-lints}/cli-unknown-force-warn.stderr (100%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/deny-unstable-lint-command-line.rs (93%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/deny-unstable-lint-command-line.stderr (100%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/deny-unstable-lint-inline.rs (87%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/deny-unstable-lint-inline.stderr (84%) rename tests/ui/lint/{issue-83477.rs => unknown-lints/redundant-path-83477.rs} (100%) rename tests/ui/lint/{issue-83477.stderr => unknown-lints/redundant-path-83477.stderr} (86%) rename tests/ui/lint/{not_found.rs => unknown-lints/suggestions.rs} (82%) rename tests/ui/lint/{not_found.stderr => unknown-lints/suggestions.stderr} (57%) rename tests/ui/lint/{issue-97094.rs => unknown-lints/unknown-lints-in-cfg-attr-97094.rs} (100%) rename tests/ui/lint/{issue-97094.stderr => unknown-lints/unknown-lints-in-cfg-attr-97094.stderr} (76%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/warn-unknown-unstable-lint-command-line.rs (100%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/warn-unknown-unstable-lint-command-line.stderr (100%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/warn-unknown-unstable-lint-inline.rs (100%) rename tests/ui/{unknown-unstable-lints => lint/unknown-lints}/warn-unknown-unstable-lint-inline.stderr (100%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index 74b2a22451ae0..7e471a102d1d9 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1463,10 +1463,8 @@ ui/lint/issue-63364.rs ui/lint/issue-70819-dont-override-forbid-in-same-scope.rs ui/lint/issue-79744.rs ui/lint/issue-81218.rs -ui/lint/issue-83477.rs ui/lint/issue-87274-paren-parent.rs ui/lint/issue-90614-accept-allow-text-direction-codepoint-in-comment-lint.rs -ui/lint/issue-97094.rs ui/lint/issue-99387.rs ui/lint/let_underscore/issue-119696-err-on-fn.rs ui/lint/let_underscore/issue-119697-extra-let.rs diff --git a/tests/ui/README.md b/tests/ui/README.md index afe4ad97aef26..946f32bf0e9ac 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1492,12 +1492,6 @@ See [Uninhabited | Reference](https://doc.rust-lang.org/reference/glossary.html? See [Unions | Reference](https://doc.rust-lang.org/reference/items/unions.html). -## `tests/ui/unknown-unstable-lints/`: Attempting to refer to an unstable lint which does not exist - -Tests for trying to use non-existent unstable lints. - -**FIXME**: move this under `tests/ui/lints/`. - ## `tests/ui/unop/`: Unary operators `-`, `*` and `!` Tests the three unary operators for negating, dereferencing and inverting, across different contexts. diff --git a/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-command-line.rs b/tests/ui/lint/unknown-lints/allow-unknown-unstable-lint-command-line.rs similarity index 100% rename from tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-command-line.rs rename to tests/ui/lint/unknown-lints/allow-unknown-unstable-lint-command-line.rs diff --git a/tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-inline.rs b/tests/ui/lint/unknown-lints/allow-unknown-unstable-lint-inline.rs similarity index 100% rename from tests/ui/unknown-unstable-lints/allow-unknown-unstable-lint-inline.rs rename to tests/ui/lint/unknown-lints/allow-unknown-unstable-lint-inline.rs diff --git a/tests/ui/lint/cli-unknown-force-warn.rs b/tests/ui/lint/unknown-lints/cli-unknown-force-warn.rs similarity index 100% rename from tests/ui/lint/cli-unknown-force-warn.rs rename to tests/ui/lint/unknown-lints/cli-unknown-force-warn.rs diff --git a/tests/ui/lint/cli-unknown-force-warn.stderr b/tests/ui/lint/unknown-lints/cli-unknown-force-warn.stderr similarity index 100% rename from tests/ui/lint/cli-unknown-force-warn.stderr rename to tests/ui/lint/unknown-lints/cli-unknown-force-warn.stderr diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs b/tests/ui/lint/unknown-lints/deny-unstable-lint-command-line.rs similarity index 93% rename from tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs rename to tests/ui/lint/unknown-lints/deny-unstable-lint-command-line.rs index 6005bc96ad6d1..bad7b37b56c7d 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.rs +++ b/tests/ui/lint/unknown-lints/deny-unstable-lint-command-line.rs @@ -1,6 +1,5 @@ //~ ERROR unknown lint: `test_unstable_lint` //~^ NOTE the `test_unstable_lint` lint is unstable -//@ check-fail //@ compile-flags: -Dunknown_lints -Atest_unstable_lint //@ dont-require-annotations: NOTE diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/lint/unknown-lints/deny-unstable-lint-command-line.stderr similarity index 100% rename from tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr rename to tests/ui/lint/unknown-lints/deny-unstable-lint-command-line.stderr diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs b/tests/ui/lint/unknown-lints/deny-unstable-lint-inline.rs similarity index 87% rename from tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs rename to tests/ui/lint/unknown-lints/deny-unstable-lint-inline.rs index a13c92151ac9c..623e639e7a00d 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.rs +++ b/tests/ui/lint/unknown-lints/deny-unstable-lint-inline.rs @@ -1,5 +1,3 @@ -//@ check-fail - #![deny(unknown_lints)] #![allow(test_unstable_lint)] //~^ ERROR unknown lint: `test_unstable_lint` diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr b/tests/ui/lint/unknown-lints/deny-unstable-lint-inline.stderr similarity index 84% rename from tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr rename to tests/ui/lint/unknown-lints/deny-unstable-lint-inline.stderr index 4ff909453979a..4b04c97810f81 100644 --- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-inline.stderr +++ b/tests/ui/lint/unknown-lints/deny-unstable-lint-inline.stderr @@ -1,5 +1,5 @@ error: unknown lint: `test_unstable_lint` - --> $DIR/deny-unstable-lint-inline.rs:4:10 + --> $DIR/deny-unstable-lint-inline.rs:2:10 | LL | #![allow(test_unstable_lint)] | ^^^^^^^^^^^^^^^^^^ @@ -8,7 +8,7 @@ LL | #![allow(test_unstable_lint)] = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date note: the lint level is defined here - --> $DIR/deny-unstable-lint-inline.rs:3:9 + --> $DIR/deny-unstable-lint-inline.rs:1:9 | LL | #![deny(unknown_lints)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/lint/issue-83477.rs b/tests/ui/lint/unknown-lints/redundant-path-83477.rs similarity index 100% rename from tests/ui/lint/issue-83477.rs rename to tests/ui/lint/unknown-lints/redundant-path-83477.rs diff --git a/tests/ui/lint/issue-83477.stderr b/tests/ui/lint/unknown-lints/redundant-path-83477.stderr similarity index 86% rename from tests/ui/lint/issue-83477.stderr rename to tests/ui/lint/unknown-lints/redundant-path-83477.stderr index f824fc09e7240..8e25bd7136be8 100644 --- a/tests/ui/lint/issue-83477.stderr +++ b/tests/ui/lint/unknown-lints/redundant-path-83477.stderr @@ -1,5 +1,5 @@ warning: unknown lint: `rustc::foo::bar::default_hash_types` - --> $DIR/issue-83477.rs:5:9 + --> $DIR/redundant-path-83477.rs:5:9 | LL | #[allow(rustc::foo::bar::default_hash_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` @@ -7,20 +7,20 @@ LL | #[allow(rustc::foo::bar::default_hash_types)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `rustc::foo::default_hash_types` - --> $DIR/issue-83477.rs:9:9 + --> $DIR/redundant-path-83477.rs:9:9 | LL | #[allow(rustc::foo::default_hash_types)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: did you mean: `rustc::default_hash_types` warning: prefer `FxHashMap` over `HashMap`, it has better performance - --> $DIR/issue-83477.rs:14:13 + --> $DIR/redundant-path-83477.rs:14:13 | LL | let _ = std::collections::HashMap::::new(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary note: the lint level is defined here - --> $DIR/issue-83477.rs:3:9 + --> $DIR/redundant-path-83477.rs:3:9 | LL | #![warn(rustc::internal)] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/lint/not_found.rs b/tests/ui/lint/unknown-lints/suggestions.rs similarity index 82% rename from tests/ui/lint/not_found.rs rename to tests/ui/lint/unknown-lints/suggestions.rs index 8e79c6da15273..72e688f70f31a 100644 --- a/tests/ui/lint/not_found.rs +++ b/tests/ui/lint/unknown-lints/suggestions.rs @@ -16,6 +16,9 @@ //~^ WARNING unknown lint //~| HELP did you mean +#[deny(rust_2018_idiots)] //~ WARNING unknown lint + //~| HELP did you mean + fn main() { unimplemented!(); } diff --git a/tests/ui/lint/not_found.stderr b/tests/ui/lint/unknown-lints/suggestions.stderr similarity index 57% rename from tests/ui/lint/not_found.stderr rename to tests/ui/lint/unknown-lints/suggestions.stderr index ea118c73ce784..322d605753416 100644 --- a/tests/ui/lint/not_found.stderr +++ b/tests/ui/lint/unknown-lints/suggestions.stderr @@ -1,5 +1,5 @@ warning: unknown lint: `FOO_BAR` - --> $DIR/not_found.rs:6:9 + --> $DIR/suggestions.rs:6:9 | LL | #[allow(FOO_BAR)] | ^^^^^^^ @@ -7,16 +7,22 @@ LL | #[allow(FOO_BAR)] = note: `#[warn(unknown_lints)]` on by default warning: unknown lint: `DEAD_CODE` - --> $DIR/not_found.rs:10:8 + --> $DIR/suggestions.rs:10:8 | LL | #[warn(DEAD_CODE)] | ^^^^^^^^^ help: did you mean: `dead_code` warning: unknown lint: `Warnings` - --> $DIR/not_found.rs:15:8 + --> $DIR/suggestions.rs:15:8 | LL | #[deny(Warnings)] | ^^^^^^^^ help: did you mean (notice the capitalization): `warnings` -warning: 3 warnings emitted +warning: unknown lint: `rust_2018_idiots` + --> $DIR/suggestions.rs:19:8 + | +LL | #[deny(rust_2018_idiots)] + | ^^^^^^^^^^^^^^^^ help: did you mean: `rust_2018_idioms` + +warning: 4 warnings emitted diff --git a/tests/ui/lint/issue-97094.rs b/tests/ui/lint/unknown-lints/unknown-lints-in-cfg-attr-97094.rs similarity index 100% rename from tests/ui/lint/issue-97094.rs rename to tests/ui/lint/unknown-lints/unknown-lints-in-cfg-attr-97094.rs diff --git a/tests/ui/lint/issue-97094.stderr b/tests/ui/lint/unknown-lints/unknown-lints-in-cfg-attr-97094.stderr similarity index 76% rename from tests/ui/lint/issue-97094.stderr rename to tests/ui/lint/unknown-lints/unknown-lints-in-cfg-attr-97094.stderr index e12250aa7542e..3309fa2c443d8 100644 --- a/tests/ui/lint/issue-97094.stderr +++ b/tests/ui/lint/unknown-lints/unknown-lints-in-cfg-attr-97094.stderr @@ -1,18 +1,18 @@ error: unknown lint: `nonex_lint_top_level` - --> $DIR/issue-97094.rs:5:25 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:5:25 | LL | #![cfg_attr(true, allow(nonex_lint_top_level))] | ^^^^^^^^^^^^^^^^^^^^ | note: the lint level is defined here - --> $DIR/issue-97094.rs:1:9 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:1:9 | LL | #![deny(warnings)] | ^^^^^^^^ = note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]` error: lint `bare_trait_object` has been renamed to `bare_trait_objects` - --> $DIR/issue-97094.rs:7:25 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:7:25 | LL | #![cfg_attr(true, allow(bare_trait_object))] | ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects` @@ -20,31 +20,31 @@ LL | #![cfg_attr(true, allow(bare_trait_object))] = note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]` error: unknown lint: `nonex_lint_mod` - --> $DIR/issue-97094.rs:10:24 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:10:24 | LL | #[cfg_attr(true, allow(nonex_lint_mod))] | ^^^^^^^^^^^^^^ error: unknown lint: `nonex_lint_mod_inner` - --> $DIR/issue-97094.rs:13:29 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:13:29 | LL | #![cfg_attr(true, allow(nonex_lint_mod_inner))] | ^^^^^^^^^^^^^^^^^^^^ error: unknown lint: `nonex_lint_fn` - --> $DIR/issue-97094.rs:17:24 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:17:24 | LL | #[cfg_attr(true, allow(nonex_lint_fn))] | ^^^^^^^^^^^^^ error: unknown lint: `nonex_lint_in_macro` - --> $DIR/issue-97094.rs:28:28 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:28:28 | LL | #[cfg_attr(true, allow(nonex_lint_in_macro))] | ^^^^^^^^^^^^^^^^^^^ error: unknown lint: `nonex_lint_fn` - --> $DIR/issue-97094.rs:47:13 + --> $DIR/unknown-lints-in-cfg-attr-97094.rs:47:13 | LL | #[allow(nonex_lint_fn)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs b/tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-command-line.rs similarity index 100% rename from tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.rs rename to tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-command-line.rs diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-command-line.stderr similarity index 100% rename from tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr rename to tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-command-line.stderr diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs b/tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-inline.rs similarity index 100% rename from tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.rs rename to tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-inline.rs diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr b/tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-inline.stderr similarity index 100% rename from tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-inline.stderr rename to tests/ui/lint/unknown-lints/warn-unknown-unstable-lint-inline.stderr From e110275cce45886a386b5e2dd8e84aef7ab05a4a Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 10 Apr 2026 04:20:36 +0000 Subject: [PATCH 04/14] Clean up unknown-lints ui tests --- .../lint/lint-unknown-lint-cmdline-allow.rs | 4 --- .../ui/lint/lint-unknown-lint-cmdline-deny.rs | 16 --------- .../lint-unknown-lint-cmdline-deny.stderr | 35 ------------------- tests/ui/lint/lint-unknown-lint-cmdline.rs | 17 --------- .../ui/lint/lint-unknown-lint-cmdline.stderr | 35 ------------------- tests/ui/lint/lint-unknown-lint.rs | 13 ------- tests/ui/lint/lint-unknown-lint.stderr | 26 -------------- tests/ui/lint/unknown-lints-at-crate-level.rs | 7 ---- 8 files changed, 153 deletions(-) delete mode 100644 tests/ui/lint/lint-unknown-lint-cmdline-allow.rs delete mode 100644 tests/ui/lint/lint-unknown-lint-cmdline-deny.rs delete mode 100644 tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr delete mode 100644 tests/ui/lint/lint-unknown-lint-cmdline.rs delete mode 100644 tests/ui/lint/lint-unknown-lint-cmdline.stderr delete mode 100644 tests/ui/lint/lint-unknown-lint.rs delete mode 100644 tests/ui/lint/lint-unknown-lint.stderr delete mode 100644 tests/ui/lint/unknown-lints-at-crate-level.rs diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-allow.rs b/tests/ui/lint/lint-unknown-lint-cmdline-allow.rs deleted file mode 100644 index 68c5e3b1a3a08..0000000000000 --- a/tests/ui/lint/lint-unknown-lint-cmdline-allow.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ check-pass -//@ compile-flags:-A unknown-lints -D bogus -D dead_cod - -fn main() { } diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs b/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs deleted file mode 100644 index ac001e1b6a04d..0000000000000 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ compile-flags:-D unknown-lints -D bogus -D dead_cod -//@ dont-require-annotations: HELP -//@ dont-require-annotations: NOTE - -fn main() { } - -//~? ERROR unknown lint: `bogus` -//~? ERROR unknown lint: `dead_cod` -//~? ERROR unknown lint: `bogus` -//~? ERROR unknown lint: `dead_cod` -//~? ERROR unknown lint: `bogus` -//~? ERROR unknown lint: `dead_cod` -//~? NOTE requested on the command line with `-D bogus` -//~? NOTE requested on the command line with `-D dead_cod` -//~? NOTE requested on the command line with `-D unknown-lints` -//~? HELP did you mean: `dead_code` diff --git a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr b/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr deleted file mode 100644 index f12ce03ddfcef..0000000000000 --- a/tests/ui/lint/lint-unknown-lint-cmdline-deny.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: requested on the command line with `-D unknown-lints` - -error[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - -error[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 6 previous errors - -For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.rs b/tests/ui/lint/lint-unknown-lint-cmdline.rs deleted file mode 100644 index 7eb8c1f73142f..0000000000000 --- a/tests/ui/lint/lint-unknown-lint-cmdline.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ check-pass -//@ compile-flags:-D bogus -D dead_cod -//@ dont-require-annotations: HELP -//@ dont-require-annotations: NOTE - -fn main() { } - -//~? WARN unknown lint: `bogus` -//~? WARN unknown lint: `dead_cod` -//~? WARN unknown lint: `bogus` -//~? WARN unknown lint: `dead_cod` -//~? WARN unknown lint: `bogus` -//~? WARN unknown lint: `dead_cod` -//~? NOTE requested on the command line with `-D bogus` -//~? NOTE `#[warn(unknown_lints)]` on by default -//~? NOTE requested on the command line with `-D dead_cod` -//~? HELP did you mean: `dead_code` diff --git a/tests/ui/lint/lint-unknown-lint-cmdline.stderr b/tests/ui/lint/lint-unknown-lint-cmdline.stderr deleted file mode 100644 index f452fc9eb943c..0000000000000 --- a/tests/ui/lint/lint-unknown-lint-cmdline.stderr +++ /dev/null @@ -1,35 +0,0 @@ -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: `#[warn(unknown_lints)]` on by default - -warning[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning[E0602]: unknown lint: `bogus` - | - = note: requested on the command line with `-D bogus` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning[E0602]: unknown lint: `dead_cod` - | - = help: did you mean: `dead_code` - = note: requested on the command line with `-D dead_cod` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -warning: 6 warnings emitted - -For more information about this error, try `rustc --explain E0602`. diff --git a/tests/ui/lint/lint-unknown-lint.rs b/tests/ui/lint/lint-unknown-lint.rs deleted file mode 100644 index 2d842d5142097..0000000000000 --- a/tests/ui/lint/lint-unknown-lint.rs +++ /dev/null @@ -1,13 +0,0 @@ -#![deny(unknown_lints)] - -#![allow(not_a_real_lint)] //~ ERROR unknown lint - -#![deny(dead_cod)] //~ ERROR unknown lint - //~| HELP did you mean - //~| SUGGESTION dead_code - -#![deny(rust_2018_idiots)] //~ ERROR unknown lint - //~| HELP did you mean - //~| SUGGESTION rust_2018_idioms - -fn main() {} diff --git a/tests/ui/lint/lint-unknown-lint.stderr b/tests/ui/lint/lint-unknown-lint.stderr deleted file mode 100644 index 0cb6b49578cf3..0000000000000 --- a/tests/ui/lint/lint-unknown-lint.stderr +++ /dev/null @@ -1,26 +0,0 @@ -error: unknown lint: `not_a_real_lint` - --> $DIR/lint-unknown-lint.rs:3:10 - | -LL | #![allow(not_a_real_lint)] - | ^^^^^^^^^^^^^^^ - | -note: the lint level is defined here - --> $DIR/lint-unknown-lint.rs:1:9 - | -LL | #![deny(unknown_lints)] - | ^^^^^^^^^^^^^ - -error: unknown lint: `dead_cod` - --> $DIR/lint-unknown-lint.rs:5:9 - | -LL | #![deny(dead_cod)] - | ^^^^^^^^ help: did you mean: `dead_code` - -error: unknown lint: `rust_2018_idiots` - --> $DIR/lint-unknown-lint.rs:9:9 - | -LL | #![deny(rust_2018_idiots)] - | ^^^^^^^^^^^^^^^^ help: did you mean: `rust_2018_idioms` - -error: aborting due to 3 previous errors - diff --git a/tests/ui/lint/unknown-lints-at-crate-level.rs b/tests/ui/lint/unknown-lints-at-crate-level.rs deleted file mode 100644 index c8cf65ce93a9a..0000000000000 --- a/tests/ui/lint/unknown-lints-at-crate-level.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ run-pass -//@ compile-flags: -D warnings -D unknown-lints - -#![allow(unknown_lints)] -#![allow(random_lint_name)] - -fn main() {} From 7c23ee6fcaf9357757fb087ec705ddd17de7550d Mon Sep 17 00:00:00 2001 From: Redddy Date: Fri, 10 Apr 2026 05:05:59 +0000 Subject: [PATCH 05/14] Move reserved tests to keyword --- tests/ui/README.md | 8 -------- tests/ui/{reserved => keyword}/meta-is-not-reserved.rs | 0 .../ui/{reserved => keyword}/meta-is-not-reserved.stderr | 0 tests/ui/{reserved => keyword}/reserved-attr-on-macro.rs | 0 .../{reserved => keyword}/reserved-attr-on-macro.stderr | 0 tests/ui/{reserved => keyword}/reserved-become.rs | 0 tests/ui/{reserved => keyword}/reserved-become.stderr | 0 7 files changed, 8 deletions(-) rename tests/ui/{reserved => keyword}/meta-is-not-reserved.rs (100%) rename tests/ui/{reserved => keyword}/meta-is-not-reserved.stderr (100%) rename tests/ui/{reserved => keyword}/reserved-attr-on-macro.rs (100%) rename tests/ui/{reserved => keyword}/reserved-attr-on-macro.stderr (100%) rename tests/ui/{reserved => keyword}/reserved-become.rs (100%) rename tests/ui/{reserved => keyword}/reserved-become.stderr (100%) diff --git a/tests/ui/README.md b/tests/ui/README.md index 946f32bf0e9ac..1f49b2d6ce5e6 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -1158,14 +1158,6 @@ Exercises `[Type; n]` syntax for creating arrays with repeated types across a se Tests on the `#[repr(..)]` attribute. See [Representations | Reference](https://doc.rust-lang.org/reference/type-layout.html#representations). -## `tests/ui/reserved/` - -Reserved keywords and attribute names. - -See e.g. [Reserved keywords | Reference](https://doc.rust-lang.org/reference/keywords.html). - -**FIXME**: maybe merge under `tests/ui/keyword/`. - ## `tests/ui/resolve/`: Name resolution See [Name resolution | rustc-dev-guide](https://rustc-dev-guide.rust-lang.org/name-resolution.html). diff --git a/tests/ui/reserved/meta-is-not-reserved.rs b/tests/ui/keyword/meta-is-not-reserved.rs similarity index 100% rename from tests/ui/reserved/meta-is-not-reserved.rs rename to tests/ui/keyword/meta-is-not-reserved.rs diff --git a/tests/ui/reserved/meta-is-not-reserved.stderr b/tests/ui/keyword/meta-is-not-reserved.stderr similarity index 100% rename from tests/ui/reserved/meta-is-not-reserved.stderr rename to tests/ui/keyword/meta-is-not-reserved.stderr diff --git a/tests/ui/reserved/reserved-attr-on-macro.rs b/tests/ui/keyword/reserved-attr-on-macro.rs similarity index 100% rename from tests/ui/reserved/reserved-attr-on-macro.rs rename to tests/ui/keyword/reserved-attr-on-macro.rs diff --git a/tests/ui/reserved/reserved-attr-on-macro.stderr b/tests/ui/keyword/reserved-attr-on-macro.stderr similarity index 100% rename from tests/ui/reserved/reserved-attr-on-macro.stderr rename to tests/ui/keyword/reserved-attr-on-macro.stderr diff --git a/tests/ui/reserved/reserved-become.rs b/tests/ui/keyword/reserved-become.rs similarity index 100% rename from tests/ui/reserved/reserved-become.rs rename to tests/ui/keyword/reserved-become.rs diff --git a/tests/ui/reserved/reserved-become.stderr b/tests/ui/keyword/reserved-become.stderr similarity index 100% rename from tests/ui/reserved/reserved-become.stderr rename to tests/ui/keyword/reserved-become.stderr From 07d015e566dc55235094ee4a48407253ca8246c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 23 Apr 2026 21:45:54 +0200 Subject: [PATCH 06/14] Syntactically reject tuple index shorthands in struct patterns to fix a correctness regression --- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_parse/src/parser/mod.rs | 21 +++++++-- compiler/rustc_parse/src/parser/pat.rs | 10 ++-- compiler/rustc_parse/src/parser/ty.rs | 12 +++-- .../struct-expr-pat-tuple-index-shorthand.rs | 19 ++++++++ ...uct-expr-pat-tuple-index-shorthand.stderr} | 16 +++++-- .../parser/struct-field-numeric-shorthand.rs | 8 ---- tests/ui/pattern/self-ctor-133272.stderr | 4 +- tests/ui/self/self_type_keyword.rs | 1 - tests/ui/self/self_type_keyword.stderr | 22 ++++----- .../struct-pat-unmentioned-tuple-indices.rs | 11 +++++ ...truct-pat-unmentioned-tuple-indices.stderr | 41 ++++++++++++++++ tests/ui/structs/struct-tuple-field-names.rs | 18 ------- .../structs/struct-tuple-field-names.stderr | 47 ------------------- ...variant-written-as-empty-struct-variant.rs | 7 +++ ...ant-written-as-empty-struct-variant.stderr | 27 +++++++++++ 16 files changed, 160 insertions(+), 106 deletions(-) create mode 100644 tests/ui/parser/struct-expr-pat-tuple-index-shorthand.rs rename tests/ui/parser/{struct-field-numeric-shorthand.stderr => struct-expr-pat-tuple-index-shorthand.stderr} (55%) delete mode 100644 tests/ui/parser/struct-field-numeric-shorthand.rs create mode 100644 tests/ui/structs/struct-pat-unmentioned-tuple-indices.rs create mode 100644 tests/ui/structs/struct-pat-unmentioned-tuple-indices.stderr delete mode 100644 tests/ui/structs/struct-tuple-field-names.rs delete mode 100644 tests/ui/structs/struct-tuple-field-names.stderr create mode 100644 tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.rs create mode 100644 tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.stderr diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a0601cc71d032..d55548dd72180 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -866,7 +866,7 @@ impl<'a> Parser<'a> { // `raw [ const | mut ]`. let found_raw = self.eat_keyword(exp!(Raw)); assert!(found_raw); - let mutability = self.parse_const_or_mut().unwrap(); + let mutability = self.parse_mut_or_const().unwrap(); (ast::BorrowKind::Raw, mutability) } else { match self.parse_pin_and_mut() { diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 8c1c3c7025f5e..9303be8ff0ccd 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1302,12 +1302,16 @@ impl<'a> Parser<'a> { Ok(self.mk_expr_with_attrs(span.to(blk_span), kind, attrs)) } - /// Parses mutability (`mut` or nothing). + /// Parse nothing or `mut`. fn parse_mutability(&mut self) -> Mutability { if self.eat_keyword(exp!(Mut)) { Mutability::Mut } else { Mutability::Not } } - /// Parses reference binding mode (`ref`, `ref mut`, `ref pin const`, `ref pin mut`, or nothing). + /// Parse nothing or a by-reference mode. + /// + /// ```ebnf + /// ByRef = "ref" PinAndMut? + /// ``` fn parse_byref(&mut self) -> ByRef { if self.eat_keyword(exp!(Ref)) { let (pinnedness, mutability) = self.parse_pin_and_mut(); @@ -1317,8 +1321,12 @@ impl<'a> Parser<'a> { } } - /// Possibly parses mutability (`const` or `mut`). - fn parse_const_or_mut(&mut self) -> Option { + /// Parse nothing or "explicit" mutability. + /// + /// ```ebnf + /// MutOrConst = "mut" | "const" + /// ``` + fn parse_mut_or_const(&mut self) -> Option { if self.eat_keyword(exp!(Mut)) { Some(Mutability::Mut) } else if self.eat_keyword(exp!(Const)) { @@ -1328,6 +1336,11 @@ impl<'a> Parser<'a> { } } + /// Parse a field name. + /// + /// ```enbf + /// FieldName = IntLit | Ident + /// ``` fn parse_field_name(&mut self) -> PResult<'a, Ident> { if let token::Literal(token::Lit { kind: token::Integer, symbol, suffix }) = self.token.kind { diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index bdcbb1eb42a88..b5c33d740872b 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1731,11 +1731,14 @@ impl<'a> Parser<'a> { self.dcx().emit_err(DotDotDotForRemainingFields { span: self.token.span, token_str }); } + /// Parse a field in a struct pattern. + /// + /// ```ebnf + /// PatField = FieldName ":" Pat | "box"? "mut"? ByRef? Ident + /// ``` fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> { - // Check if a colon exists one ahead. This means we're parsing a fieldname. let hi; let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) { - // Parsing a pattern of the form `fieldname: pat`. let fieldname = self.parse_field_name()?; self.bump(); let pat = self.parse_pat_allow_top_guard( @@ -1747,7 +1750,6 @@ impl<'a> Parser<'a> { hi = pat.span; (pat, fieldname, false) } else { - // Parsing a pattern of the form `(box) (ref) (mut) fieldname`. let is_box = self.eat_keyword(exp!(Box)); if is_box { self.psess.gated_spans.gate(sym::box_patterns, self.prev_token.span); @@ -1756,7 +1758,7 @@ impl<'a> Parser<'a> { let mutability = self.parse_mutability(); let by_ref = self.parse_byref(); - let fieldname = self.parse_field_name()?; + let fieldname = self.parse_ident_common(false)?; hi = self.prev_token.span; let ann = BindingMode(by_ref, mutability); let fieldpat = self.mk_pat_ident(boxed_span.to(hi), ann, fieldname); diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 2a5cd4cd55aec..072975f445bf4 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -596,7 +596,7 @@ impl<'a> Parser<'a> { /// Parses a raw pointer with a C-style typo fn parse_ty_c_style_pointer(&mut self) -> PResult<'a, TyKind> { let kw_span = self.token.span; - let mutbl = self.parse_const_or_mut(); + let mutbl = self.parse_mut_or_const(); if let Some(mutbl) = mutbl && self.eat(exp!(Star)) @@ -630,7 +630,7 @@ impl<'a> Parser<'a> { /// Parses a raw pointer type: `*[const | mut] $type`. fn parse_ty_ptr(&mut self) -> PResult<'a, TyKind> { - let mutbl = self.parse_const_or_mut().unwrap_or_else(|| { + let mutbl = self.parse_mut_or_const().unwrap_or_else(|| { let span = self.prev_token.span; self.dcx().emit_err(ExpectedMutOrConstInRawPointerType { span, @@ -774,14 +774,16 @@ impl<'a> Parser<'a> { }) } - /// Parses `pin` and `mut` annotations on references, patterns, or borrow modifiers. + /// Parse nothing, mutability or `pin` followed by "explicit" mutability. /// - /// It must be either `pin const`, `pin mut`, `mut`, or nothing (immutable). + /// ```ebnf + /// PinAndMut = "pin" MutOrConst | "mut" + /// ``` pub(crate) fn parse_pin_and_mut(&mut self) -> (Pinnedness, Mutability) { if self.token.is_ident_named(sym::pin) && self.look_ahead(1, Token::is_mutability) { self.psess.gated_spans.gate(sym::pin_ergonomics, self.token.span); assert!(self.eat_keyword(exp!(Pin))); - let mutbl = self.parse_const_or_mut().unwrap(); + let mutbl = self.parse_mut_or_const().unwrap(); (Pinnedness::Pinned, mutbl) } else { (Pinnedness::Not, self.parse_mutability()) diff --git a/tests/ui/parser/struct-expr-pat-tuple-index-shorthand.rs b/tests/ui/parser/struct-expr-pat-tuple-index-shorthand.rs new file mode 100644 index 0000000000000..fde5563cd4b82 --- /dev/null +++ b/tests/ui/parser/struct-expr-pat-tuple-index-shorthand.rs @@ -0,0 +1,19 @@ +// Check that tuple indices in struct exprs & pats don't have a shorthand. +// If they did it would be possible to bind and reference numeric identifiers +// which is undesirable. + +struct Rgb(u8, u8, u8); + +#[cfg(false)] // ensures that this is a *syntax* error, not just a semantic one! +fn scope() { + // FIXME: Better recover and also report a diagnostic for the other two fields. + let Rgb { 0, 1, 2 }; + //~^ ERROR expected identifier, found `0` + + let _ = Rgb { 0, 1, 2 }; + //~^ ERROR expected identifier, found `0` + //~| ERROR expected identifier, found `1` + //~| ERROR expected identifier, found `2` +} + +fn main() {} diff --git a/tests/ui/parser/struct-field-numeric-shorthand.stderr b/tests/ui/parser/struct-expr-pat-tuple-index-shorthand.stderr similarity index 55% rename from tests/ui/parser/struct-field-numeric-shorthand.stderr rename to tests/ui/parser/struct-expr-pat-tuple-index-shorthand.stderr index 9878cfbbdceb8..5a618f1d3383d 100644 --- a/tests/ui/parser/struct-field-numeric-shorthand.stderr +++ b/tests/ui/parser/struct-expr-pat-tuple-index-shorthand.stderr @@ -1,5 +1,13 @@ error: expected identifier, found `0` - --> $DIR/struct-field-numeric-shorthand.rs:4:19 + --> $DIR/struct-expr-pat-tuple-index-shorthand.rs:10:15 + | +LL | let Rgb { 0, 1, 2 }; + | --- ^ expected identifier + | | + | while parsing the fields for this pattern + +error: expected identifier, found `0` + --> $DIR/struct-expr-pat-tuple-index-shorthand.rs:13:19 | LL | let _ = Rgb { 0, 1, 2 }; | --- ^ expected identifier @@ -7,7 +15,7 @@ LL | let _ = Rgb { 0, 1, 2 }; | while parsing this struct error: expected identifier, found `1` - --> $DIR/struct-field-numeric-shorthand.rs:4:22 + --> $DIR/struct-expr-pat-tuple-index-shorthand.rs:13:22 | LL | let _ = Rgb { 0, 1, 2 }; | --- ^ expected identifier @@ -15,12 +23,12 @@ LL | let _ = Rgb { 0, 1, 2 }; | while parsing this struct error: expected identifier, found `2` - --> $DIR/struct-field-numeric-shorthand.rs:4:25 + --> $DIR/struct-expr-pat-tuple-index-shorthand.rs:13:25 | LL | let _ = Rgb { 0, 1, 2 }; | --- ^ expected identifier | | | while parsing this struct -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/parser/struct-field-numeric-shorthand.rs b/tests/ui/parser/struct-field-numeric-shorthand.rs deleted file mode 100644 index aa342eb02a916..0000000000000 --- a/tests/ui/parser/struct-field-numeric-shorthand.rs +++ /dev/null @@ -1,8 +0,0 @@ -struct Rgb(u8, u8, u8); - -fn main() { - let _ = Rgb { 0, 1, 2 }; - //~^ ERROR expected identifier, found `0` - //~| ERROR expected identifier, found `1` - //~| ERROR expected identifier, found `2` -} diff --git a/tests/ui/pattern/self-ctor-133272.stderr b/tests/ui/pattern/self-ctor-133272.stderr index bca55a43d9c08..f3053a3e7d79a 100644 --- a/tests/ui/pattern/self-ctor-133272.stderr +++ b/tests/ui/pattern/self-ctor-133272.stderr @@ -2,7 +2,9 @@ error: expected identifier, found keyword `Self` --> $DIR/self-ctor-133272.rs:17:21 | LL | let S { ref Self } = todo!(); - | ^^^^ expected identifier, found keyword + | - ^^^^ expected identifier, found keyword + | | + | while parsing the fields for this pattern error[E0422]: cannot find struct, variant or union type `S` in this scope --> $DIR/self-ctor-133272.rs:17:13 diff --git a/tests/ui/self/self_type_keyword.rs b/tests/ui/self/self_type_keyword.rs index 463872585f942..70eb539bb1fd9 100644 --- a/tests/ui/self/self_type_keyword.rs +++ b/tests/ui/self/self_type_keyword.rs @@ -22,7 +22,6 @@ pub fn main() { Foo { Self } => (), //~^ ERROR expected identifier, found keyword `Self` //~| ERROR mismatched types - //~| ERROR `Foo` does not have a field named `Self` } } diff --git a/tests/ui/self/self_type_keyword.stderr b/tests/ui/self/self_type_keyword.stderr index 06761bb40c031..b839bec0b8b7a 100644 --- a/tests/ui/self/self_type_keyword.stderr +++ b/tests/ui/self/self_type_keyword.stderr @@ -39,22 +39,24 @@ error: expected identifier, found keyword `Self` --> $DIR/self_type_keyword.rs:22:15 | LL | Foo { Self } => (), - | ^^^^ expected identifier, found keyword + | --- ^^^^ expected identifier, found keyword + | | + | while parsing the fields for this pattern error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:30:26 + --> $DIR/self_type_keyword.rs:29:26 | LL | extern crate core as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:35:32 + --> $DIR/self_type_keyword.rs:34:32 | LL | use std::option::Option as Self; | ^^^^ expected identifier, found keyword error: expected identifier, found keyword `Self` - --> $DIR/self_type_keyword.rs:40:11 + --> $DIR/self_type_keyword.rs:39:11 | LL | trait Self {} | ^^^^ expected identifier, found keyword @@ -88,13 +90,7 @@ LL | match 15 { LL | Foo { Self } => (), | ^^^^^^^^^^^^ expected integer, found `Foo` -error[E0026]: struct `Foo` does not have a field named `Self` - --> $DIR/self_type_keyword.rs:22:15 - | -LL | Foo { Self } => (), - | ^^^^ struct `Foo` does not have this field - -error: aborting due to 13 previous errors +error: aborting due to 12 previous errors -Some errors have detailed explanations: E0026, E0308, E0392, E0531. -For more information about an error, try `rustc --explain E0026`. +Some errors have detailed explanations: E0308, E0392, E0531. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/structs/struct-pat-unmentioned-tuple-indices.rs b/tests/ui/structs/struct-pat-unmentioned-tuple-indices.rs new file mode 100644 index 0000000000000..1f637d34c1abc --- /dev/null +++ b/tests/ui/structs/struct-pat-unmentioned-tuple-indices.rs @@ -0,0 +1,11 @@ +// On unmentioned tuple indices in struct patterns, don't suggest turning the pattern into a +// tuple struct pattern and keep the struct pattern in the suggestion. +// issue: + +struct S(i32, f32); +enum E { V(i32, f32) } + +fn main() { + let S { 0: _ } = S(1, 2.2); //~ ERROR: pattern does not mention field `1` + let E::V { 0: _ } = E::V(1, 2.2); //~ ERROR: pattern does not mention field `1` +} diff --git a/tests/ui/structs/struct-pat-unmentioned-tuple-indices.stderr b/tests/ui/structs/struct-pat-unmentioned-tuple-indices.stderr new file mode 100644 index 0000000000000..bc5480c26bbdc --- /dev/null +++ b/tests/ui/structs/struct-pat-unmentioned-tuple-indices.stderr @@ -0,0 +1,41 @@ +error[E0027]: pattern does not mention field `1` + --> $DIR/struct-pat-unmentioned-tuple-indices.rs:9:9 + | +LL | let S { 0: _ } = S(1, 2.2); + | ^^^^^^^^^^ missing field `1` + | +help: include the missing field in the pattern + | +LL | let S { 0: _, 1: _ } = S(1, 2.2); + | ++++++ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let S { 0: _, 1: _ } = S(1, 2.2); + | ++++++ +help: or always ignore missing fields here + | +LL | let S { 0: _, .. } = S(1, 2.2); + | ++++ + +error[E0027]: pattern does not mention field `1` + --> $DIR/struct-pat-unmentioned-tuple-indices.rs:10:9 + | +LL | let E::V { 0: _ } = E::V(1, 2.2); + | ^^^^^^^^^^^^^ missing field `1` + | +help: include the missing field in the pattern + | +LL | let E::V { 0: _, 1: _ } = E::V(1, 2.2); + | ++++++ +help: if you don't care about this missing field, you can explicitly ignore it + | +LL | let E::V { 0: _, 1: _ } = E::V(1, 2.2); + | ++++++ +help: or always ignore missing fields here + | +LL | let E::V { 0: _, .. } = E::V(1, 2.2); + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0027`. diff --git a/tests/ui/structs/struct-tuple-field-names.rs b/tests/ui/structs/struct-tuple-field-names.rs deleted file mode 100644 index 33f264aa25091..0000000000000 --- a/tests/ui/structs/struct-tuple-field-names.rs +++ /dev/null @@ -1,18 +0,0 @@ -struct S(i32, f32); -enum E { - S(i32, f32), -} -fn main() { - let x = E::S(1, 2.2); - match x { - E::S { 0, 1 } => {} - //~^ ERROR tuple variant `E::S` written as struct variant [E0769] - } - let y = S(1, 2.2); - match y { - S { } => {} //~ ERROR: tuple variant `S` written as struct variant [E0769] - } - - if let E::S { 0: a } = x { //~ ERROR: pattern does not mention field `1` - } -} diff --git a/tests/ui/structs/struct-tuple-field-names.stderr b/tests/ui/structs/struct-tuple-field-names.stderr deleted file mode 100644 index 953f01e1fb6cc..0000000000000 --- a/tests/ui/structs/struct-tuple-field-names.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error[E0769]: tuple variant `E::S` written as struct variant - --> $DIR/struct-tuple-field-names.rs:8:9 - | -LL | E::S { 0, 1 } => {} - | ^^^^^^^^^^^^^ - | -help: use the tuple variant pattern syntax instead - | -LL - E::S { 0, 1 } => {} -LL + E::S(_, _) => {} - | - -error[E0769]: tuple variant `S` written as struct variant - --> $DIR/struct-tuple-field-names.rs:13:9 - | -LL | S { } => {} - | ^^^^^ - | -help: use the tuple variant pattern syntax instead - | -LL - S { } => {} -LL + S(_, _) => {} - | - -error[E0027]: pattern does not mention field `1` - --> $DIR/struct-tuple-field-names.rs:16:12 - | -LL | if let E::S { 0: a } = x { - | ^^^^^^^^^^^^^ missing field `1` - | -help: include the missing field in the pattern - | -LL | if let E::S { 0: a, 1: _ } = x { - | ++++++ -help: if you don't care about this missing field, you can explicitly ignore it - | -LL | if let E::S { 0: a, 1: _ } = x { - | ++++++ -help: or always ignore missing fields here - | -LL | if let E::S { 0: a, .. } = x { - | ++++ - -error: aborting due to 3 previous errors - -Some errors have detailed explanations: E0027, E0769. -For more information about an error, try `rustc --explain E0027`. diff --git a/tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.rs b/tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.rs new file mode 100644 index 0000000000000..3382ac9e868a7 --- /dev/null +++ b/tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.rs @@ -0,0 +1,7 @@ +struct S(i32); +enum E { V(i32) } + +fn main() { + let S {} = S(0); //~ ERROR tuple variant `S` written as struct variant + let E::V {} = E::V(0); //~ ERROR tuple variant `E::V` written as struct variant +} diff --git a/tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.stderr b/tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.stderr new file mode 100644 index 0000000000000..ef63238b00406 --- /dev/null +++ b/tests/ui/tuple/tuple-variant-written-as-empty-struct-variant.stderr @@ -0,0 +1,27 @@ +error[E0769]: tuple variant `S` written as struct variant + --> $DIR/tuple-variant-written-as-empty-struct-variant.rs:5:9 + | +LL | let S {} = S(0); + | ^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL - let S {} = S(0); +LL + let S(_) = S(0); + | + +error[E0769]: tuple variant `E::V` written as struct variant + --> $DIR/tuple-variant-written-as-empty-struct-variant.rs:6:9 + | +LL | let E::V {} = E::V(0); + | ^^^^^^^ + | +help: use the tuple variant pattern syntax instead + | +LL - let E::V {} = E::V(0); +LL + let E::V(_) = E::V(0); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0769`. From 87b0ce595c03a811f78ef1b05f1689545cd83392 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Apr 2026 23:00:38 +0200 Subject: [PATCH 07/14] Remove `AttributeLintKind::MissingOptionsForDiagnosticAttribute` variant --- .../src/attributes/diagnostic/mod.rs | 14 +++++++++----- compiler/rustc_attr_parsing/src/errors.rs | 8 ++++++++ compiler/rustc_lint/src/early/diagnostics.rs | 4 ---- compiler/rustc_lint/src/lints.rs | 8 -------- compiler/rustc_lint_defs/src/lib.rs | 1 - 5 files changed, 17 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs index 00e753eea97cd..da598d8bac8cd 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs @@ -20,7 +20,8 @@ use thin_vec::{ThinVec, thin_vec}; use crate::context::{AcceptContext, Stage}; use crate::errors::{ DisallowedPlaceholder, DisallowedPositionalArgument, IgnoredDiagnosticOption, - InvalidFormatSpecifier, MalFormedDiagnosticAttributeLint, WrappedParserError, + InvalidFormatSpecifier, MalFormedDiagnosticAttributeLint, MissingOptionsForDiagnosticAttribute, + WrappedParserError, }; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser}; @@ -151,11 +152,14 @@ fn parse_list<'p, S: Stage>( ); } ArgParser::NoArgs => { - cx.emit_lint( + cx.emit_dyn_lint( MALFORMED_DIAGNOSTIC_ATTRIBUTES, - AttributeLintKind::MissingOptionsForDiagnosticAttribute { - attribute: mode.as_str(), - options: mode.expected_options(), + move |dcx, level| { + MissingOptionsForDiagnosticAttribute { + attribute: mode.as_str(), + options: mode.expected_options(), + } + .into_diag(dcx, level) }, span, ); diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index b421e85688958..34558c8c057ed 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -392,3 +392,11 @@ pub(crate) struct IgnoredDiagnosticOption { #[label("`{$option_name}` is later redundantly declared here")] pub later_span: Span, } + +#[derive(Diagnostic)] +#[diag("missing options for `{$attribute}` attribute")] +#[help("{$options}")] +pub(crate) struct MissingOptionsForDiagnosticAttribute { + pub attribute: &'static str, + pub options: &'static str, +} diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 29c302ff2802a..40623a4af6cef 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -43,10 +43,6 @@ impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> { .into_diag(dcx, level) } - &AttributeLintKind::MissingOptionsForDiagnosticAttribute { attribute, options } => { - lints::MissingOptionsForDiagnosticAttribute { attribute, options } - .into_diag(dcx, level) - } &AttributeLintKind::NonMetaItemDiagnosticAttribute => { lints::NonMetaItemDiagnosticAttribute.into_diag(dcx, level) } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index c2c140a3c6d92..0fc9ed8116f57 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3282,14 +3282,6 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } } -#[derive(Diagnostic)] -#[diag("missing options for `{$attribute}` attribute")] -#[help("{$options}")] -pub(crate) struct MissingOptionsForDiagnosticAttribute { - pub attribute: &'static str, - pub options: &'static str, -} - #[derive(Diagnostic)] #[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")] #[note("this method was used to add checks to the `Eq` derive macro")] diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index aef62c768337b..5df038e3124a2 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -656,7 +656,6 @@ pub enum DeprecatedSinceKind { pub enum AttributeLintKind { UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), - MissingOptionsForDiagnosticAttribute { attribute: &'static str, options: &'static str }, NonMetaItemDiagnosticAttribute, } From 7a07b795737d798b90c82a7edb02cc4287039d67 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 23 Apr 2026 23:08:40 +0200 Subject: [PATCH 08/14] Remove `AttributeLintKind::NonMetaItemDiagnosticAttribute` variant --- .../rustc_attr_parsing/src/attributes/diagnostic/mod.rs | 8 ++++---- compiler/rustc_attr_parsing/src/errors.rs | 7 +++++++ compiler/rustc_lint/src/early/diagnostics.rs | 6 ------ compiler/rustc_lint/src/lints.rs | 7 ------- compiler/rustc_lint_defs/src/lib.rs | 1 - 5 files changed, 11 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs index da598d8bac8cd..53491a0a959ac 100644 --- a/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs @@ -6,7 +6,7 @@ use rustc_hir::attrs::diagnostic::{ Directive, FilterFormatString, Flag, FormatArg, FormatString, LitOrArg, Name, NameValue, OnUnimplementedCondition, Piece, Predicate, }; -use rustc_hir::lints::{AttributeLintKind, FormatWarning}; +use rustc_hir::lints::FormatWarning; use rustc_macros::Diagnostic; use rustc_parse_format::{ Argument, FormatSpec, ParseError, ParseMode, Parser, Piece as RpfPiece, Position, @@ -21,7 +21,7 @@ use crate::context::{AcceptContext, Stage}; use crate::errors::{ DisallowedPlaceholder, DisallowedPositionalArgument, IgnoredDiagnosticOption, InvalidFormatSpecifier, MalFormedDiagnosticAttributeLint, MissingOptionsForDiagnosticAttribute, - WrappedParserError, + NonMetaItemDiagnosticAttribute, WrappedParserError, }; use crate::parser::{ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser}; @@ -145,9 +145,9 @@ fn parse_list<'p, S: Stage>( // We're dealing with `#[diagnostic::attr()]`. // This can be because that is what the user typed, but that's also what we'd see // if the user used non-metaitem syntax. See `ArgParser::from_attr_args`. - cx.emit_lint( + cx.emit_dyn_lint( MALFORMED_DIAGNOSTIC_ATTRIBUTES, - AttributeLintKind::NonMetaItemDiagnosticAttribute, + move |dcx, level| NonMetaItemDiagnosticAttribute.into_diag(dcx, level), list.span, ); } diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 34558c8c057ed..95d0e82f472c0 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -400,3 +400,10 @@ pub(crate) struct MissingOptionsForDiagnosticAttribute { pub attribute: &'static str, pub options: &'static str, } + +#[derive(Diagnostic)] +#[diag("expected a literal or missing delimiter")] +#[help( + "only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma" +)] +pub(crate) struct NonMetaItemDiagnosticAttribute; diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 40623a4af6cef..a4cb4e5320672 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -6,8 +6,6 @@ use rustc_hir::lints::AttributeLintKind; use rustc_middle::ty::TyCtxt; use rustc_session::Session; -use crate::lints; - mod check_cfg; pub struct DiagAndSess<'sess> { @@ -42,10 +40,6 @@ impl<'a> Diagnostic<'a, ()> for DecorateAttrLint<'_, '_, '_> { check_cfg::unexpected_cfg_value(self.sess, self.tcx, name, value) .into_diag(dcx, level) } - - &AttributeLintKind::NonMetaItemDiagnosticAttribute => { - lints::NonMetaItemDiagnosticAttribute.into_diag(dcx, level) - } } } } diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 0fc9ed8116f57..05914686705a6 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3286,10 +3286,3 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { #[diag("`Eq::assert_receiver_is_total_eq` should never be implemented by hand")] #[note("this method was used to add checks to the `Eq` derive macro")] pub(crate) struct EqInternalMethodImplemented; - -#[derive(Diagnostic)] -#[diag("expected a literal or missing delimiter")] -#[help( - "only literals are allowed as values for the `message`, `note` and `label` options. These options must be separated by a comma" -)] -pub(crate) struct NonMetaItemDiagnosticAttribute; diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs index 5df038e3124a2..0a9c0669a5bd3 100644 --- a/compiler/rustc_lint_defs/src/lib.rs +++ b/compiler/rustc_lint_defs/src/lib.rs @@ -656,7 +656,6 @@ pub enum DeprecatedSinceKind { pub enum AttributeLintKind { UnexpectedCfgName((Symbol, Span), Option<(Symbol, Span)>), UnexpectedCfgValue((Symbol, Span), Option<(Symbol, Span)>), - NonMetaItemDiagnosticAttribute, } #[derive(Debug, Clone, HashStable_Generic)] From 874b7d31416fdfcad39f7f8f0179868cecac8cf6 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 23 Apr 2026 15:19:05 -0700 Subject: [PATCH 09/14] Remove myself as a maintainer of `wasm32-wasip1-threads` Over time the landscape for myself has changed, and I no longer would like to be officially listed as a maintainer of this target in Rust, so I'm going to step down. There are still a number of others listed on this target, however, so I'm sure they can address issues should they come up. --- src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md | 1 - 1 file changed, 1 deletion(-) diff --git a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md index 6c8bf21ec1997..cc66b2fdc6dcb 100644 --- a/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md +++ b/src/doc/rustc/src/platform-support/wasm32-wasip1-threads.md @@ -19,7 +19,6 @@ with native multi threading capabilities. ## Target maintainers [@g0djan](https://github.com/g0djan) -[@alexcrichton](https://github.com/alexcrichton) [@abrown](https://github.com/abrown) [@loganek](https://github.com/loganek) From 804e419ed85bbcaf99d1a3385cfef3bf3105cd05 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 22 Apr 2026 13:44:43 +1000 Subject: [PATCH 10/14] Eliminate `CrateMetadataRef`. There are a number of things I dislike about `CrateMetadataRef`. - It contains two fields `cstore` and `cdata`. The latter points to data within the former. It's like having an `Elem` type that has a reference to a vec element and also a reference to the vec itself. Weird. - The `cdata` field gets a lot of use, and the `Deref` impl just derefs that field. The `cstore` field is rarely used. - `CrateMetadataRef` is not a good name. - Variables named `cdata` sometimes refer to values of this type and sometimes to values of type `CrateMetadata`, which is confusing. The good news is that `CrateMetadataRef` is not necessary and can be replaced with `&CrateMetadata`. Why? Everywhere that `CrateMetadataRef` is used, a `TyCtxt` is also present, and the `CStore` is accessible from the `TyCtxt` with `CStore::from_tcx`. So this commit removes `CrateMetadataRef` and replaces all its uses with `&CrateMetadata`. Notes: - This requires adding only two uses of `CStore::from_tcx`, which shows how rarely the `cstore` field was used. - `get_crate_data` now matches `get_crate_data_mut` more closely. - A few variables are renamed for consistency, e.g. `data`/`cmeta` -> `cdata`. - An unnecessary local variable (`local_cdata`) in `decode_expn_id` is removed. - All the `CrateMetadataRef` methods become `CrateMetadata` methods, and their receiver changes from `self` to `&self`. - `RawDefId::decode_from_cdata` is inlined and removed, because it has a single call site. --- compiler/rustc_metadata/src/creader.rs | 54 ++-- compiler/rustc_metadata/src/rmeta/decoder.rs | 267 ++++++++---------- .../src/rmeta/decoder/cstore_impl.rs | 48 ++-- compiler/rustc_metadata/src/rmeta/mod.rs | 9 +- 4 files changed, 165 insertions(+), 213 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index feeb38830e0a9..9a756337335c0 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -111,21 +111,6 @@ enum LoadResult { Loaded(Library), } -/// A reference to `CrateMetadata` that can also give access to whole crate store when necessary. -#[derive(Clone, Copy)] -pub(crate) struct CrateMetadataRef<'a> { - pub cdata: &'a CrateMetadata, - pub cstore: &'a CStore, -} - -impl std::ops::Deref for CrateMetadataRef<'_> { - type Target = CrateMetadata; - - fn deref(&self) -> &Self::Target { - self.cdata - } -} - struct CrateDump<'a>(&'a CStore); impl<'a> std::fmt::Debug for CrateDump<'a> { @@ -245,11 +230,8 @@ impl CStore { self.metas[cnum].is_some() } - pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> CrateMetadataRef<'_> { - let cdata = self.metas[cnum] - .as_ref() - .unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}")); - CrateMetadataRef { cdata, cstore: self } + pub(crate) fn get_crate_data(&self, cnum: CrateNum) -> &CrateMetadata { + self.metas[cnum].as_ref().unwrap_or_else(|| panic!("Failed to get crate data for {cnum:?}")) } pub(crate) fn get_crate_data_mut(&mut self, cnum: CrateNum) -> &mut CrateMetadata { @@ -284,14 +266,13 @@ impl CStore { } pub fn all_proc_macro_def_ids(&self, tcx: TyCtxt<'_>) -> impl Iterator { - self.iter_crate_data() - .flat_map(move |(krate, data)| data.proc_macros_for_crate(tcx, krate, self)) + self.iter_crate_data().flat_map(move |(krate, data)| data.proc_macros_for_crate(tcx, krate)) } fn push_dependencies_in_postorder(&self, deps: &mut IndexSet, cnum: CrateNum) { if !deps.contains(&cnum) { - let data = self.get_crate_data(cnum); - for dep in data.dependencies() { + let cdata = self.get_crate_data(cnum); + for dep in cdata.dependencies() { if dep != cnum { self.push_dependencies_in_postorder(deps, dep); } @@ -676,7 +657,6 @@ impl CStore { let crate_metadata = CrateMetadata::new( tcx, - self, metadata, crate_root, raw_proc_macros, @@ -865,12 +845,12 @@ impl CStore { // `private-dependency` when `register_crate` is called for the first time. Then it must be updated to // `public-dependency` here. let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep); - let data = self.get_crate_data_mut(cnum); - if data.is_proc_macro_crate() { + let cdata = self.get_crate_data_mut(cnum); + if cdata.is_proc_macro_crate() { dep_kind = CrateDepKind::MacrosOnly; } - data.set_dep_kind(cmp::max(data.dep_kind(), dep_kind)); - data.update_and_private_dep(private_dep); + cdata.set_dep_kind(cmp::max(cdata.dep_kind(), dep_kind)); + cdata.update_and_private_dep(private_dep); Ok(cnum) } (LoadResult::Loaded(library), host_library) => { @@ -1045,14 +1025,14 @@ impl CStore { ) else { return; }; - let data = self.get_crate_data(cnum); + let cdata = self.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a panic runtime // and the panic strategy is indeed what we thought it was. - if !data.is_panic_runtime() { + if !cdata.is_panic_runtime() { tcx.dcx().emit_err(errors::CrateNotPanicRuntime { crate_name: name }); } - if data.required_panic_strategy() != Some(desired_strategy) { + if cdata.required_panic_strategy() != Some(desired_strategy) { tcx.dcx() .emit_err(errors::NoPanicStrategy { crate_name: name, strategy: desired_strategy }); } @@ -1086,10 +1066,10 @@ impl CStore { ) else { return; }; - let data = self.get_crate_data(cnum); + let cdata = self.get_crate_data(cnum); // Sanity check the loaded crate to ensure it is indeed a profiler runtime - if !data.is_profiler_runtime() { + if !cdata.is_profiler_runtime() { tcx.dcx().emit_err(errors::NotProfilerRuntime { crate_name: name }); } } @@ -1243,9 +1223,9 @@ impl CStore { }; // Sanity check that the loaded crate is `#![compiler_builtins]` - let cmeta = self.get_crate_data(cnum); - if !cmeta.is_compiler_builtins() { - tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cmeta.name() }); + let cdata = self.get_crate_data(cnum); + if !cdata.is_compiler_builtins() { + tcx.dcx().emit_err(errors::CrateNotCompilerBuiltins { crate_name: cdata.name() }); } } diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 181dbfa126d73..230ce5686e979 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -221,10 +221,11 @@ impl<'a> LazyDecoder for BlobDecodeContext<'a> { /// This is the decode context used when crate metadata was already read. /// Decoding of some types, like `Span` require some information to already been read. -/// Can be constructed from a [`TyCtxt`] and [`CrateMetadataRef`] (see the [`MetaDecoder`] trait) +/// Can be constructed from a [`TyCtxt`] and [`CrateMetadata`] (see impls of the [`MetaDecoder`] +/// trait). pub(super) struct MetadataDecodeContext<'a, 'tcx> { blob_decoder: BlobDecodeContext<'a>, - cdata: CrateMetadataRef<'a>, + cdata: &'a CrateMetadata, tcx: TyCtxt<'tcx>, // Used for decoding interpret::AllocIds in a cached & thread-safe manner. @@ -296,15 +297,15 @@ impl<'a> MetaBlob<'a> for &'a CrateMetadata { } } -impl<'a, 'tcx> MetaDecoder for (CrateMetadataRef<'a>, TyCtxt<'tcx>) { +impl<'a, 'tcx> MetaDecoder for (&'a CrateMetadata, TyCtxt<'tcx>) { type Context = MetadataDecodeContext<'a, 'tcx>; fn decoder(self, pos: usize) -> MetadataDecodeContext<'a, 'tcx> { MetadataDecodeContext { - blob_decoder: self.0.cdata.blob().decoder(pos), + blob_decoder: self.0.blob().decoder(pos), cdata: self.0, tcx: self.1, - alloc_decoding_session: self.0.cdata.alloc_decoding_state.new_decoding_session(), + alloc_decoding_session: self.0.alloc_decoding_state.new_decoding_session(), } } } @@ -472,15 +473,13 @@ impl<'a, 'tcx> SpanDecoder for MetadataDecodeContext<'a, 'tcx> { cdata .root .syntax_contexts - .get(cdata.cdata, id) + .get(cdata, id) .unwrap_or_else(|| panic!("Missing SyntaxContext {id:?} for crate {cname:?}")) .decode((cdata, tcx)) }) } fn decode_expn_id(&mut self) -> ExpnId { - let local_cdata = self.cdata; - let tcx = self.tcx; let cnum = CrateNum::decode(self); let index = u32::decode(self); @@ -490,23 +489,15 @@ impl<'a, 'tcx> SpanDecoder for MetadataDecodeContext<'a, 'tcx> { // Lookup local `ExpnData`s in our own crate data. Foreign `ExpnData`s // are stored in the owning crate, to avoid duplication. debug_assert_ne!(cnum, LOCAL_CRATE); - let crate_data = if cnum == local_cdata.cnum { - local_cdata + let cstore; + let cdata = if cnum == self.cdata.cnum { + self.cdata } else { - local_cdata.cstore.get_crate_data(cnum) + cstore = CStore::from_tcx(tcx); + cstore.get_crate_data(cnum) }; - let expn_data = crate_data - .root - .expn_data - .get(crate_data.cdata, index) - .unwrap() - .decode((crate_data, tcx)); - let expn_hash = crate_data - .root - .expn_hashes - .get(crate_data.cdata, index) - .unwrap() - .decode((crate_data, tcx)); + let expn_data = cdata.root.expn_data.get(cdata, index).unwrap().decode((cdata, tcx)); + let expn_hash = cdata.root.expn_hashes.get(cdata, index).unwrap().decode((cdata, tcx)); (expn_data, expn_hash) }); expn_id @@ -639,8 +630,9 @@ impl<'a, 'tcx> Decodable> for SpanData { cnum ); - let foreign_data = decoder.cdata.cstore.get_crate_data(cnum); - foreign_data.imported_source_file(tcx, metadata_index) + let cstore = CStore::from_tcx(tcx); + let foreign_cdata = cstore.get_crate_data(cnum); + foreign_cdata.imported_source_file(tcx, metadata_index) }; // Make sure our span is well-formed. @@ -979,12 +971,12 @@ impl CrateRoot { } } -impl<'a> CrateMetadataRef<'a> { - fn missing(self, descr: &str, id: DefIndex) -> ! { +impl CrateMetadata { + fn missing(&self, descr: &str, id: DefIndex) -> ! { bug!("missing `{descr}` for {:?}", self.local_def_id(id)) } - fn raw_proc_macro(self, tcx: TyCtxt<'_>, id: DefIndex) -> &'a ProcMacro { + fn raw_proc_macro(&self, tcx: TyCtxt<'_>, id: DefIndex) -> &ProcMacro { // DefIndex's in root.proc_macro_data have a one-to-one correspondence // with items in 'raw_proc_macros'. let pos = self @@ -999,7 +991,7 @@ impl<'a> CrateMetadataRef<'a> { &self.raw_proc_macros.unwrap()[pos] } - fn opt_item_name(self, item_index: DefIndex) -> Option { + fn opt_item_name(&self, item_index: DefIndex) -> Option { let def_key = self.def_key(item_index); def_key.disambiguated_data.data.get_opt_name().or_else(|| { if def_key.disambiguated_data.data == DefPathData::Ctor { @@ -1011,49 +1003,49 @@ impl<'a> CrateMetadataRef<'a> { }) } - fn item_name(self, item_index: DefIndex) -> Symbol { + fn item_name(&self, item_index: DefIndex) -> Symbol { self.opt_item_name(item_index).expect("no encoded ident for item") } - fn opt_item_ident(self, tcx: TyCtxt<'_>, item_index: DefIndex) -> Option { + fn opt_item_ident(&self, tcx: TyCtxt<'_>, item_index: DefIndex) -> Option { let name = self.opt_item_name(item_index)?; let span = self .root .tables .def_ident_span - .get(self.cdata, item_index) + .get(self, item_index) .unwrap_or_else(|| self.missing("def_ident_span", item_index)) .decode((self, tcx)); Some(Ident::new(name, span)) } - fn item_ident(self, tcx: TyCtxt<'_>, item_index: DefIndex) -> Ident { + fn item_ident(&self, tcx: TyCtxt<'_>, item_index: DefIndex) -> Ident { self.opt_item_ident(tcx, item_index).expect("no encoded ident for item") } #[inline] - pub(super) fn map_encoded_cnum_to_current(self, cnum: CrateNum) -> CrateNum { + pub(super) fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum { if cnum == LOCAL_CRATE { self.cnum } else { self.cnum_map[cnum] } } - fn def_kind(self, item_id: DefIndex) -> DefKind { + fn def_kind(&self, item_id: DefIndex) -> DefKind { self.root .tables .def_kind - .get(self.cdata, item_id) + .get(self, item_id) .unwrap_or_else(|| self.missing("def_kind", item_id)) } - fn get_span(self, tcx: TyCtxt<'_>, index: DefIndex) -> Span { + fn get_span(&self, tcx: TyCtxt<'_>, index: DefIndex) -> Span { self.root .tables .def_span - .get(self.cdata, index) + .get(self, index) .unwrap_or_else(|| self.missing("def_span", index)) .decode((self, tcx)) } - fn load_proc_macro<'tcx>(self, tcx: TyCtxt<'tcx>, id: DefIndex) -> SyntaxExtension { + fn load_proc_macro<'tcx>(&self, tcx: TyCtxt<'tcx>, id: DefIndex) -> SyntaxExtension { let (name, kind, helper_attrs) = match *self.raw_proc_macro(tcx, id) { ProcMacro::CustomDerive { trait_name, attributes, client } => { let helper_attrs = @@ -1087,7 +1079,7 @@ impl<'a> CrateMetadataRef<'a> { } fn get_variant( - self, + &self, tcx: TyCtxt<'_>, kind: DefKind, index: DefIndex, @@ -1100,8 +1092,7 @@ impl<'a> CrateMetadataRef<'a> { _ => bug!(), }; - let data = - self.root.tables.variant_data.get(self.cdata, index).unwrap().decode((self, tcx)); + let data = self.root.tables.variant_data.get(self, index).unwrap().decode((self, tcx)); let variant_did = if adt_kind == ty::AdtKind::Enum { Some(self.local_def_id(index)) } else { None }; @@ -1130,7 +1121,7 @@ impl<'a> CrateMetadataRef<'a> { ) } - fn get_adt_def<'tcx>(self, tcx: TyCtxt<'tcx>, item_id: DefIndex) -> ty::AdtDef<'tcx> { + fn get_adt_def<'tcx>(&self, tcx: TyCtxt<'tcx>, item_id: DefIndex) -> ty::AdtDef<'tcx> { let kind = self.def_kind(item_id); let did = self.local_def_id(item_id); @@ -1140,14 +1131,13 @@ impl<'a> CrateMetadataRef<'a> { DefKind::Union => ty::AdtKind::Union, _ => bug!("get_adt_def called on a non-ADT {:?}", did), }; - let repr = - self.root.tables.repr_options.get(self.cdata, item_id).unwrap().decode((self, tcx)); + let repr = self.root.tables.repr_options.get(self, item_id).unwrap().decode((self, tcx)); let mut variants: Vec<_> = if let ty::AdtKind::Enum = adt_kind { self.root .tables .module_children_non_reexports - .get(self.cdata, item_id) + .get(self, item_id) .expect("variants are not encoded for an enum") .decode((self, tcx)) .filter_map(|index| { @@ -1172,39 +1162,39 @@ impl<'a> CrateMetadataRef<'a> { ) } - fn get_visibility(self, tcx: TyCtxt<'_>, id: DefIndex) -> Visibility { + fn get_visibility(&self, tcx: TyCtxt<'_>, id: DefIndex) -> Visibility { self.root .tables .visibility - .get(self.cdata, id) + .get(self, id) .unwrap_or_else(|| self.missing("visibility", id)) .decode((self, tcx)) .map_id(|index| self.local_def_id(index)) } - fn get_safety(self, id: DefIndex) -> Safety { - self.root.tables.safety.get(self.cdata, id) + fn get_safety(&self, id: DefIndex) -> Safety { + self.root.tables.safety.get(self, id) } - fn get_default_field(self, tcx: TyCtxt<'_>, id: DefIndex) -> Option { - self.root.tables.default_fields.get(self.cdata, id).map(|d| d.decode((self, tcx))) + fn get_default_field(&self, tcx: TyCtxt<'_>, id: DefIndex) -> Option { + self.root.tables.default_fields.get(self, id).map(|d| d.decode((self, tcx))) } - fn get_expn_that_defined(self, tcx: TyCtxt<'_>, id: DefIndex) -> ExpnId { + fn get_expn_that_defined(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ExpnId { self.root .tables .expn_that_defined - .get(self.cdata, id) + .get(self, id) .unwrap_or_else(|| self.missing("expn_that_defined", id)) .decode((self, tcx)) } - fn get_debugger_visualizers(self, tcx: TyCtxt<'_>) -> Vec { + fn get_debugger_visualizers(&self, tcx: TyCtxt<'_>) -> Vec { self.root.debugger_visualizers.decode((self, tcx)).collect::>() } /// Iterates over all the stability attributes in the given crate. - fn get_lib_features(self, tcx: TyCtxt<'_>) -> LibFeatures { + fn get_lib_features(&self, tcx: TyCtxt<'_>) -> LibFeatures { LibFeatures { stability: self .root @@ -1218,12 +1208,12 @@ impl<'a> CrateMetadataRef<'a> { /// Iterates over the stability implications in the given crate (when a `#[unstable]` attribute /// has an `implied_by` meta item, then the mapping from the implied feature to the actual /// feature is a stability implication). - fn get_stability_implications<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { + fn get_stability_implications<'tcx>(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(Symbol, Symbol)] { tcx.arena.alloc_from_iter(self.root.stability_implications.decode((self, tcx))) } /// Iterates over the lang items in the given crate. - fn get_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { + fn get_lang_items<'tcx>(&self, tcx: TyCtxt<'tcx>) -> &'tcx [(DefId, LangItem)] { tcx.arena.alloc_from_iter( self.root .lang_items @@ -1233,7 +1223,7 @@ impl<'a> CrateMetadataRef<'a> { } fn get_stripped_cfg_items<'tcx>( - self, + &self, tcx: TyCtxt<'tcx>, cnum: CrateNum, ) -> &'tcx [StrippedCfgItem] { @@ -1246,7 +1236,7 @@ impl<'a> CrateMetadataRef<'a> { } /// Iterates over the diagnostic items in the given crate. - fn get_diagnostic_items(self, tcx: TyCtxt<'_>) -> DiagnosticItems { + fn get_diagnostic_items(&self, tcx: TyCtxt<'_>) -> DiagnosticItems { let mut id_to_name = DefIdMap::default(); let name_to_id = self .root @@ -1261,7 +1251,7 @@ impl<'a> CrateMetadataRef<'a> { DiagnosticItems { id_to_name, name_to_id } } - fn get_mod_child(self, tcx: TyCtxt<'_>, id: DefIndex) -> ModChild { + fn get_mod_child(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ModChild { let ident = self.item_ident(tcx, id); let res = Res::Def(self.def_kind(id), self.local_def_id(id)); let vis = self.get_visibility(tcx, id); @@ -1273,7 +1263,7 @@ impl<'a> CrateMetadataRef<'a> { /// including both proper items and reexports. /// Module here is understood in name resolution sense - it can be a `mod` item, /// or a crate root, or an enum, or a trait. - fn get_module_children(self, tcx: TyCtxt<'_>, id: DefIndex) -> impl Iterator { + fn get_module_children(&self, tcx: TyCtxt<'_>, id: DefIndex) -> impl Iterator { gen move { if let Some(data) = &self.root.proc_macro_data { // If we are loading as a proc macro, we want to return @@ -1285,13 +1275,12 @@ impl<'a> CrateMetadataRef<'a> { } } else { // Iterate over all children. - let non_reexports = - self.root.tables.module_children_non_reexports.get(self.cdata, id); + let non_reexports = self.root.tables.module_children_non_reexports.get(self, id); for child_index in non_reexports.unwrap().decode((self, tcx)) { yield self.get_mod_child(tcx, child_index); } - let reexports = self.root.tables.module_children_reexports.get(self.cdata, id); + let reexports = self.root.tables.module_children_reexports.get(self, id); if !reexports.is_default() { for reexport in reexports.decode((self, tcx)) { yield reexport; @@ -1302,12 +1291,12 @@ impl<'a> CrateMetadataRef<'a> { } fn get_ambig_module_children( - self, + &self, tcx: TyCtxt<'_>, id: DefIndex, ) -> impl Iterator { gen move { - let children = self.root.tables.ambig_module_children.get(self.cdata, id); + let children = self.root.tables.ambig_module_children.get(self, id); if !children.is_default() { for child in children.decode((self, tcx)) { yield child; @@ -1316,15 +1305,15 @@ impl<'a> CrateMetadataRef<'a> { } } - fn is_item_mir_available(self, id: DefIndex) -> bool { - self.root.tables.optimized_mir.get(self.cdata, id).is_some() + fn is_item_mir_available(&self, id: DefIndex) -> bool { + self.root.tables.optimized_mir.get(self, id).is_some() } - fn get_fn_has_self_parameter(self, tcx: TyCtxt<'_>, id: DefIndex) -> bool { + fn get_fn_has_self_parameter(&self, tcx: TyCtxt<'_>, id: DefIndex) -> bool { self.root .tables .fn_arg_idents - .get(self.cdata, id) + .get(self, id) .expect("argument names not encoded for a function") .decode((self, tcx)) .nth(0) @@ -1332,20 +1321,20 @@ impl<'a> CrateMetadataRef<'a> { } fn get_associated_item_or_field_def_ids( - self, + &self, tcx: TyCtxt<'_>, id: DefIndex, ) -> impl Iterator { self.root .tables .associated_item_or_field_def_ids - .get(self.cdata, id) + .get(self, id) .unwrap_or_else(|| self.missing("associated_item_or_field_def_ids", id)) .decode((self, tcx)) .map(move |child_index| self.local_def_id(child_index)) } - fn get_associated_item(self, tcx: TyCtxt<'_>, id: DefIndex) -> ty::AssocItem { + fn get_associated_item(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ty::AssocItem { let kind = match self.def_kind(id) { DefKind::AssocConst { is_type_const } => { ty::AssocKind::Const { name: self.item_name(id), is_type_const } @@ -1355,8 +1344,7 @@ impl<'a> CrateMetadataRef<'a> { has_self: self.get_fn_has_self_parameter(tcx, id), }, DefKind::AssocTy => { - let data = if let Some(rpitit_info) = - self.root.tables.opt_rpitit_info.get(self.cdata, id) + let data = if let Some(rpitit_info) = self.root.tables.opt_rpitit_info.get(self, id) { ty::AssocTypeData::Rpitit(rpitit_info.decode((self, tcx))) } else { @@ -1366,33 +1354,31 @@ impl<'a> CrateMetadataRef<'a> { } _ => bug!("cannot get associated-item of `{:?}`", self.def_key(id)), }; - let container = - self.root.tables.assoc_container.get(self.cdata, id).unwrap().decode((self, tcx)); + let container = self.root.tables.assoc_container.get(self, id).unwrap().decode((self, tcx)); ty::AssocItem { kind, def_id: self.local_def_id(id), container } } - fn get_ctor(self, tcx: TyCtxt<'_>, node_id: DefIndex) -> Option<(CtorKind, DefId)> { + fn get_ctor(&self, tcx: TyCtxt<'_>, node_id: DefIndex) -> Option<(CtorKind, DefId)> { match self.def_kind(node_id) { DefKind::Struct | DefKind::Variant => { - let vdata = self - .root - .tables - .variant_data - .get(self.cdata, node_id) - .unwrap() - .decode((self, tcx)); + let vdata = + self.root.tables.variant_data.get(self, node_id).unwrap().decode((self, tcx)); vdata.ctor.map(|(kind, index)| (kind, self.local_def_id(index))) } _ => None, } } - fn get_item_attrs(self, tcx: TyCtxt<'_>, id: DefIndex) -> impl Iterator { + fn get_item_attrs( + &self, + tcx: TyCtxt<'_>, + id: DefIndex, + ) -> impl Iterator { self.root .tables .attributes - .get(self.cdata, id) + .get(self, id) .unwrap_or_else(|| { // Structure and variant constructors don't have any attributes encoded for them, // but we assume that someone passing a constructor ID actually wants to look at @@ -1403,14 +1389,14 @@ impl<'a> CrateMetadataRef<'a> { self.root .tables .attributes - .get(self.cdata, parent_id) + .get(self, parent_id) .expect("no encoded attributes for a structure or variant") }) .decode((self, tcx)) } fn get_inherent_implementations_for_type<'tcx>( - self, + &self, tcx: TyCtxt<'tcx>, id: DefIndex, ) -> &'tcx [DefId] { @@ -1418,26 +1404,26 @@ impl<'a> CrateMetadataRef<'a> { self.root .tables .inherent_impls - .get(self.cdata, id) + .get(self, id) .decode((self, tcx)) .map(|index| self.local_def_id(index)), ) } /// Decodes all traits in the crate (for rustdoc and rustc diagnostics). - fn get_traits(self, tcx: TyCtxt<'_>) -> impl Iterator { + fn get_traits(&self, tcx: TyCtxt<'_>) -> impl Iterator { self.root.traits.decode((self, tcx)).map(move |index| self.local_def_id(index)) } /// Decodes all trait impls in the crate (for rustdoc). - fn get_trait_impls(self, tcx: TyCtxt<'_>) -> impl Iterator { - self.cdata.trait_impls.values().flat_map(move |impls| { + fn get_trait_impls(&self, tcx: TyCtxt<'_>) -> impl Iterator { + self.trait_impls.values().flat_map(move |impls| { impls.decode((self, tcx)).map(move |(impl_index, _)| self.local_def_id(impl_index)) }) } - fn get_incoherent_impls<'tcx>(self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { - if let Some(impls) = self.cdata.incoherent_impls.get(&simp) { + fn get_incoherent_impls<'tcx>(&self, tcx: TyCtxt<'tcx>, simp: SimplifiedType) -> &'tcx [DefId] { + if let Some(impls) = self.incoherent_impls.get(&simp) { tcx.arena.alloc_from_iter(impls.decode((self, tcx)).map(|idx| self.local_def_id(idx))) } else { &[] @@ -1445,7 +1431,7 @@ impl<'a> CrateMetadataRef<'a> { } fn get_implementations_of_trait<'tcx>( - self, + &self, tcx: TyCtxt<'tcx>, trait_def_id: DefId, ) -> &'tcx [(DefId, Option)] { @@ -1471,25 +1457,25 @@ impl<'a> CrateMetadataRef<'a> { } } - fn get_native_libraries(self, tcx: TyCtxt<'_>) -> impl Iterator { + fn get_native_libraries(&self, tcx: TyCtxt<'_>) -> impl Iterator { self.root.native_libraries.decode((self, tcx)) } - fn get_proc_macro_quoted_span(self, tcx: TyCtxt<'_>, index: usize) -> Span { + fn get_proc_macro_quoted_span(&self, tcx: TyCtxt<'_>, index: usize) -> Span { self.root .tables .proc_macro_quoted_spans - .get(self.cdata, index) + .get(self, index) .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}")) .decode((self, tcx)) } - fn get_foreign_modules(self, tcx: TyCtxt<'_>) -> impl Iterator { + fn get_foreign_modules(&self, tcx: TyCtxt<'_>) -> impl Iterator { self.root.foreign_modules.decode((self, tcx)) } fn get_dylib_dependency_formats<'tcx>( - self, + &self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(CrateNum, LinkagePreference)] { tcx.arena.alloc_from_iter( @@ -1503,22 +1489,22 @@ impl<'a> CrateMetadataRef<'a> { } fn get_externally_implementable_items( - self, + &self, tcx: TyCtxt<'_>, ) -> impl Iterator { self.root.externally_implementable_items.decode((self, tcx)) } - fn get_missing_lang_items<'tcx>(self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { + fn get_missing_lang_items<'tcx>(&self, tcx: TyCtxt<'tcx>) -> &'tcx [LangItem] { tcx.arena.alloc_from_iter(self.root.lang_items_missing.decode((self, tcx))) } - fn get_exportable_items(self, tcx: TyCtxt<'_>) -> impl Iterator { + fn get_exportable_items(&self, tcx: TyCtxt<'_>) -> impl Iterator { self.root.exportable_items.decode((self, tcx)).map(move |index| self.local_def_id(index)) } fn get_stable_order_of_exportable_impls( - self, + &self, tcx: TyCtxt<'_>, ) -> impl Iterator { self.root @@ -1528,30 +1514,25 @@ impl<'a> CrateMetadataRef<'a> { } fn exported_non_generic_symbols<'tcx>( - self, + &self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { tcx.arena.alloc_from_iter(self.root.exported_non_generic_symbols.decode((self, tcx))) } fn exported_generic_symbols<'tcx>( - self, + &self, tcx: TyCtxt<'tcx>, ) -> &'tcx [(ExportedSymbol<'tcx>, SymbolExportInfo)] { tcx.arena.alloc_from_iter(self.root.exported_generic_symbols.decode((self, tcx))) } - fn get_macro(self, tcx: TyCtxt<'_>, id: DefIndex) -> ast::MacroDef { + fn get_macro(&self, tcx: TyCtxt<'_>, id: DefIndex) -> ast::MacroDef { match self.def_kind(id) { DefKind::Macro(_) => { - let macro_rules = self.root.tables.is_macro_rules.get(self.cdata, id); - let body = self - .root - .tables - .macro_definition - .get(self.cdata, id) - .unwrap() - .decode((self, tcx)); + let macro_rules = self.root.tables.is_macro_rules.get(self, id); + let body = + self.root.tables.macro_definition.get(self, id).unwrap().decode((self, tcx)); ast::MacroDef { macro_rules, body: Box::new(body), eii_declaration: None } } _ => bug!(), @@ -1559,20 +1540,20 @@ impl<'a> CrateMetadataRef<'a> { } #[inline] - fn def_key(self, index: DefIndex) -> DefKey { + fn def_key(&self, index: DefIndex) -> DefKey { *self.def_key_cache.lock().entry(index).or_insert_with(|| { self.root.tables.def_keys.get(&self.blob, index).unwrap().decode(&self.blob) }) } // Returns the path leading to the thing with this `id`. - fn def_path(self, id: DefIndex) -> DefPath { + fn def_path(&self, id: DefIndex) -> DefPath { debug!("def_path(cnum={:?}, id={:?})", self.cnum, id); DefPath::make(self.cnum, id, |parent| self.def_key(parent)) } #[inline] - fn def_path_hash(self, index: DefIndex) -> DefPathHash { + fn def_path_hash(&self, index: DefIndex) -> DefPathHash { // This is a hack to workaround the fact that we can't easily encode/decode a Hash64 // into the FixedSizeEncoding, as Hash64 lacks a Default impl. A future refactor to // relax the Default restriction will likely fix this. @@ -1584,14 +1565,14 @@ impl<'a> CrateMetadataRef<'a> { } #[inline] - fn def_path_hash_to_def_index(self, hash: DefPathHash) -> Option { + fn def_path_hash_to_def_index(&self, hash: DefPathHash) -> Option { self.def_path_hash_map.def_path_hash_to_def_index(&hash) } - fn expn_hash_to_expn_id(self, tcx: TyCtxt<'_>, index_guess: u32, hash: ExpnHash) -> ExpnId { + fn expn_hash_to_expn_id(&self, tcx: TyCtxt<'_>, index_guess: u32, hash: ExpnHash) -> ExpnId { let index_guess = ExpnIndex::from_u32(index_guess); let old_hash = - self.root.expn_hashes.get(self.cdata, index_guess).map(|lazy| lazy.decode((self, tcx))); + self.root.expn_hashes.get(self, index_guess).map(|lazy| lazy.decode((self, tcx))); let index = if old_hash == Some(hash) { // Fast path: the expn and its index is unchanged from the @@ -1602,13 +1583,13 @@ impl<'a> CrateMetadataRef<'a> { // Slow path: We need to find out the new `DefIndex` of the provided // `DefPathHash`, if its still exists. This requires decoding every `DefPathHash` // stored in this crate. - let map = self.cdata.expn_hash_map.get_or_init(|| { + let map = self.expn_hash_map.get_or_init(|| { let end_id = self.root.expn_hashes.size() as u32; let mut map = UnhashMap::with_capacity_and_hasher(end_id as usize, Default::default()); for i in 0..end_id { let i = ExpnIndex::from_u32(i); - if let Some(hash) = self.root.expn_hashes.get(self.cdata, i) { + if let Some(hash) = self.root.expn_hashes.get(self, i) { map.insert(hash.decode((self, tcx)), i); } } @@ -1617,7 +1598,7 @@ impl<'a> CrateMetadataRef<'a> { map[&hash] }; - let data = self.root.expn_data.get(self.cdata, index).unwrap().decode((self, tcx)); + let data = self.root.expn_data.get(self, index).unwrap().decode((self, tcx)); rustc_span::hygiene::register_expn_id(self.cnum, index, data, hash) } @@ -1646,7 +1627,7 @@ impl<'a> CrateMetadataRef<'a> { /// /// Proc macro crates don't currently export spans, so this function does not have /// to work for them. - fn imported_source_file(self, tcx: TyCtxt<'_>, source_file_index: u32) -> ImportedSourceFile { + fn imported_source_file(&self, tcx: TyCtxt<'_>, source_file_index: u32) -> ImportedSourceFile { fn filter<'a>( tcx: TyCtxt<'_>, real_source_base_dir: &Option, @@ -1745,7 +1726,7 @@ impl<'a> CrateMetadataRef<'a> { } }; - let mut import_info = self.cdata.source_map_import_info.lock(); + let mut import_info = self.source_map_import_info.lock(); for _ in import_info.len()..=(source_file_index as usize) { import_info.push(None); } @@ -1754,7 +1735,7 @@ impl<'a> CrateMetadataRef<'a> { let source_file_to_import = self .root .source_map - .get(self.cdata, source_file_index) + .get(self, source_file_index) .expect("missing source file") .decode((self, tcx)); @@ -1855,32 +1836,32 @@ impl<'a> CrateMetadataRef<'a> { .clone() } - fn get_attr_flags(self, index: DefIndex) -> AttrFlags { - self.root.tables.attr_flags.get(self.cdata, index) + fn get_attr_flags(&self, index: DefIndex) -> AttrFlags { + self.root.tables.attr_flags.get(self, index) } - fn get_intrinsic(self, tcx: TyCtxt<'_>, index: DefIndex) -> Option { - self.root.tables.intrinsic.get(self.cdata, index).map(|d| d.decode((self, tcx))) + fn get_intrinsic(&self, tcx: TyCtxt<'_>, index: DefIndex) -> Option { + self.root.tables.intrinsic.get(self, index).map(|d| d.decode((self, tcx))) } - fn get_doc_link_resolutions(self, tcx: TyCtxt<'_>, index: DefIndex) -> DocLinkResMap { + fn get_doc_link_resolutions(&self, tcx: TyCtxt<'_>, index: DefIndex) -> DocLinkResMap { self.root .tables .doc_link_resolutions - .get(self.cdata, index) + .get(self, index) .expect("no resolutions for a doc link") .decode((self, tcx)) } fn get_doc_link_traits_in_scope( - self, + &self, tcx: TyCtxt<'_>, index: DefIndex, ) -> impl Iterator { self.root .tables .doc_link_traits_in_scope - .get(self.cdata, index) + .get(self, index) .expect("no traits in scope for a doc link") .decode((self, tcx)) } @@ -1889,7 +1870,6 @@ impl<'a> CrateMetadataRef<'a> { impl CrateMetadata { pub(crate) fn new( tcx: TyCtxt<'_>, - cstore: &CStore, blob: MetadataBlob, root: CrateRoot, raw_proc_macros: Option<&'static [ProcMacro]>, @@ -1934,14 +1914,12 @@ impl CrateMetadata { def_key_cache: Default::default(), }; - // Need `CrateMetadataRef` to decode `DefId`s in simplified types. - let cref = CrateMetadataRef { cdata: &cdata, cstore }; cdata.incoherent_impls = cdata .root .incoherent_impls - .decode((cref, tcx)) + .decode((&cdata, tcx)) .map(|incoherent_impls| { - (incoherent_impls.self_ty.decode((cref, tcx)), incoherent_impls.impls) + (incoherent_impls.self_ty.decode((&cdata, tcx)), incoherent_impls.impls) }) .collect(); @@ -2041,13 +2019,10 @@ impl CrateMetadata { &self, tcx: TyCtxt<'_>, krate: CrateNum, - cstore: &CStore, ) -> impl Iterator { gen move { for def_id in self.root.proc_macro_data.as_ref().into_iter().flat_map(move |data| { - data.macros - .decode((CrateMetadataRef { cdata: self, cstore }, tcx)) - .map(move |index| DefId { index, krate }) + data.macros.decode((self, tcx)).map(move |index| DefId { index, krate }) }) { yield def_id; } diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 3e63e953e4469..a00fb59963ac2 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -100,7 +100,7 @@ macro_rules! provide_one { .root .tables .$name - .get($cdata.cdata, $def_id.index) + .get($cdata, $def_id.index) .map(|lazy| lazy.decode(($cdata, $tcx))) .process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name))) } @@ -109,7 +109,7 @@ macro_rules! provide_one { ($tcx:ident, $def_id:ident, $other:ident, $cdata:ident, $name:ident => { table_defaulted_array }) => { provide_one! { $tcx, $def_id, $other, $cdata, $name => { - let lazy = $cdata.root.tables.$name.get($cdata.cdata, $def_id.index); + let lazy = $cdata.root.tables.$name.get($cdata, $def_id.index); let value = if lazy.is_default() { &[] as &[_] } else { @@ -127,7 +127,7 @@ macro_rules! provide_one { .root .tables .$name - .get($cdata.cdata, $def_id.index) + .get($cdata, $def_id.index) .process_decoded($tcx, || panic!("{:?} does not have a {:?}", $def_id, stringify!($name))) } } @@ -259,7 +259,7 @@ provide! { tcx, def_id, other, cdata, .root .tables .coerce_unsized_info - .get(cdata.cdata, def_id.index) + .get(cdata, def_id.index) .map(|lazy| lazy.decode((cdata, tcx))) .process_decoded(tcx, || panic!("{def_id:?} does not have coerce_unsized_info"))) } mir_const_qualif => { table } @@ -275,7 +275,7 @@ provide! { tcx, def_id, other, cdata, .root .tables .eval_static_initializer - .get(cdata.cdata, def_id.index) + .get(cdata, def_id.index) .map(|lazy| lazy.decode((cdata, tcx))) .unwrap_or_else(|| panic!("{def_id:?} does not have eval_static_initializer"))) } @@ -288,7 +288,7 @@ provide! { tcx, def_id, other, cdata, .root .tables .deduced_param_attrs - .get(cdata.cdata, def_id.index) + .get(cdata, def_id.index) .map(|lazy| { &*tcx.arena.alloc_from_iter(lazy.decode((cdata, tcx))) }) @@ -301,7 +301,7 @@ provide! { tcx, def_id, other, cdata, .root .tables .trait_impl_trait_tys - .get(cdata.cdata, def_id.index) + .get(cdata, def_id.index) .map(|lazy| lazy.decode((cdata, tcx))) .process_decoded(tcx, || panic!("{def_id:?} does not have trait_impl_trait_tys"))) } @@ -399,7 +399,9 @@ provide! { tcx, def_id, other, cdata, debugger_visualizers => { cdata.get_debugger_visualizers(tcx) } exportable_items => { tcx.arena.alloc_from_iter(cdata.get_exportable_items(tcx)) } - stable_order_of_exportable_impls => { tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls(tcx).collect()) } + stable_order_of_exportable_impls => { + tcx.arena.alloc(cdata.get_stable_order_of_exportable_impls(tcx).collect()) + } exported_non_generic_symbols => { cdata.exported_non_generic_symbols(tcx) } exported_generic_symbols => { cdata.exported_generic_symbols(tcx) } @@ -590,16 +592,16 @@ impl CStore { let sess = tcx.sess; let _prof_timer = sess.prof.generic_activity("metadata_load_macro"); - let data = self.get_crate_data(id.krate); - if data.root.is_proc_macro_crate() { - LoadedMacro::ProcMacro(data.load_proc_macro(tcx, id.index)) + let cdata = self.get_crate_data(id.krate); + if cdata.root.is_proc_macro_crate() { + LoadedMacro::ProcMacro(cdata.load_proc_macro(tcx, id.index)) } else { LoadedMacro::MacroDef { - def: data.get_macro(tcx, id.index), - ident: data.item_ident(tcx, id.index), - attrs: data.get_item_attrs(tcx, id.index).collect(), - span: data.get_span(tcx, id.index), - edition: data.root.edition, + def: cdata.get_macro(tcx, id.index), + ident: cdata.item_ident(tcx, id.index), + attrs: cdata.get_item_attrs(tcx, id.index).collect(), + span: cdata.get_span(tcx, id.index), + edition: cdata.root.edition, } } } @@ -641,10 +643,10 @@ impl CStore { } pub fn set_used_recursively(&mut self, cnum: CrateNum) { - let cmeta = self.get_crate_data_mut(cnum); - if !cmeta.used { - cmeta.used = true; - let cnum_map = mem::take(&mut cmeta.cnum_map); + let cdata = self.get_crate_data_mut(cnum); + if !cdata.used { + cdata.used = true; + let cnum_map = mem::take(&mut cdata.cnum_map); for &dep_cnum in cnum_map.iter() { self.set_used_recursively(dep_cnum); } @@ -676,11 +678,11 @@ impl CStore { cnum: CrateNum, extern_crate: ExternCrate, ) { - let cmeta = self.get_crate_data_mut(cnum); - if cmeta.update_extern_crate_diagnostics(extern_crate) { + let cdata = self.get_crate_data_mut(cnum); + if cdata.update_extern_crate_diagnostics(extern_crate) { // Propagate the extern crate info to dependencies if it was updated. let extern_crate = ExternCrate { dependency_of: cnum, ..extern_crate }; - let cnum_map = mem::take(&mut cmeta.cnum_map); + let cnum_map = mem::take(&mut cdata.cnum_map); for &dep_cnum in cnum_map.iter() { self.update_transitive_extern_crate_diagnostics(dep_cnum, extern_crate); } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 781d3c6d18372..c7b2eaa15ebfb 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -45,7 +45,6 @@ use rustc_span::{self, ExpnData, ExpnHash, ExpnId, Ident, Span, Symbol}; use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; -use crate::creader::CrateMetadataRef; use crate::eii::EiiMapEncodedKeyValue; mod decoder; @@ -317,13 +316,9 @@ impl From for RawDefId { impl RawDefId { /// This exists so that `provide_one!` is happy - fn decode(self, meta: (CrateMetadataRef<'_>, TyCtxt<'_>)) -> DefId { - self.decode_from_cdata(meta.0) - } - - fn decode_from_cdata(self, cdata: CrateMetadataRef<'_>) -> DefId { + fn decode(self, meta: (&CrateMetadata, TyCtxt<'_>)) -> DefId { let krate = CrateNum::from_u32(self.krate); - let krate = cdata.map_encoded_cnum_to_current(krate); + let krate = meta.0.map_encoded_cnum_to_current(krate); DefId { krate, index: DefIndex::from_u32(self.index) } } } From 70fe8a6dc4a903bae3f630ac1dcc5cd27faa9e02 Mon Sep 17 00:00:00 2001 From: Sidney Cammeresi Date: Wed, 22 Apr 2026 21:21:55 -0700 Subject: [PATCH 11/14] Add `Sender` diagnostic item for `std::sync::mpsc::Sender` Similar to the existing `Receiver` item, it will be used in Clippy to detect uses of `is_disconnected` that are racy. --- library/std/src/sync/mpsc.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/std/src/sync/mpsc.rs b/library/std/src/sync/mpsc.rs index a1c49bb83010c..460ad02c67d2c 100644 --- a/library/std/src/sync/mpsc.rs +++ b/library/std/src/sync/mpsc.rs @@ -330,6 +330,7 @@ pub struct IntoIter { /// assert_eq!(3, msg + msg2); /// ``` #[stable(feature = "rust1", since = "1.0.0")] +#[cfg_attr(not(test), rustc_diagnostic_item = "MpscSender")] pub struct Sender { inner: mpmc::Sender, } From bcb1af095ed973da0f9dfb3c5f759707f0e66113 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Wed, 22 Apr 2026 14:11:19 +1000 Subject: [PATCH 12/14] Forbid `*-pass` and `*-fail` directives in tests/crashes Crash tests are always expected to crash during compilation, so there is no sensible meaning for specifying a pass/fail expectation in a crash test. --- src/doc/rustc-dev-guide/src/tests/directives.md | 16 ++++++++-------- src/tools/compiletest/src/directives.rs | 4 +--- src/tools/compiletest/src/runtest/crashes.rs | 5 ++--- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index d536d324cb2bf..38450d991d05a 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -70,17 +70,17 @@ See [Controlling pass/fail expectations](ui.md#controlling-passfail-expectations | Directive | Explanation | Supported test suites | Possible values | |-----------------------------|---------------------------------------------|-------------------------------------------|-----------------| -| `check-pass` | Building (no codegen) should pass | `ui`, `crashes` | N/A | -| `check-fail` | Building (no codegen) should fail | `ui`, `crashes` | N/A | -| `build-pass` | Building should pass | `ui`, `crashes`, `codegen` | N/A | -| `build-fail` | Building should fail | `ui`, `crashes` | N/A | -| `run-pass` | Program must exit with code `0` | `ui`, `crashes` | N/A | -| `run-fail` | Program must exit with code `1..=127` | `ui`, `crashes` | N/A | +| `check-pass` | Building (no codegen) should pass | `ui` | N/A | +| `check-fail` | Building (no codegen) should fail | `ui` | N/A | +| `build-pass` | Building should pass | `ui` | N/A | +| `build-fail` | Building should fail | `ui` | N/A | +| `run-pass` | Program must exit with code `0` | `ui` | N/A | +| `run-fail` | Program must exit with code `1..=127` | `ui` | N/A | | `run-crash` | Program must crash | `ui` | N/A | | `run-fail-or-crash` | Program must `run-fail` or `run-crash` | `ui` | N/A | -| `ignore-pass` | Ignore `--pass` flag | `ui`, `crashes`, `codegen`, `incremental` | N/A | +| `ignore-pass` | Ignore `--pass` flag | `ui` | N/A | | `dont-check-failure-status` | Don't check exact failure status (i.e. `1`) | `ui`, `incremental` | N/A | -| `failure-status` | On failure, the compiler must exit with this status code. To expect an ICE, use `//@ failure-status: 101`. | `ui`, `crashes`, `incremental` | Any `u16` | +| `failure-status` | On failure, the compiler must exit with this status code. To expect an ICE, use `//@ failure-status: 101`. | `ui`, `incremental` | Any `u16` | | `should-fail` | Compiletest self-test | All | N/A | ### Controlling output snapshots and normalizations diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index d87cb915b07b8..0575285af7a43 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -408,8 +408,7 @@ impl TestProps { fn update_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { let check_ui = |mode: &str| { - // Mode::Crashes may need build-fail in order to trigger llvm errors or stack overflows - if config.mode != TestMode::Ui && config.mode != TestMode::Crashes { + if config.mode != TestMode::Ui { panic!("`{}-fail` directive is only supported in UI tests", mode); } }; @@ -441,7 +440,6 @@ impl TestProps { fn update_pass_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { let check_no_run = |s| match (config.mode, s) { (TestMode::Ui, _) => (), - (TestMode::Crashes, _) => (), (mode, _) => panic!("`{s}` directive is not supported in `{mode}` tests"), }; let pass_mode = if config.parse_name_directive(ln, "check-pass") { diff --git a/src/tools/compiletest/src/runtest/crashes.rs b/src/tools/compiletest/src/runtest/crashes.rs index 0aae7eaa39cd5..210ab4dd05a71 100644 --- a/src/tools/compiletest/src/runtest/crashes.rs +++ b/src/tools/compiletest/src/runtest/crashes.rs @@ -1,9 +1,8 @@ -use super::{TestCx, WillExecute}; +use super::{Emit, TestCx, WillExecute}; impl TestCx<'_> { pub(super) fn run_crash_test(&self) { - let pm = self.pass_mode(); - let proc_res = self.compile_test(WillExecute::No, self.should_emit_metadata(pm)); + let proc_res = self.compile_test(WillExecute::No, Emit::None); if std::env::var("COMPILETEST_VERBOSE_CRASHES").is_ok() { writeln!(self.stderr, "{}", proc_res.status); From 4b1f3926deb3d6b508ef3dc3985ff0fe417e417b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 24 Apr 2026 03:04:03 +0000 Subject: [PATCH 13/14] Avoid query cycles in DataflowConstProp * Avoid query cycles in DataflowConstProp * Add -Zmir-opt-level=0 to the test --- .../rustc_mir_transform/src/dataflow_const_prop.rs | 5 +++++ tests/ui/dataflow_const_prop/recursive-async.rs | 11 +++++++++++ 2 files changed, 16 insertions(+) create mode 100644 tests/ui/dataflow_const_prop/recursive-async.rs diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 122429276e3c5..a2df3dcb85acf 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -41,6 +41,11 @@ impl<'tcx> crate::MirPass<'tcx> for DataflowConstProp { #[instrument(skip_all level = "debug")] fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + // Avoid query cycles from coroutines. + if body.coroutine.is_some() { + return; + } + debug!(def_id = ?body.source.def_id()); if tcx.sess.mir_opt_level() < 4 && body.basic_blocks.len() > BLOCK_LIMIT { debug!("aborted dataflow const prop due too many basic blocks"); diff --git a/tests/ui/dataflow_const_prop/recursive-async.rs b/tests/ui/dataflow_const_prop/recursive-async.rs new file mode 100644 index 0000000000000..f2c194c6ca3ff --- /dev/null +++ b/tests/ui/dataflow_const_prop/recursive-async.rs @@ -0,0 +1,11 @@ +//! Ensure DataflowConstProp doesn't cause an error with async recursion as in #155376. + +//@ edition:2018 +//@ check-pass +//@ compile-flags: -Zmir-opt-level=0 -Zmir-enable-passes=+DataflowConstProp --crate-type=lib + +pub async fn foo(n: usize) { + if n > 0 { + Box::pin(foo(n - 1)).await; + } +} From 7ba9478184436b9627178b61071d2b9ff9acb81c Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Thu, 23 Apr 2026 21:41:59 +1000 Subject: [PATCH 14/14] Implement `Read`/`Write`/`Seek` for `Arc` Added a marker trait `IoHandle` which can be used by the standard library to opt-in types to a blanket implementation of the various IO traits on `Arc` where `&T: IoTrait` for some `IoTrait`. The marker is required to avoid types like `Arc<[u8]>` being included, since they don't have interior mutability and would not give expected results. --- library/std/src/fs.rs | 54 +--------------- library/std/src/io/impls.rs | 120 ++++++++++++++++++++++++++++++++++++ library/std/src/io/mod.rs | 15 +++++ 3 files changed, 136 insertions(+), 53 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index c75f005f18021..fab695c1c5e1f 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -45,7 +45,6 @@ use crate::ffi::OsString; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; use crate::path::{Path, PathBuf}; use crate::sealed::Sealed; -use crate::sync::Arc; use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, fs as fs_imp}; use crate::time::SystemTime; use crate::{error, fmt}; @@ -1541,58 +1540,7 @@ impl Seek for File { (&*self).stream_position() } } - -#[stable(feature = "io_traits_arc", since = "1.73.0")] -impl Read for Arc { - fn read(&mut self, buf: &mut [u8]) -> io::Result { - (&**self).read(buf) - } - fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { - (&**self).read_vectored(bufs) - } - fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { - (&**self).read_buf(cursor) - } - #[inline] - fn is_read_vectored(&self) -> bool { - (&**self).is_read_vectored() - } - fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { - (&**self).read_to_end(buf) - } - fn read_to_string(&mut self, buf: &mut String) -> io::Result { - (&**self).read_to_string(buf) - } -} -#[stable(feature = "io_traits_arc", since = "1.73.0")] -impl Write for Arc { - fn write(&mut self, buf: &[u8]) -> io::Result { - (&**self).write(buf) - } - fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { - (&**self).write_vectored(bufs) - } - #[inline] - fn is_write_vectored(&self) -> bool { - (&**self).is_write_vectored() - } - #[inline] - fn flush(&mut self) -> io::Result<()> { - (&**self).flush() - } -} -#[stable(feature = "io_traits_arc", since = "1.73.0")] -impl Seek for Arc { - fn seek(&mut self, pos: SeekFrom) -> io::Result { - (&**self).seek(pos) - } - fn stream_len(&mut self) -> io::Result { - (&**self).stream_len() - } - fn stream_position(&mut self) -> io::Result { - (&**self).stream_position() - } -} +impl crate::io::IoHandle for File {} impl Dir { /// Attempts to open a directory at `path` in read-only mode. diff --git a/library/std/src/io/impls.rs b/library/std/src/io/impls.rs index d0245f3d4984c..f0b7764b4cc5e 100644 --- a/library/std/src/io/impls.rs +++ b/library/std/src/io/impls.rs @@ -4,6 +4,7 @@ mod tests; use crate::alloc::Allocator; use crate::collections::VecDeque; use crate::io::{self, BorrowedCursor, BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write}; +use crate::sync::Arc; use crate::{cmp, fmt, mem, str}; // ============================================================================= @@ -715,3 +716,122 @@ impl<'a> io::Write for core::io::BorrowedCursor<'a> { Ok(()) } } + +#[stable(feature = "io_traits_arc", since = "1.73.0")] +impl Read for Arc +where + for<'a> &'a R: Read, + R: crate::io::IoHandle, +{ + #[inline] + fn read(&mut self, buf: &mut [u8]) -> io::Result { + (&**self).read(buf) + } + + #[inline] + fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + (&**self).read_buf(cursor) + } + + #[inline] + fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result { + (&**self).read_vectored(bufs) + } + + #[inline] + fn is_read_vectored(&self) -> bool { + (&**self).is_read_vectored() + } + + #[inline] + fn read_to_end(&mut self, buf: &mut Vec) -> io::Result { + (&**self).read_to_end(buf) + } + + #[inline] + fn read_to_string(&mut self, buf: &mut String) -> io::Result { + (&**self).read_to_string(buf) + } + + #[inline] + fn read_exact(&mut self, buf: &mut [u8]) -> io::Result<()> { + (&**self).read_exact(buf) + } + + #[inline] + fn read_buf_exact(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> { + (&**self).read_buf_exact(cursor) + } +} +#[stable(feature = "io_traits_arc", since = "1.73.0")] +impl Write for Arc +where + for<'a> &'a W: Write, + W: crate::io::IoHandle, +{ + #[inline] + fn write(&mut self, buf: &[u8]) -> io::Result { + (&**self).write(buf) + } + + #[inline] + fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result { + (&**self).write_vectored(bufs) + } + + #[inline] + fn is_write_vectored(&self) -> bool { + (&**self).is_write_vectored() + } + + #[inline] + fn flush(&mut self) -> io::Result<()> { + (&**self).flush() + } + + #[inline] + fn write_all(&mut self, buf: &[u8]) -> io::Result<()> { + (&**self).write_all(buf) + } + + #[inline] + fn write_all_vectored(&mut self, bufs: &mut [IoSlice<'_>]) -> io::Result<()> { + (&**self).write_all_vectored(bufs) + } + + #[inline] + fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> io::Result<()> { + (&**self).write_fmt(fmt) + } +} +#[stable(feature = "io_traits_arc", since = "1.73.0")] +impl Seek for Arc +where + for<'a> &'a S: Seek, + S: crate::io::IoHandle, +{ + #[inline] + fn seek(&mut self, pos: SeekFrom) -> io::Result { + (&**self).seek(pos) + } + + #[inline] + fn rewind(&mut self) -> io::Result<()> { + (&**self).rewind() + } + + #[inline] + fn stream_len(&mut self) -> io::Result { + (&**self).stream_len() + } + + #[inline] + fn stream_position(&mut self) -> io::Result { + (&**self).stream_position() + } + + #[inline] + fn seek_relative(&mut self, offset: i64) -> io::Result<()> { + (&**self).seek_relative(offset) + } +} diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs index 1166ba8baf430..934d4bd684034 100644 --- a/library/std/src/io/mod.rs +++ b/library/std/src/io/mod.rs @@ -2226,6 +2226,21 @@ pub enum SeekFrom { Current(#[stable(feature = "rust1", since = "1.0.0")] i64), } +/// Marks that a type `T` can have IO traits such as [`Seek`], [`Write`], etc. automatically +/// implemented for handle types like [`Arc`][arc] as well. +/// +/// This trait should only be implemented for types where `<&T as Trait>::method(&mut &value, ..)` +/// would be identical to `::method(&mut value, ..)`. +/// +/// [`File`][file] passes this test, as operations on `&File` and `File` both affect +/// the same underlying file. +/// `[u8]` fails, because any modification to `&mut &[u8]` would only affect a temporary +/// and be lost after the method has been called. +/// +/// [file]: crate::fs::File +/// [arc]: crate::sync::Arc +pub(crate) trait IoHandle {} + fn read_until(r: &mut R, delim: u8, buf: &mut Vec) -> Result { let mut read = 0; loop {