From 5eae716fb9876a7f6672dacdb0d44728e893fcb2 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Mon, 20 Apr 2026 10:39:00 +0400 Subject: [PATCH 01/17] docs(unstable-book): Document const generics features --- .../language-features/generic-const-args.md | 37 ++++++ .../language-features/generic-const-exprs.md | 73 ++++++++++++ .../language-features/generic-const-items.md | 59 ++++++++++ .../min-generic-const-args.md | 110 ++++++++++++++++++ 4 files changed, 279 insertions(+) create mode 100644 src/doc/unstable-book/src/language-features/generic-const-args.md create mode 100644 src/doc/unstable-book/src/language-features/generic-const-exprs.md create mode 100644 src/doc/unstable-book/src/language-features/generic-const-items.md create mode 100644 src/doc/unstable-book/src/language-features/min-generic-const-args.md diff --git a/src/doc/unstable-book/src/language-features/generic-const-args.md b/src/doc/unstable-book/src/language-features/generic-const-args.md new file mode 100644 index 0000000000000..b9870e60d0f91 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/generic-const-args.md @@ -0,0 +1,37 @@ +# generic_const_args + +Allows using generics in more complex const expressions, based on definitional equality. + +The tracking issue for this feature is: [#151972] + +[#151972]: https://github.com/rust-lang/rust/issues/151972 + +------------------------ + +Warning: This feature is incomplete; its design and syntax may change. + +This feature enables many of the same use cases supported by [generic_const_exprs], +but based on the machinery developed for [min_generic_const_args]. In a way, it is +meant to be an interim successor for GCE (though it might not currently support all +the valid cases that supported by GCE). + +See also: [generic_const_items] + +[min_generic_const_args]: min-generic-const-args.md +[generic_const_exprs]: generic-const-exprs.md +[generic_const_items]: generic-const-items.md + +## Examples + +```rust +#![feature(generic_const_items)] +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +#![expect(incomplete_features)] + +type const ADD1: usize = const { N + 1 }; + +type const INC: usize = ADD1::; + +const ARR: [(); ADD1::<0>] = [(); INC::<0>]; +``` diff --git a/src/doc/unstable-book/src/language-features/generic-const-exprs.md b/src/doc/unstable-book/src/language-features/generic-const-exprs.md new file mode 100644 index 0000000000000..2085ed8fed0cc --- /dev/null +++ b/src/doc/unstable-book/src/language-features/generic-const-exprs.md @@ -0,0 +1,73 @@ +# generic_const_exprs + +Allows non-trivial generic constants which have to be shown to successfully evaluate +to a value by being part of an item signature. + +The tracking issue for this feature is: [#76560] + + +[#76560]: https://github.com/rust-lang/rust/issues/76560 + +------------------------ + +Warning: This feature is incomplete; its design and syntax may change. + +See also: [min_generic_const_args], [generic_const_args] + +[min_generic_const_args]: min-generic-const-args.md +[generic_const_args]: generic-const-args.md + +## Examples + +```rust +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +// Use parameters that depend on a generic argument. +struct Foo +where + [(); N + 1]:, +{ + array: [usize; N + 1], +} + +// Use generic parameters in const operations. +trait Bar { + const X: usize; + const Y: usize; +} + +// Note `B::X * B::Y`. +const fn baz(x: [usize; B::X], y: [usize; B::Y]) -> [usize; B::X * B::Y] { + let mut out = [0; B::X * B::Y]; + let mut i = 0; + while i < B::Y { + let mut j = 0; + while j < B::X { + out[i * B::X + j] = y[i].saturating_mul(x[j]); + j += 1; + } + i += 1; + } + out +} + + +// Create a new type based on a generic argument. +pub struct Grow { + arr: [usize; N], +} + +impl Grow { + pub const fn grow(self, val: usize) -> Grow<{ N + 1 }> { + let mut new_arr = [0; { N + 1 }]; + let mut idx = 0; + while idx < N { + new_arr[idx] = self.arr[idx]; + idx += 1; + } + new_arr[N] = val; + Grow { arr: new_arr } + } +} +``` diff --git a/src/doc/unstable-book/src/language-features/generic-const-items.md b/src/doc/unstable-book/src/language-features/generic-const-items.md new file mode 100644 index 0000000000000..dc267d0225c87 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/generic-const-items.md @@ -0,0 +1,59 @@ +# generic_const_items + +Allows generic parameters and where-clauses on free & associated const items. + +The tracking issue for this feature is: [#113521] + +[#113521]: https://github.com/rust-lang/rust/issues/113521 + +------------------------ + +Warning: This feature is an [experiment] and lacks an RFC. +There are no guarantees that it will ever be stabilized. + +See also: [generic_const_exprs], [min_generic_const_args]. + +[experiment]: https://lang-team.rust-lang.org/how_to/experiment.html +[generic_const_exprs]: generic-const-exprs.md +[min_generic_const_args]: min-generic-const-args.md + +## Examples + +### Generic constant values + +```rust +#![allow(incomplete_features)] +#![feature(generic_const_items)] + +const GENERIC_VAL: usize = const { ARG + 1 }; + +#[test] +fn generic_const_arg() { + assert_eq!(GENERIC_VAL::<1>, 2); + assert_eq!(GENERIC_VAL::<2>, 3); +} +``` + +### Conditional constants + +```rust +#![allow(incomplete_features)] +#![feature(generic_const_items)] + +// `GENERIC_VAL::<0>` will fail to compile +const GENERIC_VAL: usize = const { + if ARG > 0 { + ARG + 1 + } else { + panic!("0 value") + } +}; + +// Will fail to compile if the `Copy` derive is removed. +const COPY_MARKER: () = (); + +#[derive(Clone, Copy)] +struct Foo; + +const FOO_IS_COPY: () = COPY_MARKER::; +``` diff --git a/src/doc/unstable-book/src/language-features/min-generic-const-args.md b/src/doc/unstable-book/src/language-features/min-generic-const-args.md new file mode 100644 index 0000000000000..336b6a420c2d6 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/min-generic-const-args.md @@ -0,0 +1,110 @@ +# min_generic_const_args + +Enables the generic const args MVP (paths to type const items and constructors for ADTs and primitives). + +The tracking issue for this feature is: [#132980] + +[#132980]: https://github.com/rust-lang/rust/issues/132980 + +------------------------ + +Warning: This feature is incomplete; its design and syntax may change. + +This feature acts as a minimal alternative to [generic_const_exprs] that allows a smaller subset of functionality, +and uses a different approach for implementation. It is intentionally more restrictive, which helps with avoiding edge +cases that make the `generic_const_exprs` hard to implement properly. See [Feature background][feature_background] +for more details. + +Related features: [generic_const_args], [generic_const_items]. + +[feature_background]: https://github.com/rust-lang/project-const-generics/blob/main/documents/min_const_generics_plan.md +[generic_const_exprs]: generic-const-exprs.md +[generic_const_args]: generic-const-args.md +[generic_const_items]: generic-const-items.md + +## `type const` syntax + +This feature introduces new syntax: `type const`. +Constants marked as `type const` are allowed to be used in type contexts, e.g.: + +```compile_fail +#![allow(incomplete_features)] +#![feature(min_generic_const_args)] + +type const X: usize = 1; +const Y: usize = 1; + +struct Foo { + good_arr: [(); X], // Allowed + bad_arr: [(); Y], // Will not compile, `Y` must be `type const`. +} +``` + +## Examples + +```rust +#![allow(incomplete_features)] +#![feature(min_generic_const_args)] + +trait Bar { + type const VAL: usize; + type const VAL2: usize; +} + +struct Baz; + +impl Bar for Baz { + type const VAL: usize = 2; + type const VAL2: usize = const { Self::VAL * 2 }; +} + +struct Foo { + arr1: [usize; B::VAL], + arr2: [usize; B::VAL2], +} +``` + +Note that with [generic_const_exprs] the same example would look as follows: + +```rust +#![allow(incomplete_features)] +#![feature(generic_const_exprs)] + +trait Bar { + const VAL: usize; + const VAL2: usize; +} + +struct Baz; + +impl Bar for Baz { + const VAL: usize = 2; + const VAL2: usize = const { Self::VAL * 2 }; +} + +struct Foo +where + [(); B::VAL]:, + [(); B::VAL2]:, +{ + arr1: [usize; B::VAL], + arr2: [usize; B::VAL2], +} +``` + +Use of const functions is allowed: + +```rust +#![allow(incomplete_features)] +#![feature(min_generic_const_args)] + +const VAL: usize = 1; + +const fn inc(val: usize) -> usize { + val + 1 +} + +type const INC: usize = const { inc(VAL) }; + +const ARR: [usize; INC] = [0; INC]; +``` From 6315e1799b92cd25e57f664cbaff8ab3f2f25504 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Mon, 20 Apr 2026 18:13:48 +0400 Subject: [PATCH 02/17] Update unstable feature descriptions (min_generic_const_args, generic_const_exprs) --- compiler/rustc_feature/src/unstable.rs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1785014954093..bc1ae7c0cde2c 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -528,7 +528,8 @@ declare_features! ( (unstable, gen_blocks, "1.75.0", Some(117078)), /// Allows using generics in more complex const expressions, based on definitional equality. (unstable, generic_const_args, "1.95.0", Some(151972)), - /// Allows non-trivial generic constants which have to have wfness manually propagated to callers + /// Allows non-trivial generic constants which have to be shown to successfully evaluate + /// to a value by being part of an item signature. (incomplete, generic_const_exprs, "1.56.0", Some(76560)), /// Allows generic parameters and where-clauses on free & associated const items. (incomplete, generic_const_items, "1.73.0", Some(113521)), @@ -590,7 +591,8 @@ declare_features! ( /// Allows additional const parameter types, such as [u8; 10] or user defined types. /// User defined types must not have fields more private than the type itself. (unstable, min_adt_const_params, "1.96.0", Some(154042)), - /// Enables the generic const args MVP (only bare paths, not arbitrary computation). + /// Enables the generic const args MVP (paths to type const items and constructors + /// for ADTs and primitives). (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization From 73e44e82cee7894ba18455d89e707e1f977431bc Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Mon, 20 Apr 2026 18:15:06 +0400 Subject: [PATCH 03/17] Change generic_const_args feature from unstable to incomplete --- compiler/rustc_feature/src/unstable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index bc1ae7c0cde2c..ff2baf30e1c88 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -527,7 +527,7 @@ declare_features! ( /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), /// Allows using generics in more complex const expressions, based on definitional equality. - (unstable, generic_const_args, "1.95.0", Some(151972)), + (incomplete, generic_const_args, "1.95.0", Some(151972)), /// Allows non-trivial generic constants which have to be shown to successfully evaluate /// to a value by being part of an item signature. (incomplete, generic_const_exprs, "1.56.0", Some(76560)), From c4eb1bf1d2394741509cef6199eacd7c4c1593b0 Mon Sep 17 00:00:00 2001 From: Igor Aleksanov Date: Thu, 23 Apr 2026 07:33:08 +0400 Subject: [PATCH 04/17] Do not use `const { }` blocks for GCI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: León Orell Valerian Liehr --- .../src/language-features/generic-const-items.md | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/doc/unstable-book/src/language-features/generic-const-items.md b/src/doc/unstable-book/src/language-features/generic-const-items.md index dc267d0225c87..c856c9f135aff 100644 --- a/src/doc/unstable-book/src/language-features/generic-const-items.md +++ b/src/doc/unstable-book/src/language-features/generic-const-items.md @@ -25,7 +25,7 @@ See also: [generic_const_exprs], [min_generic_const_args]. #![allow(incomplete_features)] #![feature(generic_const_items)] -const GENERIC_VAL: usize = const { ARG + 1 }; +const GENERIC_VAL: usize = ARG + 1; #[test] fn generic_const_arg() { @@ -41,13 +41,7 @@ fn generic_const_arg() { #![feature(generic_const_items)] // `GENERIC_VAL::<0>` will fail to compile -const GENERIC_VAL: usize = const { - if ARG > 0 { - ARG + 1 - } else { - panic!("0 value") - } -}; +const GENERIC_VAL: usize = if ARG > 0 { ARG + 1 } else { panic!("0 value") }; // Will fail to compile if the `Copy` derive is removed. const COPY_MARKER: () = (); From 2aeb041abadf867c1719784df8e0a7a353e2f9e5 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Mon, 27 Apr 2026 09:31:08 +1000 Subject: [PATCH 05/17] Revert documentation changes from 08bd077 These changes were made falsely assuming documentation links from `core` to `std` were not possible. Since it is possible, we can restore the documentation to its original form prior to the `core::io` move. --- library/core/src/io/error.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/library/core/src/io/error.rs b/library/core/src/io/error.rs index fe12de2952f0a..e14ec856d9691 100644 --- a/library/core/src/io/error.rs +++ b/library/core/src/io/error.rs @@ -7,6 +7,10 @@ use crate::fmt; /// This list is intended to grow over time and it is not recommended to /// exhaustively match against it. /// +/// It is used with the [`io::Error`][error] type. +/// +/// [error]: ../../std/io/struct.Error.html +/// /// # Handling errors and matching on `ErrorKind` /// /// In application code, use `match` for the `ErrorKind` values you are @@ -121,12 +125,13 @@ pub enum ErrorKind { #[stable(feature = "rust1", since = "1.0.0")] TimedOut, /// An error returned when an operation could not be completed because a - /// call to an underlying writer returned [`Ok(0)`]. + /// call to [`write`][write] returned [`Ok(0)`]. /// /// This typically means that an operation could only succeed if it wrote a /// particular number of bytes but only a smaller number of bytes could be /// written. /// + /// [write]: ../../std/io/trait.Write.html#tymethod.write /// [`Ok(0)`]: Ok #[stable(feature = "rust1", since = "1.0.0")] WriteZero, @@ -225,7 +230,7 @@ pub enum ErrorKind { // /// A custom error that does not fall under any other I/O error kind. /// - /// This can be used to construct your own errors that do not match any + /// This can be used to construct your own [`Error`][error]s that do not match any /// [`ErrorKind`]. /// /// This [`ErrorKind`] is not used by the standard library. @@ -233,6 +238,8 @@ pub enum ErrorKind { /// Errors from the standard library that do not fall under any of the I/O /// error kinds cannot be `match`ed on, and will only match a wildcard (`_`) pattern. /// New [`ErrorKind`]s might be added in the future for some of those. + /// + /// [error]: ../../std/io/struct.Error.html #[stable(feature = "rust1", since = "1.0.0")] Other, @@ -365,7 +372,15 @@ impl ErrorKind { #[stable(feature = "io_errorkind_display", since = "1.60.0")] impl fmt::Display for ErrorKind { - /// Shows a human-readable description of the `ErrorKind`. + /// Shows a human-readable description of the [`ErrorKind`]. + /// + /// This is similar to `impl Display for Error`, but doesn't require first converting to Error. + /// + /// # Examples + /// ``` + /// use core::io::ErrorKind; + /// assert_eq!("entity not found", ErrorKind::NotFound.to_string()); + /// ``` fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { fmt.write_str(self.as_str()) } From 69cc5fa4b0ff22c298a3c39649ce4a6fd8b93837 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Mon, 27 Apr 2026 03:28:16 +0000 Subject: [PATCH 06/17] Remove unnecessary `get_unchecked` My benchmarking did not show any issue with using the safe method instead so I assume this isn't an issue any more. But let's do a perf run to be sure. --- library/core/src/str/lossy.rs | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs index d2dc650910f63..18ad28f8f3b97 100644 --- a/library/core/src/str/lossy.rs +++ b/library/core/src/str/lossy.rs @@ -211,12 +211,7 @@ impl<'a> Iterator for Utf8Chunks<'a> { let mut i = 0; let mut valid_up_to = 0; - while i < self.source.len() { - // SAFETY: `i < self.source.len()` per previous line. - // For some reason the following are both significantly slower: - // while let Some(&byte) = self.source.get(i) { - // while let Some(byte) = self.source.get(i).copied() { - let byte = unsafe { *self.source.get_unchecked(i) }; + while let Some(byte) = self.source.get(i).copied() { i += 1; if byte < 128 { From b9499e0e9773e0c60931e2db9162912d289e892f Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Sat, 2 May 2026 08:45:06 +0100 Subject: [PATCH 07/17] move associated type tests out of issues --- .../ambiguous-associated-type-default.rs | 9 ++ .../ambiguous-associated-type-default.stderr | 14 +++ ...soc-type-add-output-via-operator-syntax.rs | 10 ++ ...-type-default-without-override-in-impl.rs} | 0 .../assoc-type-element-mismatch-in-hrtb.rs} | 0 ...ssoc-type-element-mismatch-in-hrtb.stderr} | 0 .../assoc-type-in-extern-fn-signature.rs} | 0 .../assoc-type-in-generic-struct-bound.rs | 13 +++ ...assoc-type-in-strategy-pattern-iterator.rs | 93 +++++++++++++++++++ .../assoc-type-in-struct-constructor.rs | 12 +++ .../assoc-type-in-unused-where-clause.rs | 15 +++ ...type-layout-unsized-allowed-sized-used.rs} | 0 ...assoc-type-method-call-via-blanket-impl.rs | 11 +++ .../assoc-type-named-string.rs | 12 +++ .../assoc-type-output-is-sized.rs | 12 +++ .../assoc-type-projection-in-box-return.rs | 23 +++++ .../assoc-type-projection-in-let-binding.rs | 21 +++++ .../assoc-type-projection-on-ref-lifetime.rs | 15 +++ .../assoc-type-ref-in-tuple-return.rs} | 0 .../assoc-type-returns-outer-wrapping-self.rs | 19 ++++ .../bound-references-sibling-assoc-type.rs | 14 +++ ...-variant-with-assoc-type-and-lifetimes.rs} | 0 ...thod-on-impl-with-assoc-type-projection.rs | 20 ++++ .../recursive-enum-with-assoc-type-selfref.rs | 22 +++++ .../same-name-assoc-type-and-method.rs} | 0 .../self-type-alias-for-assoc-type.rs | 17 ++++ .../simple-associated-type-impl.rs | 12 +++ .../size-of-assoc-type-output.rs} | 0 .../unspecified-assoc-type-in-trait-object.rs | 13 +++ ...pecified-assoc-type-in-trait-object.stderr | 17 ++++ 30 files changed, 394 insertions(+) create mode 100644 tests/ui/associated-types/ambiguous-associated-type-default.rs create mode 100644 tests/ui/associated-types/ambiguous-associated-type-default.stderr create mode 100644 tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs rename tests/ui/{issues/issue-37051.rs => associated-types/assoc-type-default-without-override-in-impl.rs} (100%) rename tests/ui/{issues/issue-39970.rs => associated-types/assoc-type-element-mismatch-in-hrtb.rs} (100%) rename tests/ui/{issues/issue-39970.stderr => associated-types/assoc-type-element-mismatch-in-hrtb.stderr} (100%) rename tests/ui/{issues/issue-28983.rs => associated-types/assoc-type-in-extern-fn-signature.rs} (100%) create mode 100644 tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs create mode 100644 tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs create mode 100644 tests/ui/associated-types/assoc-type-in-struct-constructor.rs create mode 100644 tests/ui/associated-types/assoc-type-in-unused-where-clause.rs rename tests/ui/{issues/issue-36036-associated-type-layout.rs => associated-types/assoc-type-layout-unsized-allowed-sized-used.rs} (100%) create mode 100644 tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs create mode 100644 tests/ui/associated-types/assoc-type-named-string.rs create mode 100644 tests/ui/associated-types/assoc-type-output-is-sized.rs create mode 100644 tests/ui/associated-types/assoc-type-projection-in-box-return.rs create mode 100644 tests/ui/associated-types/assoc-type-projection-in-let-binding.rs create mode 100644 tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs rename tests/ui/{issues/issue-37109.rs => associated-types/assoc-type-ref-in-tuple-return.rs} (100%) create mode 100644 tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs create mode 100644 tests/ui/associated-types/bound-references-sibling-assoc-type.rs rename tests/ui/{issues/issue-34839.rs => associated-types/enum-variant-with-assoc-type-and-lifetimes.rs} (100%) create mode 100644 tests/ui/associated-types/method-on-impl-with-assoc-type-projection.rs create mode 100644 tests/ui/associated-types/recursive-enum-with-assoc-type-selfref.rs rename tests/ui/{issues/issue-35600.rs => associated-types/same-name-assoc-type-and-method.rs} (100%) create mode 100644 tests/ui/associated-types/self-type-alias-for-assoc-type.rs create mode 100644 tests/ui/associated-types/simple-associated-type-impl.rs rename tests/ui/{issues/issue-43357.rs => associated-types/size-of-assoc-type-output.rs} (100%) create mode 100644 tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs create mode 100644 tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr diff --git a/tests/ui/associated-types/ambiguous-associated-type-default.rs b/tests/ui/associated-types/ambiguous-associated-type-default.rs new file mode 100644 index 0000000000000..a0ca91336c365 --- /dev/null +++ b/tests/ui/associated-types/ambiguous-associated-type-default.rs @@ -0,0 +1,9 @@ +#![feature(associated_type_defaults)] + +trait Foo { type T; } +trait Bar { + type Foo: Foo; + type FooT = <::Foo>::T; //~ ERROR ambiguous associated type +} + +fn main() {} diff --git a/tests/ui/associated-types/ambiguous-associated-type-default.stderr b/tests/ui/associated-types/ambiguous-associated-type-default.stderr new file mode 100644 index 0000000000000..87dcf3b328923 --- /dev/null +++ b/tests/ui/associated-types/ambiguous-associated-type-default.stderr @@ -0,0 +1,14 @@ +error[E0223]: ambiguous associated type + --> $DIR/issue-23073.rs:6:17 + | +LL | type FooT = <::Foo>::T; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `T` implemented for `::Foo`, you could use the fully-qualified path + | +LL | type FooT = <::Foo as Example>::T; + | ++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs b/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs new file mode 100644 index 0000000000000..47bf52b31a026 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs @@ -0,0 +1,10 @@ +//@ run-pass +use std::ops::Add; + +fn foo(x: T) -> >::Output where i32: Add { + 42i32 + x +} + +fn main() { + println!("{}", foo(0i32)); +} diff --git a/tests/ui/issues/issue-37051.rs b/tests/ui/associated-types/assoc-type-default-without-override-in-impl.rs similarity index 100% rename from tests/ui/issues/issue-37051.rs rename to tests/ui/associated-types/assoc-type-default-without-override-in-impl.rs diff --git a/tests/ui/issues/issue-39970.rs b/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.rs similarity index 100% rename from tests/ui/issues/issue-39970.rs rename to tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.rs diff --git a/tests/ui/issues/issue-39970.stderr b/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.stderr similarity index 100% rename from tests/ui/issues/issue-39970.stderr rename to tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.stderr diff --git a/tests/ui/issues/issue-28983.rs b/tests/ui/associated-types/assoc-type-in-extern-fn-signature.rs similarity index 100% rename from tests/ui/issues/issue-28983.rs rename to tests/ui/associated-types/assoc-type-in-extern-fn-signature.rs diff --git a/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs b/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs new file mode 100644 index 0000000000000..a99ab5f5ebe1d --- /dev/null +++ b/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs @@ -0,0 +1,13 @@ +//@ check-pass +#![allow(dead_code)] + +trait PoolManager { + type C; + fn dummy(&self) { } +} + +struct InnerPool { + manager: M, +} + +fn main() {} diff --git a/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs b/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs new file mode 100644 index 0000000000000..3d3160c6e85d6 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs @@ -0,0 +1,93 @@ +//@ build-pass + +// Regression test for #20797. + +use std::default::Default; +use std::io; +use std::fs; +use std::path::PathBuf; + +pub trait PathExtensions { + fn is_dir(&self) -> bool { false } +} + +impl PathExtensions for PathBuf {} + +/// A strategy for acquiring more subpaths to walk. +pub trait Strategy { + type P: PathExtensions; + /// Gets additional subpaths from a given path. + fn get_more(&self, item: &Self::P) -> io::Result>; + /// Determine whether a path should be walked further. + /// This is run against each item from `get_more()`. + fn prune(&self, p: &Self::P) -> bool; +} + +/// The basic fully-recursive strategy. Nothing is pruned. +#[derive(Copy, Clone, Default)] +pub struct Recursive; + +impl Strategy for Recursive { + type P = PathBuf; + fn get_more(&self, p: &PathBuf) -> io::Result> { + Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect()) + } + + fn prune(&self, _: &PathBuf) -> bool { false } +} + +/// A directory walker of `P` using strategy `S`. +pub struct Subpaths { + stack: Vec, + strategy: S, +} + +impl Subpaths { + /// Creates a directory walker with a root path and strategy. + pub fn new(p: &S::P, strategy: S) -> io::Result> { + let stack = strategy.get_more(p)?; + Ok(Subpaths { stack: stack, strategy: strategy }) + } +} + +impl Subpaths { + /// Creates a directory walker with a root path and a default strategy. + pub fn walk(p: &S::P) -> io::Result> { + Subpaths::new(p, Default::default()) + } +} + +impl Default for Subpaths { + fn default() -> Subpaths { + Subpaths { stack: Vec::new(), strategy: Default::default() } + } +} + +impl Iterator for Subpaths { + type Item = S::P; + fn next (&mut self) -> Option { + let mut opt_path = self.stack.pop(); + while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { + opt_path = self.stack.pop(); + } + match opt_path { + Some(path) => { + if path.is_dir() { + let result = self.strategy.get_more(&path); + match result { + Ok(dirs) => { self.stack.extend(dirs); }, + Err(..) => { } + } + } + Some(path) + } + None => None, + } + } +} + +fn _foo() { + let _walker: Subpaths = Subpaths::walk(&PathBuf::from("/home")).unwrap(); +} + +fn main() {} diff --git a/tests/ui/associated-types/assoc-type-in-struct-constructor.rs b/tests/ui/associated-types/assoc-type-in-struct-constructor.rs new file mode 100644 index 0000000000000..45f50efdccbdb --- /dev/null +++ b/tests/ui/associated-types/assoc-type-in-struct-constructor.rs @@ -0,0 +1,12 @@ +//@ run-pass +trait Tr { type T; } +impl Tr for u8 { type T=(); } +struct S(#[allow(dead_code)] I::T); + +fn foo(i: I::T) { + S::(i); +} + +fn main() { + foo::(()); +} diff --git a/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs b/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs new file mode 100644 index 0000000000000..d13ac216e36ea --- /dev/null +++ b/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs @@ -0,0 +1,15 @@ +//@ check-pass +#![allow(dead_code)] + +trait PoolManager { + type C; + fn dummy(&self) { } +} + +struct InnerPool { + manager: M, +} + +impl InnerPool where M: PoolManager {} + +fn main() {} diff --git a/tests/ui/issues/issue-36036-associated-type-layout.rs b/tests/ui/associated-types/assoc-type-layout-unsized-allowed-sized-used.rs similarity index 100% rename from tests/ui/issues/issue-36036-associated-type-layout.rs rename to tests/ui/associated-types/assoc-type-layout-unsized-allowed-sized-used.rs diff --git a/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs b/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs new file mode 100644 index 0000000000000..e71c2af0c85d6 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs @@ -0,0 +1,11 @@ +//@ run-pass +pub trait Data { fn doit(&self) {} } +impl Data for T {} +pub trait UnaryLogic { type D: Data; } +impl UnaryLogic for () { type D = i32; } + +pub fn crashes(t: T::D) { + t.doit(); +} + +fn main() { crashes::<()>(0); } diff --git a/tests/ui/associated-types/assoc-type-named-string.rs b/tests/ui/associated-types/assoc-type-named-string.rs new file mode 100644 index 0000000000000..e093ed7f41fb0 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-named-string.rs @@ -0,0 +1,12 @@ +//@ check-pass +#![allow(dead_code)] +#![allow(non_camel_case_types)] + +trait Person { + type string; + fn dummy(&self) { } +} + +struct Someone(std::marker::PhantomData

); + +fn main() {} diff --git a/tests/ui/associated-types/assoc-type-output-is-sized.rs b/tests/ui/associated-types/assoc-type-output-is-sized.rs new file mode 100644 index 0000000000000..4d091f3a962c6 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-output-is-sized.rs @@ -0,0 +1,12 @@ +//@ check-pass +// Check that associated types are `Sized` + + +trait Trait { + type Output; + + fn is_sized(&self) -> Self::Output; + fn wasnt_sized(&self) -> Self::Output { loop {} } +} + +fn main() {} diff --git a/tests/ui/associated-types/assoc-type-projection-in-box-return.rs b/tests/ui/associated-types/assoc-type-projection-in-box-return.rs new file mode 100644 index 0000000000000..31dd910191935 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-projection-in-box-return.rs @@ -0,0 +1,23 @@ +// Regression test for Issue #20971. + +//@ run-fail +//@ error-pattern:Hello, world! +//@ needs-subprocess + +pub trait Parser { + type Input; + fn parse(&mut self, input: ::Input); +} + +impl Parser for () { + type Input = (); + fn parse(&mut self, input: ()) {} +} + +pub fn many() -> Box::Input> + 'static> { + panic!("Hello, world!") +} + +fn main() { + many().parse(()); +} diff --git a/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs b/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs new file mode 100644 index 0000000000000..485b1a763900b --- /dev/null +++ b/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs @@ -0,0 +1,21 @@ +//@ check-pass +#![allow(unused_variables)] +// Test that `::Output` and `Self::Output` are accepted as type annotations in let +// bindings + + +trait Int { + fn one() -> Self; + fn leading_zeros(self) -> usize; +} + +trait Foo { + type T : Int; + + fn test(&self) { + let r: ::T = Int::one(); + let r: Self::T = Int::one(); + } +} + +fn main() {} diff --git a/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs b/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs new file mode 100644 index 0000000000000..819f0feb6147a --- /dev/null +++ b/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs @@ -0,0 +1,15 @@ +//@ build-pass +#![allow(dead_code)] +trait Inner { + type T; +} + +impl<'a> Inner for &'a i32 { + type T = i32; +} + +fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T { + *x +} + +fn main() {} diff --git a/tests/ui/issues/issue-37109.rs b/tests/ui/associated-types/assoc-type-ref-in-tuple-return.rs similarity index 100% rename from tests/ui/issues/issue-37109.rs rename to tests/ui/associated-types/assoc-type-ref-in-tuple-return.rs diff --git a/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs b/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs new file mode 100644 index 0000000000000..08a99d357bc43 --- /dev/null +++ b/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs @@ -0,0 +1,19 @@ +//@ run-pass +pub struct Outer(T); +pub struct Inner<'a> { value: &'a bool } + +pub trait Trait { + type Error; + fn ready(self) -> Self::Error; +} + +impl<'a> Trait for Inner<'a> { + type Error = Outer>; + fn ready(self) -> Outer> { Outer(self) } +} + +fn main() { + let value = true; + let inner = Inner { value: &value }; + assert_eq!(inner.ready().0.value, &value); +} diff --git a/tests/ui/associated-types/bound-references-sibling-assoc-type.rs b/tests/ui/associated-types/bound-references-sibling-assoc-type.rs new file mode 100644 index 0000000000000..ffc75f1f08cdd --- /dev/null +++ b/tests/ui/associated-types/bound-references-sibling-assoc-type.rs @@ -0,0 +1,14 @@ +//@ check-pass + +trait A { + fn dummy(&self, arg: X); +} + +trait B { + type X; + type Y: A; + + fn dummy(&self); +} + +fn main () { } diff --git a/tests/ui/issues/issue-34839.rs b/tests/ui/associated-types/enum-variant-with-assoc-type-and-lifetimes.rs similarity index 100% rename from tests/ui/issues/issue-34839.rs rename to tests/ui/associated-types/enum-variant-with-assoc-type-and-lifetimes.rs diff --git a/tests/ui/associated-types/method-on-impl-with-assoc-type-projection.rs b/tests/ui/associated-types/method-on-impl-with-assoc-type-projection.rs new file mode 100644 index 0000000000000..75da3becb5436 --- /dev/null +++ b/tests/ui/associated-types/method-on-impl-with-assoc-type-projection.rs @@ -0,0 +1,20 @@ +//@ run-pass +trait Device { + type Resources; +} +#[allow(dead_code)] +struct Foo(D, R); + +impl Foo { + fn present(&self) {} +} + +struct Res; +struct Dev; + +impl Device for Dev { type Resources = Res; } + +fn main() { + let foo = Foo(Dev, Res); + foo.present(); +} diff --git a/tests/ui/associated-types/recursive-enum-with-assoc-type-selfref.rs b/tests/ui/associated-types/recursive-enum-with-assoc-type-selfref.rs new file mode 100644 index 0000000000000..3f4a2247edf25 --- /dev/null +++ b/tests/ui/associated-types/recursive-enum-with-assoc-type-selfref.rs @@ -0,0 +1,22 @@ +//@ run-pass +#![allow(unused_variables)] +pub trait Parameters { type SelfRef; } + +struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> } +struct BP; + +impl<'a> Parameters for RP<'a> { type SelfRef = &'a X>; } +impl Parameters for BP { type SelfRef = Box>; } + +pub struct Y; +pub enum X { + Nothing, + SameAgain(P::SelfRef, Y) +} + +fn main() { + let bnil: Box> = Box::new(X::Nothing); + let bx: Box> = Box::new(X::SameAgain(bnil, Y)); + let rnil: X = X::Nothing; + let rx: X = X::SameAgain(&rnil, Y); +} diff --git a/tests/ui/issues/issue-35600.rs b/tests/ui/associated-types/same-name-assoc-type-and-method.rs similarity index 100% rename from tests/ui/issues/issue-35600.rs rename to tests/ui/associated-types/same-name-assoc-type-and-method.rs diff --git a/tests/ui/associated-types/self-type-alias-for-assoc-type.rs b/tests/ui/associated-types/self-type-alias-for-assoc-type.rs new file mode 100644 index 0000000000000..e76fd135dcd23 --- /dev/null +++ b/tests/ui/associated-types/self-type-alias-for-assoc-type.rs @@ -0,0 +1,17 @@ +//@ check-pass +pub trait Trait<'a> { + type T; + type U; + fn foo(&self, s: &'a ()) -> &'a (); +} + +impl<'a> Trait<'a> for () { + type T = &'a (); + type U = Self::T; + + fn foo(&self, s: &'a ()) -> &'a () { + let t: Self::T = s; t + } +} + +fn main() {} diff --git a/tests/ui/associated-types/simple-associated-type-impl.rs b/tests/ui/associated-types/simple-associated-type-impl.rs new file mode 100644 index 0000000000000..d3ef6abc8bdc8 --- /dev/null +++ b/tests/ui/associated-types/simple-associated-type-impl.rs @@ -0,0 +1,12 @@ +//@ check-pass +trait Tup { + type T0; + type T1; +} + +impl Tup for isize { + type T0 = f32; + type T1 = (); +} + +fn main() {} diff --git a/tests/ui/issues/issue-43357.rs b/tests/ui/associated-types/size-of-assoc-type-output.rs similarity index 100% rename from tests/ui/issues/issue-43357.rs rename to tests/ui/associated-types/size-of-assoc-type-output.rs diff --git a/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs new file mode 100644 index 0000000000000..9d0c8d96d29a6 --- /dev/null +++ b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs @@ -0,0 +1,13 @@ +// Test that a partially specified trait object with unspecified associated +// type does not type-check. + +trait Foo { + type A; + + fn dummy(&self) { } +} + +fn bar(x: &dyn Foo) {} +//~^ ERROR the associated type `A` in `Foo` must be specified + +pub fn main() {} diff --git a/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr new file mode 100644 index 0000000000000..5ac5130b2cd6c --- /dev/null +++ b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr @@ -0,0 +1,17 @@ +error[E0191]: the value of the associated type `A` in `Foo` must be specified + --> $DIR/issue-19482.rs:10:16 + | +LL | type A; + | ------ `A` defined here +... +LL | fn bar(x: &dyn Foo) {} + | ^^^ + | +help: specify the associated type + | +LL | fn bar(x: &dyn Foo) {} + | ++++++++++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0191`. From 4cca528f801a8e5c8b6139ea6a63f772cd136289 Mon Sep 17 00:00:00 2001 From: danieljofficial Date: Sat, 2 May 2026 10:58:43 +0100 Subject: [PATCH 08/17] add issue links and bless --- .../ambiguous-associated-type-default.rs | 2 + .../ambiguous-associated-type-default.stderr | 2 +- ...soc-type-add-output-via-operator-syntax.rs | 2 + ...c-type-default-without-override-in-impl.rs | 2 + .../assoc-type-element-mismatch-in-hrtb.rs | 2 + ...assoc-type-element-mismatch-in-hrtb.stderr | 6 +- .../assoc-type-in-extern-fn-signature.rs | 2 + .../assoc-type-in-generic-struct-bound.rs | 2 + ...assoc-type-in-strategy-pattern-iterator.rs | 2 +- .../assoc-type-in-struct-constructor.rs | 2 + .../assoc-type-in-unused-where-clause.rs | 2 + ...-type-layout-unsized-allowed-sized-used.rs | 3 +- ...assoc-type-method-call-via-blanket-impl.rs | 2 + .../assoc-type-named-string.rs | 2 + .../assoc-type-output-is-sized.rs | 2 + .../assoc-type-projection-in-box-return.rs | 2 +- .../assoc-type-projection-in-let-binding.rs | 2 + .../assoc-type-projection-on-ref-lifetime.rs | 2 + .../assoc-type-ref-in-tuple-return.rs | 2 + .../assoc-type-returns-outer-wrapping-self.rs | 2 + .../bound-references-sibling-assoc-type.rs | 2 + ...m-variant-with-assoc-type-and-lifetimes.rs | 2 + .../same-name-assoc-type-and-method.rs | 2 + .../self-type-alias-for-assoc-type.rs | 2 + .../simple-associated-type-impl.rs | 2 + .../size-of-assoc-type-output.rs | 2 + .../unspecified-assoc-type-in-trait-object.rs | 1 + ...pecified-assoc-type-in-trait-object.stderr | 2 +- tests/ui/issues/issue-17732.rs | 12 --- tests/ui/issues/issue-18809.rs | 12 --- tests/ui/issues/issue-19482.rs | 13 --- tests/ui/issues/issue-19482.stderr | 17 ---- tests/ui/issues/issue-19631.rs | 15 --- tests/ui/issues/issue-19632.rs | 13 --- tests/ui/issues/issue-19850.rs | 21 ----- tests/ui/issues/issue-20009.rs | 12 --- tests/ui/issues/issue-20797.rs | 93 ------------------- tests/ui/issues/issue-20803.rs | 10 -- tests/ui/issues/issue-20971.rs | 23 ----- tests/ui/issues/issue-21909.rs | 14 --- tests/ui/issues/issue-23073.rs | 9 -- tests/ui/issues/issue-23073.stderr | 14 --- tests/ui/issues/issue-23336.rs | 11 --- tests/ui/issues/issue-23406.rs | 15 --- tests/ui/issues/issue-23992.rs | 19 ---- tests/ui/issues/issue-25679.rs | 20 ---- tests/ui/issues/issue-25693.rs | 22 ----- tests/ui/issues/issue-26127.rs | 12 --- tests/ui/issues/issue-27281.rs | 17 ---- 49 files changed, 52 insertions(+), 402 deletions(-) delete mode 100644 tests/ui/issues/issue-17732.rs delete mode 100644 tests/ui/issues/issue-18809.rs delete mode 100644 tests/ui/issues/issue-19482.rs delete mode 100644 tests/ui/issues/issue-19482.stderr delete mode 100644 tests/ui/issues/issue-19631.rs delete mode 100644 tests/ui/issues/issue-19632.rs delete mode 100644 tests/ui/issues/issue-19850.rs delete mode 100644 tests/ui/issues/issue-20009.rs delete mode 100644 tests/ui/issues/issue-20797.rs delete mode 100644 tests/ui/issues/issue-20803.rs delete mode 100644 tests/ui/issues/issue-20971.rs delete mode 100644 tests/ui/issues/issue-21909.rs delete mode 100644 tests/ui/issues/issue-23073.rs delete mode 100644 tests/ui/issues/issue-23073.stderr delete mode 100644 tests/ui/issues/issue-23336.rs delete mode 100644 tests/ui/issues/issue-23406.rs delete mode 100644 tests/ui/issues/issue-23992.rs delete mode 100644 tests/ui/issues/issue-25679.rs delete mode 100644 tests/ui/issues/issue-25693.rs delete mode 100644 tests/ui/issues/issue-26127.rs delete mode 100644 tests/ui/issues/issue-27281.rs diff --git a/tests/ui/associated-types/ambiguous-associated-type-default.rs b/tests/ui/associated-types/ambiguous-associated-type-default.rs index a0ca91336c365..31d1355d41cee 100644 --- a/tests/ui/associated-types/ambiguous-associated-type-default.rs +++ b/tests/ui/associated-types/ambiguous-associated-type-default.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/23073 + #![feature(associated_type_defaults)] trait Foo { type T; } diff --git a/tests/ui/associated-types/ambiguous-associated-type-default.stderr b/tests/ui/associated-types/ambiguous-associated-type-default.stderr index 87dcf3b328923..38484756fa94a 100644 --- a/tests/ui/associated-types/ambiguous-associated-type-default.stderr +++ b/tests/ui/associated-types/ambiguous-associated-type-default.stderr @@ -1,5 +1,5 @@ error[E0223]: ambiguous associated type - --> $DIR/issue-23073.rs:6:17 + --> $DIR/ambiguous-associated-type-default.rs:8:17 | LL | type FooT = <::Foo>::T; | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs b/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs index 47bf52b31a026..180c3576595de 100644 --- a/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs +++ b/tests/ui/associated-types/assoc-type-add-output-via-operator-syntax.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/20803 + //@ run-pass use std::ops::Add; diff --git a/tests/ui/associated-types/assoc-type-default-without-override-in-impl.rs b/tests/ui/associated-types/assoc-type-default-without-override-in-impl.rs index fa9cc5964fe1f..c9f1760787102 100644 --- a/tests/ui/associated-types/assoc-type-default-without-override-in-impl.rs +++ b/tests/ui/associated-types/assoc-type-default-without-override-in-impl.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/37051 + //@ check-pass #![feature(associated_type_defaults)] diff --git a/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.rs b/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.rs index 40d3ae30a87c6..254fb0051ed30 100644 --- a/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.rs +++ b/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/39970 + trait Array<'a> { type Element: 'a; } diff --git a/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.stderr b/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.stderr index 0fe73574bad6f..eff0a5b53ae06 100644 --- a/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.stderr +++ b/tests/ui/associated-types/assoc-type-element-mismatch-in-hrtb.stderr @@ -1,16 +1,16 @@ error[E0271]: type mismatch resolving `<() as Array<'a>>::Element == ()` - --> $DIR/issue-39970.rs:19:6 + --> $DIR/assoc-type-element-mismatch-in-hrtb.rs:21:6 | LL | <() as Visit>::visit(); | ^^ type mismatch resolving `<() as Array<'a>>::Element == ()` | note: expected this to be `()` - --> $DIR/issue-39970.rs:10:20 + --> $DIR/assoc-type-element-mismatch-in-hrtb.rs:12:20 | LL | type Element = &'a (); | ^^^^^^ note: required for `()` to implement `Visit` - --> $DIR/issue-39970.rs:13:6 + --> $DIR/assoc-type-element-mismatch-in-hrtb.rs:15:6 | LL | impl Visit for () where | ^^^^^ ^^ diff --git a/tests/ui/associated-types/assoc-type-in-extern-fn-signature.rs b/tests/ui/associated-types/assoc-type-in-extern-fn-signature.rs index 90a4793787d4e..ffd26ad8462f5 100644 --- a/tests/ui/associated-types/assoc-type-in-extern-fn-signature.rs +++ b/tests/ui/associated-types/assoc-type-in-extern-fn-signature.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/28983 + //@ run-pass pub trait Test { type T; } diff --git a/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs b/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs index a99ab5f5ebe1d..4aa4b5f3caa10 100644 --- a/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs +++ b/tests/ui/associated-types/assoc-type-in-generic-struct-bound.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/19632 + //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs b/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs index 3d3160c6e85d6..0291b225f6955 100644 --- a/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs +++ b/tests/ui/associated-types/assoc-type-in-strategy-pattern-iterator.rs @@ -1,6 +1,6 @@ //@ build-pass -// Regression test for #20797. +// Regression test for https://github.com/rust-lang/rust/issues/20797 use std::default::Default; use std::io; diff --git a/tests/ui/associated-types/assoc-type-in-struct-constructor.rs b/tests/ui/associated-types/assoc-type-in-struct-constructor.rs index 45f50efdccbdb..b041260cfb356 100644 --- a/tests/ui/associated-types/assoc-type-in-struct-constructor.rs +++ b/tests/ui/associated-types/assoc-type-in-struct-constructor.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/26127 + //@ run-pass trait Tr { type T; } impl Tr for u8 { type T=(); } diff --git a/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs b/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs index d13ac216e36ea..7f570015fc752 100644 --- a/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs +++ b/tests/ui/associated-types/assoc-type-in-unused-where-clause.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/19631 + //@ check-pass #![allow(dead_code)] diff --git a/tests/ui/associated-types/assoc-type-layout-unsized-allowed-sized-used.rs b/tests/ui/associated-types/assoc-type-layout-unsized-allowed-sized-used.rs index 63f9927c67826..1e6fc4ebbb38f 100644 --- a/tests/ui/associated-types/assoc-type-layout-unsized-allowed-sized-used.rs +++ b/tests/ui/associated-types/assoc-type-layout-unsized-allowed-sized-used.rs @@ -1,5 +1,6 @@ //@ run-pass -// Issue 36036: computing the layout of a type composed from another +// Regression test for https://github.com/rust-lang/rust/issues/36036 +// computing the layout of a type composed from another // trait's associated type caused compiler to ICE when the associated // type was allowed to be unsized, even though the known instantiated // type is itself sized. diff --git a/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs b/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs index e71c2af0c85d6..d4fa38124a77c 100644 --- a/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs +++ b/tests/ui/associated-types/assoc-type-method-call-via-blanket-impl.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/23336 + //@ run-pass pub trait Data { fn doit(&self) {} } impl Data for T {} diff --git a/tests/ui/associated-types/assoc-type-named-string.rs b/tests/ui/associated-types/assoc-type-named-string.rs index e093ed7f41fb0..03449e2cdabe5 100644 --- a/tests/ui/associated-types/assoc-type-named-string.rs +++ b/tests/ui/associated-types/assoc-type-named-string.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/17732 + //@ check-pass #![allow(dead_code)] #![allow(non_camel_case_types)] diff --git a/tests/ui/associated-types/assoc-type-output-is-sized.rs b/tests/ui/associated-types/assoc-type-output-is-sized.rs index 4d091f3a962c6..8ef4595843df2 100644 --- a/tests/ui/associated-types/assoc-type-output-is-sized.rs +++ b/tests/ui/associated-types/assoc-type-output-is-sized.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/20009 + //@ check-pass // Check that associated types are `Sized` diff --git a/tests/ui/associated-types/assoc-type-projection-in-box-return.rs b/tests/ui/associated-types/assoc-type-projection-in-box-return.rs index 31dd910191935..6c95467d141aa 100644 --- a/tests/ui/associated-types/assoc-type-projection-in-box-return.rs +++ b/tests/ui/associated-types/assoc-type-projection-in-box-return.rs @@ -1,4 +1,4 @@ -// Regression test for Issue #20971. +// Regression test for Issue https://github.com/rust-lang/rust/issues/20971 //@ run-fail //@ error-pattern:Hello, world! diff --git a/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs b/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs index 485b1a763900b..0438bcd96e1f5 100644 --- a/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs +++ b/tests/ui/associated-types/assoc-type-projection-in-let-binding.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/19850 + //@ check-pass #![allow(unused_variables)] // Test that `::Output` and `Self::Output` are accepted as type annotations in let diff --git a/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs b/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs index 819f0feb6147a..b70d0a7468ff1 100644 --- a/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs +++ b/tests/ui/associated-types/assoc-type-projection-on-ref-lifetime.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/23406 + //@ build-pass #![allow(dead_code)] trait Inner { diff --git a/tests/ui/associated-types/assoc-type-ref-in-tuple-return.rs b/tests/ui/associated-types/assoc-type-ref-in-tuple-return.rs index 5276266523d8d..a587affb52ef8 100644 --- a/tests/ui/associated-types/assoc-type-ref-in-tuple-return.rs +++ b/tests/ui/associated-types/assoc-type-ref-in-tuple-return.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/37109 + //@ run-pass trait ToRef<'a> { type Ref: 'a; diff --git a/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs b/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs index 08a99d357bc43..74e941962a16b 100644 --- a/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs +++ b/tests/ui/associated-types/assoc-type-returns-outer-wrapping-self.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/23992 + //@ run-pass pub struct Outer(T); pub struct Inner<'a> { value: &'a bool } diff --git a/tests/ui/associated-types/bound-references-sibling-assoc-type.rs b/tests/ui/associated-types/bound-references-sibling-assoc-type.rs index ffc75f1f08cdd..18709cec121aa 100644 --- a/tests/ui/associated-types/bound-references-sibling-assoc-type.rs +++ b/tests/ui/associated-types/bound-references-sibling-assoc-type.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/21909 + //@ check-pass trait A { diff --git a/tests/ui/associated-types/enum-variant-with-assoc-type-and-lifetimes.rs b/tests/ui/associated-types/enum-variant-with-assoc-type-and-lifetimes.rs index 73edba5817af3..64de3df1e7c92 100644 --- a/tests/ui/associated-types/enum-variant-with-assoc-type-and-lifetimes.rs +++ b/tests/ui/associated-types/enum-variant-with-assoc-type-and-lifetimes.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/34839 + //@ check-pass trait RegularExpression: Sized { diff --git a/tests/ui/associated-types/same-name-assoc-type-and-method.rs b/tests/ui/associated-types/same-name-assoc-type-and-method.rs index 40df0b6dfd890..21990ee150ab6 100644 --- a/tests/ui/associated-types/same-name-assoc-type-and-method.rs +++ b/tests/ui/associated-types/same-name-assoc-type-and-method.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/35600 + //@ run-pass #![allow(non_camel_case_types)] #![allow(unused_variables)] diff --git a/tests/ui/associated-types/self-type-alias-for-assoc-type.rs b/tests/ui/associated-types/self-type-alias-for-assoc-type.rs index e76fd135dcd23..14864ede2a8be 100644 --- a/tests/ui/associated-types/self-type-alias-for-assoc-type.rs +++ b/tests/ui/associated-types/self-type-alias-for-assoc-type.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/27281 + //@ check-pass pub trait Trait<'a> { type T; diff --git a/tests/ui/associated-types/simple-associated-type-impl.rs b/tests/ui/associated-types/simple-associated-type-impl.rs index d3ef6abc8bdc8..1ebaf3b281786 100644 --- a/tests/ui/associated-types/simple-associated-type-impl.rs +++ b/tests/ui/associated-types/simple-associated-type-impl.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/18809 + //@ check-pass trait Tup { type T0; diff --git a/tests/ui/associated-types/size-of-assoc-type-output.rs b/tests/ui/associated-types/size-of-assoc-type-output.rs index fd20bac804074..c8f1865a3a5c1 100644 --- a/tests/ui/associated-types/size-of-assoc-type-output.rs +++ b/tests/ui/associated-types/size-of-assoc-type-output.rs @@ -1,3 +1,5 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/43357 + //@ check-pass #![allow(dead_code)] trait Trait { diff --git a/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs index 9d0c8d96d29a6..45b0171bccba0 100644 --- a/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs +++ b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.rs @@ -1,3 +1,4 @@ +// Regression test for https://github.com/rust-lang/rust/issues/19842 // Test that a partially specified trait object with unspecified associated // type does not type-check. diff --git a/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr index 5ac5130b2cd6c..0bcd91e31c2c4 100644 --- a/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr +++ b/tests/ui/associated-types/unspecified-assoc-type-in-trait-object.stderr @@ -1,5 +1,5 @@ error[E0191]: the value of the associated type `A` in `Foo` must be specified - --> $DIR/issue-19482.rs:10:16 + --> $DIR/unspecified-assoc-type-in-trait-object.rs:11:16 | LL | type A; | ------ `A` defined here diff --git a/tests/ui/issues/issue-17732.rs b/tests/ui/issues/issue-17732.rs deleted file mode 100644 index e093ed7f41fb0..0000000000000 --- a/tests/ui/issues/issue-17732.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ check-pass -#![allow(dead_code)] -#![allow(non_camel_case_types)] - -trait Person { - type string; - fn dummy(&self) { } -} - -struct Someone(std::marker::PhantomData

); - -fn main() {} diff --git a/tests/ui/issues/issue-18809.rs b/tests/ui/issues/issue-18809.rs deleted file mode 100644 index d3ef6abc8bdc8..0000000000000 --- a/tests/ui/issues/issue-18809.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ check-pass -trait Tup { - type T0; - type T1; -} - -impl Tup for isize { - type T0 = f32; - type T1 = (); -} - -fn main() {} diff --git a/tests/ui/issues/issue-19482.rs b/tests/ui/issues/issue-19482.rs deleted file mode 100644 index 9d0c8d96d29a6..0000000000000 --- a/tests/ui/issues/issue-19482.rs +++ /dev/null @@ -1,13 +0,0 @@ -// Test that a partially specified trait object with unspecified associated -// type does not type-check. - -trait Foo { - type A; - - fn dummy(&self) { } -} - -fn bar(x: &dyn Foo) {} -//~^ ERROR the associated type `A` in `Foo` must be specified - -pub fn main() {} diff --git a/tests/ui/issues/issue-19482.stderr b/tests/ui/issues/issue-19482.stderr deleted file mode 100644 index 5ac5130b2cd6c..0000000000000 --- a/tests/ui/issues/issue-19482.stderr +++ /dev/null @@ -1,17 +0,0 @@ -error[E0191]: the value of the associated type `A` in `Foo` must be specified - --> $DIR/issue-19482.rs:10:16 - | -LL | type A; - | ------ `A` defined here -... -LL | fn bar(x: &dyn Foo) {} - | ^^^ - | -help: specify the associated type - | -LL | fn bar(x: &dyn Foo) {} - | ++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0191`. diff --git a/tests/ui/issues/issue-19631.rs b/tests/ui/issues/issue-19631.rs deleted file mode 100644 index d13ac216e36ea..0000000000000 --- a/tests/ui/issues/issue-19631.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ check-pass -#![allow(dead_code)] - -trait PoolManager { - type C; - fn dummy(&self) { } -} - -struct InnerPool { - manager: M, -} - -impl InnerPool where M: PoolManager {} - -fn main() {} diff --git a/tests/ui/issues/issue-19632.rs b/tests/ui/issues/issue-19632.rs deleted file mode 100644 index a99ab5f5ebe1d..0000000000000 --- a/tests/ui/issues/issue-19632.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ check-pass -#![allow(dead_code)] - -trait PoolManager { - type C; - fn dummy(&self) { } -} - -struct InnerPool { - manager: M, -} - -fn main() {} diff --git a/tests/ui/issues/issue-19850.rs b/tests/ui/issues/issue-19850.rs deleted file mode 100644 index 485b1a763900b..0000000000000 --- a/tests/ui/issues/issue-19850.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ check-pass -#![allow(unused_variables)] -// Test that `::Output` and `Self::Output` are accepted as type annotations in let -// bindings - - -trait Int { - fn one() -> Self; - fn leading_zeros(self) -> usize; -} - -trait Foo { - type T : Int; - - fn test(&self) { - let r: ::T = Int::one(); - let r: Self::T = Int::one(); - } -} - -fn main() {} diff --git a/tests/ui/issues/issue-20009.rs b/tests/ui/issues/issue-20009.rs deleted file mode 100644 index 4d091f3a962c6..0000000000000 --- a/tests/ui/issues/issue-20009.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ check-pass -// Check that associated types are `Sized` - - -trait Trait { - type Output; - - fn is_sized(&self) -> Self::Output; - fn wasnt_sized(&self) -> Self::Output { loop {} } -} - -fn main() {} diff --git a/tests/ui/issues/issue-20797.rs b/tests/ui/issues/issue-20797.rs deleted file mode 100644 index 3d3160c6e85d6..0000000000000 --- a/tests/ui/issues/issue-20797.rs +++ /dev/null @@ -1,93 +0,0 @@ -//@ build-pass - -// Regression test for #20797. - -use std::default::Default; -use std::io; -use std::fs; -use std::path::PathBuf; - -pub trait PathExtensions { - fn is_dir(&self) -> bool { false } -} - -impl PathExtensions for PathBuf {} - -/// A strategy for acquiring more subpaths to walk. -pub trait Strategy { - type P: PathExtensions; - /// Gets additional subpaths from a given path. - fn get_more(&self, item: &Self::P) -> io::Result>; - /// Determine whether a path should be walked further. - /// This is run against each item from `get_more()`. - fn prune(&self, p: &Self::P) -> bool; -} - -/// The basic fully-recursive strategy. Nothing is pruned. -#[derive(Copy, Clone, Default)] -pub struct Recursive; - -impl Strategy for Recursive { - type P = PathBuf; - fn get_more(&self, p: &PathBuf) -> io::Result> { - Ok(fs::read_dir(p).unwrap().map(|s| s.unwrap().path()).collect()) - } - - fn prune(&self, _: &PathBuf) -> bool { false } -} - -/// A directory walker of `P` using strategy `S`. -pub struct Subpaths { - stack: Vec, - strategy: S, -} - -impl Subpaths { - /// Creates a directory walker with a root path and strategy. - pub fn new(p: &S::P, strategy: S) -> io::Result> { - let stack = strategy.get_more(p)?; - Ok(Subpaths { stack: stack, strategy: strategy }) - } -} - -impl Subpaths { - /// Creates a directory walker with a root path and a default strategy. - pub fn walk(p: &S::P) -> io::Result> { - Subpaths::new(p, Default::default()) - } -} - -impl Default for Subpaths { - fn default() -> Subpaths { - Subpaths { stack: Vec::new(), strategy: Default::default() } - } -} - -impl Iterator for Subpaths { - type Item = S::P; - fn next (&mut self) -> Option { - let mut opt_path = self.stack.pop(); - while opt_path.is_some() && self.strategy.prune(opt_path.as_ref().unwrap()) { - opt_path = self.stack.pop(); - } - match opt_path { - Some(path) => { - if path.is_dir() { - let result = self.strategy.get_more(&path); - match result { - Ok(dirs) => { self.stack.extend(dirs); }, - Err(..) => { } - } - } - Some(path) - } - None => None, - } - } -} - -fn _foo() { - let _walker: Subpaths = Subpaths::walk(&PathBuf::from("/home")).unwrap(); -} - -fn main() {} diff --git a/tests/ui/issues/issue-20803.rs b/tests/ui/issues/issue-20803.rs deleted file mode 100644 index 47bf52b31a026..0000000000000 --- a/tests/ui/issues/issue-20803.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ run-pass -use std::ops::Add; - -fn foo(x: T) -> >::Output where i32: Add { - 42i32 + x -} - -fn main() { - println!("{}", foo(0i32)); -} diff --git a/tests/ui/issues/issue-20971.rs b/tests/ui/issues/issue-20971.rs deleted file mode 100644 index 31dd910191935..0000000000000 --- a/tests/ui/issues/issue-20971.rs +++ /dev/null @@ -1,23 +0,0 @@ -// Regression test for Issue #20971. - -//@ run-fail -//@ error-pattern:Hello, world! -//@ needs-subprocess - -pub trait Parser { - type Input; - fn parse(&mut self, input: ::Input); -} - -impl Parser for () { - type Input = (); - fn parse(&mut self, input: ()) {} -} - -pub fn many() -> Box::Input> + 'static> { - panic!("Hello, world!") -} - -fn main() { - many().parse(()); -} diff --git a/tests/ui/issues/issue-21909.rs b/tests/ui/issues/issue-21909.rs deleted file mode 100644 index ffc75f1f08cdd..0000000000000 --- a/tests/ui/issues/issue-21909.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ check-pass - -trait A { - fn dummy(&self, arg: X); -} - -trait B { - type X; - type Y: A; - - fn dummy(&self); -} - -fn main () { } diff --git a/tests/ui/issues/issue-23073.rs b/tests/ui/issues/issue-23073.rs deleted file mode 100644 index a0ca91336c365..0000000000000 --- a/tests/ui/issues/issue-23073.rs +++ /dev/null @@ -1,9 +0,0 @@ -#![feature(associated_type_defaults)] - -trait Foo { type T; } -trait Bar { - type Foo: Foo; - type FooT = <::Foo>::T; //~ ERROR ambiguous associated type -} - -fn main() {} diff --git a/tests/ui/issues/issue-23073.stderr b/tests/ui/issues/issue-23073.stderr deleted file mode 100644 index 87dcf3b328923..0000000000000 --- a/tests/ui/issues/issue-23073.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0223]: ambiguous associated type - --> $DIR/issue-23073.rs:6:17 - | -LL | type FooT = <::Foo>::T; - | ^^^^^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `T` implemented for `::Foo`, you could use the fully-qualified path - | -LL | type FooT = <::Foo as Example>::T; - | ++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/issues/issue-23336.rs b/tests/ui/issues/issue-23336.rs deleted file mode 100644 index e71c2af0c85d6..0000000000000 --- a/tests/ui/issues/issue-23336.rs +++ /dev/null @@ -1,11 +0,0 @@ -//@ run-pass -pub trait Data { fn doit(&self) {} } -impl Data for T {} -pub trait UnaryLogic { type D: Data; } -impl UnaryLogic for () { type D = i32; } - -pub fn crashes(t: T::D) { - t.doit(); -} - -fn main() { crashes::<()>(0); } diff --git a/tests/ui/issues/issue-23406.rs b/tests/ui/issues/issue-23406.rs deleted file mode 100644 index 819f0feb6147a..0000000000000 --- a/tests/ui/issues/issue-23406.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ build-pass -#![allow(dead_code)] -trait Inner { - type T; -} - -impl<'a> Inner for &'a i32 { - type T = i32; -} - -fn f<'a>(x: &'a i32) -> <&'a i32 as Inner>::T { - *x -} - -fn main() {} diff --git a/tests/ui/issues/issue-23992.rs b/tests/ui/issues/issue-23992.rs deleted file mode 100644 index 08a99d357bc43..0000000000000 --- a/tests/ui/issues/issue-23992.rs +++ /dev/null @@ -1,19 +0,0 @@ -//@ run-pass -pub struct Outer(T); -pub struct Inner<'a> { value: &'a bool } - -pub trait Trait { - type Error; - fn ready(self) -> Self::Error; -} - -impl<'a> Trait for Inner<'a> { - type Error = Outer>; - fn ready(self) -> Outer> { Outer(self) } -} - -fn main() { - let value = true; - let inner = Inner { value: &value }; - assert_eq!(inner.ready().0.value, &value); -} diff --git a/tests/ui/issues/issue-25679.rs b/tests/ui/issues/issue-25679.rs deleted file mode 100644 index 75da3becb5436..0000000000000 --- a/tests/ui/issues/issue-25679.rs +++ /dev/null @@ -1,20 +0,0 @@ -//@ run-pass -trait Device { - type Resources; -} -#[allow(dead_code)] -struct Foo(D, R); - -impl Foo { - fn present(&self) {} -} - -struct Res; -struct Dev; - -impl Device for Dev { type Resources = Res; } - -fn main() { - let foo = Foo(Dev, Res); - foo.present(); -} diff --git a/tests/ui/issues/issue-25693.rs b/tests/ui/issues/issue-25693.rs deleted file mode 100644 index 3f4a2247edf25..0000000000000 --- a/tests/ui/issues/issue-25693.rs +++ /dev/null @@ -1,22 +0,0 @@ -//@ run-pass -#![allow(unused_variables)] -pub trait Parameters { type SelfRef; } - -struct RP<'a> { _marker: std::marker::PhantomData<&'a ()> } -struct BP; - -impl<'a> Parameters for RP<'a> { type SelfRef = &'a X>; } -impl Parameters for BP { type SelfRef = Box>; } - -pub struct Y; -pub enum X { - Nothing, - SameAgain(P::SelfRef, Y) -} - -fn main() { - let bnil: Box> = Box::new(X::Nothing); - let bx: Box> = Box::new(X::SameAgain(bnil, Y)); - let rnil: X = X::Nothing; - let rx: X = X::SameAgain(&rnil, Y); -} diff --git a/tests/ui/issues/issue-26127.rs b/tests/ui/issues/issue-26127.rs deleted file mode 100644 index 45f50efdccbdb..0000000000000 --- a/tests/ui/issues/issue-26127.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ run-pass -trait Tr { type T; } -impl Tr for u8 { type T=(); } -struct S(#[allow(dead_code)] I::T); - -fn foo(i: I::T) { - S::(i); -} - -fn main() { - foo::(()); -} diff --git a/tests/ui/issues/issue-27281.rs b/tests/ui/issues/issue-27281.rs deleted file mode 100644 index e76fd135dcd23..0000000000000 --- a/tests/ui/issues/issue-27281.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ check-pass -pub trait Trait<'a> { - type T; - type U; - fn foo(&self, s: &'a ()) -> &'a (); -} - -impl<'a> Trait<'a> for () { - type T = &'a (); - type U = Self::T; - - fn foo(&self, s: &'a ()) -> &'a () { - let t: Self::T = s; t - } -} - -fn main() {} From a34cb767bea8acc06036e788ae96f6b5069b48eb Mon Sep 17 00:00:00 2001 From: Matyas Susits Date: Sat, 2 May 2026 17:30:58 +0200 Subject: [PATCH 09/17] Only include `crate_hash` in `Linker` if incremental compilation is enabled, not when `needs_crate_hash` is true. Exactly as the comment on the `crate_hash` field of `Linker` says, that field is only used when incremental compilation is enabled. `needs_crate_hash` returns true in some other cases too. --- compiler/rustc_interface/src/queries.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 170393f3b8179..63c7332893b81 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -36,7 +36,7 @@ impl Linker { Linker { dep_graph: tcx.dep_graph.clone(), output_filenames: Arc::clone(tcx.output_filenames(())), - crate_hash: if tcx.needs_crate_hash() { + crate_hash: if tcx.sess.opts.incremental.is_some() { Some(tcx.crate_hash(LOCAL_CRATE)) } else { None From 5313fb1d0bc13507db5a0518edb25f9b3614240b Mon Sep 17 00:00:00 2001 From: Matyas Susits Date: Sat, 2 May 2026 17:34:12 +0200 Subject: [PATCH 10/17] rename `needs_crate_hash` to `needs_hir_hash`. It's easy to confuse the functionality of `needs_crate_hash` with "is the crate_hash query needed" right now. The function returns whether we need to calculate the stable hash of various hir structs. --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_middle/src/hir/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 3c8abf3ee2bbb..278c82c5eeb6d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -563,7 +563,7 @@ pub fn lower_to_hir(tcx: TyCtxt<'_>, (): ()) -> mid_hir::Crate<'_> { // Don't hash unless necessary, because it's expensive. let opt_hir_hash = - if tcx.needs_crate_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; + if tcx.needs_hir_hash() { Some(compute_hir_hash(tcx, &owners)) } else { None }; let delayed_resolver = Steal::new((resolver, krate)); mid_hir::Crate::new(owners, delayed_ids, delayed_resolver, opt_hir_hash) diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index 492d21b3169a8..2d55078bc4d3e 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -237,7 +237,7 @@ impl<'tcx> TyCtxt<'tcx> { attrs: &SortedMap, define_opaque: Option<&[(Span, LocalDefId)]>, ) -> Hashes { - if !self.needs_crate_hash() { + if !self.needs_hir_hash() { return Hashes { opt_hash_including_bodies: None, attrs_hash: None }; } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bbe241c574d41..2a80ea670353a 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1136,12 +1136,12 @@ impl<'tcx> TyCtxt<'tcx> { }) } - pub fn needs_crate_hash(self) -> bool { - // Why is the crate hash needed for these configurations? + pub fn needs_hir_hash(self) -> bool { + // Why is the hir hash needed for these configurations? // - debug_assertions: for the "fingerprint the result" check in // `rustc_query_impl::execution::execute_job`. // - incremental: for query lookups. - // - needs_metadata: for putting into crate metadata. + // - needs_metadata: it is included in the crate metadata through the crate_hash query // - instrument_coverage: for putting into coverage data (see // `hash_mir_source`). // - metrics_dir: metrics use the strict version hash in the filenames From ecf527faafa4b992cfa7c411489bf13cc1831258 Mon Sep 17 00:00:00 2001 From: aobatact Date: Sun, 3 May 2026 16:08:11 +0900 Subject: [PATCH 11/17] Relax `T: Sized` bound on `try_as_dyn` / `try_as_dyn_mut` `trait_info_of` already returns `None` for unsized types, so allowing `T: ?Sized` is sound and lets callers in generic contexts use these functions without a separate `Sized` bound. For unsized `T`, the function always returns `None`. --- library/core/src/any.rs | 18 ++++++++++++---- tests/ui/any/try_as_dyn_unsized.rs | 34 ++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 4 deletions(-) create mode 100644 tests/ui/any/try_as_dyn_unsized.rs diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 53c5e28c0be27..7d820403ccb7d 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -1007,18 +1007,23 @@ pub const fn type_name_of_val(_val: &T) -> &'static str { #[must_use] #[unstable(feature = "try_as_dyn", issue = "144361")] pub const fn try_as_dyn< - T: Any + 'static, + T: Any + ?Sized + 'static, U: ptr::Pointee> + ?Sized + 'static, >( t: &T, ) -> Option<&U> { + // For unsized `T`, `trait_info_of` always returns `None` (vtable lookup is + // only supported for sized types). The function therefore unconditionally + // returns `None` in that case. let vtable: Option> = const { TypeId::of::().trait_info_of::().as_ref().map(TraitImpl::get_vtable) }; match vtable { Some(dyn_metadata) => { - let pointer = ptr::from_raw_parts(t, dyn_metadata); + let pointer = ptr::from_raw_parts(t as *const T as *const (), dyn_metadata); // SAFETY: `t` is a reference to a type, so we know it is valid. // `dyn_metadata` is a vtable for T, implementing the trait of `U`. + // `T` is sized here because `trait_info_of` only returns `Some` for sized types, + // so the thin data pointer fully describes the value. Some(unsafe { &*pointer }) } None => None, @@ -1061,18 +1066,23 @@ pub const fn try_as_dyn< #[must_use] #[unstable(feature = "try_as_dyn", issue = "144361")] pub const fn try_as_dyn_mut< - T: Any + 'static, + T: Any + ?Sized + 'static, U: ptr::Pointee> + ?Sized + 'static, >( t: &mut T, ) -> Option<&mut U> { + // For unsized `T`, `trait_info_of` always returns `None` (vtable lookup is + // only supported for sized types). The function therefore unconditionally + // returns `None` in that case. let vtable: Option> = const { TypeId::of::().trait_info_of::().as_ref().map(TraitImpl::get_vtable) }; match vtable { Some(dyn_metadata) => { - let pointer = ptr::from_raw_parts_mut(t, dyn_metadata); + let pointer = ptr::from_raw_parts_mut(t as *mut T as *mut (), dyn_metadata); // SAFETY: `t` is a reference to a type, so we know it is valid. // `dyn_metadata` is a vtable for T, implementing the trait of `U`. + // `T` is sized here because `trait_info_of` only returns `Some` for sized types, + // so the thin data pointer fully describes the value. Some(unsafe { &mut *pointer }) } None => None, diff --git a/tests/ui/any/try_as_dyn_unsized.rs b/tests/ui/any/try_as_dyn_unsized.rs new file mode 100644 index 0000000000000..83bf1e2863c43 --- /dev/null +++ b/tests/ui/any/try_as_dyn_unsized.rs @@ -0,0 +1,34 @@ +//@ run-pass +#![feature(try_as_dyn)] + +use std::fmt::Debug; + +// Generic over `?Sized` T: relies on the relaxed bound on `try_as_dyn`. +fn try_debug(t: &T) -> Option { + std::any::try_as_dyn::(t).map(|d| format!("{d:?}")) +} + +fn try_debug_mut(t: &mut T) -> Option { + std::any::try_as_dyn_mut::(t).map(|d| format!("{d:?}")) +} + +fn main() { + // Sized case still works through a `?Sized` generic context. + let x: i32 = 7; + assert_eq!(try_debug(&x).as_deref(), Some("7")); + + let mut y: i32 = 8; + assert_eq!(try_debug_mut(&mut y).as_deref(), Some("8")); + + // Unsized `T` always returns `None`, even though `str: Debug` and + // `[T]: Debug` hold — vtable lookup for unsized impl types is not + // currently supported by `TypeId::trait_info_of`. + let s: &str = "hello"; + assert!(try_debug::(s).is_none()); + + let slice: &[i32] = &[1, 2, 3]; + assert!(try_debug::<[i32]>(slice).is_none()); + + let dyn_any: &dyn std::any::Any = &0i32; + assert!(try_debug::(dyn_any).is_none()); +} From 1e649f13ca4b29c990c39278450e3d13b01f373d Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sun, 3 May 2026 20:31:11 -0700 Subject: [PATCH 12/17] .mailmap: prefer matching just based on commit emails So that commits under different names are still caught --- .mailmap | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.mailmap b/.mailmap index fa30f07ad7310..4a3e39831e8a2 100644 --- a/.mailmap +++ b/.mailmap @@ -259,11 +259,9 @@ Gregor Peach Grzegorz Bartoszek Guanqun Lu Guillaume Gomez -Guillaume Gomez Guillaume Gomez -Guillaume Gomez ggomez -Guillaume Gomez ggomez -Guillaume Gomez Guillaume Gomez -Guillaume Gomez Guillaume Gomez +Guillaume Gomez +Guillaume Gomez +Guillaume Gomez gnzlbg hamidreza kalbasi Hanna Kruppe From 8e0ebb9044c49c1e9ff1334c800f18d988474b24 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 1 May 2026 12:39:27 +0200 Subject: [PATCH 13/17] c-variadic: gate `va_arg` on `c_variadic_experimental_arch` Just gating `...` is insufficient because we make the types available everywhere, and you could still define and export functions that used va_arg for targets where we don't want to stably support it. --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 15 +- tests/assembly-llvm/c-variadic/avr.rs | 220 +++++++++++++++++++ tests/assembly-llvm/c-variadic/sparc.rs | 1 + 3 files changed, 234 insertions(+), 2 deletions(-) create mode 100644 tests/assembly-llvm/c-variadic/avr.rs diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 81160b6c3fed5..dd9ebf298b229 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -3,8 +3,8 @@ use std::ffi::c_uint; use std::{assert_matches, iter, ptr}; use rustc_abi::{ - AddressSpace, Align, BackendRepr, Float, HasDataLayout, Integer, NumScalableVectors, Primitive, - Size, WrappingRange, + AddressSpace, Align, BackendRepr, CVariadicStatus, Float, HasDataLayout, Integer, + NumScalableVectors, Primitive, Size, WrappingRange, }; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; @@ -23,6 +23,7 @@ use rustc_middle::ty::{ }; use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; +use rustc_session::errors::feature_err; use rustc_session::lint::builtin::DEPRECATED_LLVM_INTRINSIC; use rustc_span::{Span, Symbol, sym}; use rustc_symbol_mangling::{mangle_internal_symbol, symbol_name_for_instance_in_crate}; @@ -288,6 +289,16 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } sym::breakpoint => self.call_intrinsic("llvm.debugtrap", &[], &[]), sym::va_arg => { + let target = &self.cx.tcx.sess.target; + let stability = target.supports_c_variadic_definitions(); + if let CVariadicStatus::Unstable { feature } = stability + && !self.tcx.features().enabled(feature) + { + let msg = + format!("C-variadic function definitions on this target are unstable"); + feature_err(&*self.sess(), feature, span, msg).emit(); + } + let BackendRepr::Scalar(scalar) = result.layout.backend_repr else { bug!("the va_arg intrinsic does not support non-scalar types") }; diff --git a/tests/assembly-llvm/c-variadic/avr.rs b/tests/assembly-llvm/c-variadic/avr.rs new file mode 100644 index 0000000000000..a5f48a2d0533e --- /dev/null +++ b/tests/assembly-llvm/c-variadic/avr.rs @@ -0,0 +1,220 @@ +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ revisions: AVR +//@ [AVR] compile-flags: -Copt-level=3 --target=avr-none -Ctarget-cpu=atmega328p +//@ [AVR] needs-llvm-components: avr +#![feature(c_variadic, c_variadic_experimental_arch, no_core, lang_items, intrinsics, rustc_attrs)] +#![no_core] +#![crate_type = "lib"] + +// Check that rustc and clang output match, see https://godbolt.org/z/1MvxoceeT. + +extern crate minicore; +use minicore::*; + +#[lang = "va_arg_safe"] +pub unsafe trait VaArgSafe {} + +unsafe impl VaArgSafe for i16 {} +unsafe impl VaArgSafe for i32 {} +unsafe impl VaArgSafe for i64 {} +unsafe impl VaArgSafe for f32 {} +unsafe impl VaArgSafe for f64 {} +unsafe impl VaArgSafe for *const T {} + +#[repr(transparent)] +struct VaListInner { + ptr: *const c_void, +} + +#[repr(transparent)] +#[lang = "va_list"] +pub struct VaList<'a> { + inner: VaListInner, + _marker: PhantomData<&'a mut ()>, +} + +#[rustc_intrinsic] +#[rustc_nounwind] +pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; + +#[unsafe(no_mangle)] +unsafe extern "C" fn read_f32(ap: &mut VaList<'_>) -> f32 { + // CHECK-LABEL: read_f32 + // + // AVR: movw r30, r24 + // AVR-NEXT: ld r24, Z + // AVR-NEXT: ldd r25, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 2 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r20, r30 + // AVR-NEXT: movw r18, r24 + // AVR-NEXT: movw r30, r18 + // AVR-NEXT: ld r22, Z + // AVR-NEXT: ldd r23, Z+1 + // AVR-NEXT: adiw r24, 4 + // AVR-NEXT: movw r30, r20 + // AVR-NEXT: std Z+1, r25 + // AVR-NEXT: st Z, r24 + // AVR-NEXT: movw r30, r18 + // AVR-NEXT: ldd r24, Z+2 + // AVR-NEXT: ldd r25, Z+3 + // AVR-NEXT: ret + va_arg(ap) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { + // CHECK-LABEL: read_f64 + // + // AVR: push r14 + // AVR-NEXT: push r15 + // AVR-NEXT: push r16 + // AVR-NEXT: push r17 + // AVR-NEXT: movw r30, r24 + // AVR-NEXT: ld r24, Z + // AVR-NEXT: ldd r25, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 2 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r14, r30 + // AVR-NEXT: movw r16, r24 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ld r18, Z + // AVR-NEXT: ldd r19, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 4 + // AVR-NEXT: movw r30, r14 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ldd r20, Z+2 + // AVR-NEXT: ldd r21, Z+3 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 6 + // AVR-NEXT: movw r30, r14 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ldd r22, Z+4 + // AVR-NEXT: ldd r23, Z+5 + // AVR-NEXT: adiw r24, 8 + // AVR-NEXT: movw r30, r14 + // AVR-NEXT: std Z+1, r25 + // AVR-NEXT: st Z, r24 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ldd r24, Z+6 + // AVR-NEXT: ldd r25, Z+7 + // AVR-NEXT: pop r17 + // AVR-NEXT: pop r16 + // AVR-NEXT: pop r15 + // AVR-NEXT: pop r14 + // AVR-NEXT: ret + va_arg(ap) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn read_i16(ap: &mut VaList<'_>) -> i16 { + // CHECK-LABEL: read_i16 + // + // AVR: movw r30, r24 + // AVR-NEXT: ld r24, Z + // AVR-NEXT: ldd r25, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 2 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r30, r24 + // AVR-NEXT: ld r24, Z + // AVR-NEXT: ldd r25, Z+1 + // AVR-NEXT: ret + va_arg(ap) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { + // CHECK-LABEL: read_i32 + // + // AVR: movw r30, r24 + // AVR-NEXT: ld r24, Z + // AVR-NEXT: ldd r25, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 2 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r20, r30 + // AVR-NEXT: movw r18, r24 + // AVR-NEXT: movw r30, r18 + // AVR-NEXT: ld r22, Z + // AVR-NEXT: ldd r23, Z+1 + // AVR-NEXT: adiw r24, 4 + // AVR-NEXT: movw r30, r20 + // AVR-NEXT: std Z+1, r25 + // AVR-NEXT: st Z, r24 + // AVR-NEXT: movw r30, r18 + // AVR-NEXT: ldd r24, Z+2 + // AVR-NEXT: ldd r25, Z+3 + // AVR-NEXT: ret + va_arg(ap) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { + // CHECK-LABEL: read_i64 + // + // AVR: push r14 + // AVR-NEXT: push r15 + // AVR-NEXT: push r16 + // AVR-NEXT: push r17 + // AVR-NEXT: movw r30, r24 + // AVR-NEXT: ld r24, Z + // AVR-NEXT: ldd r25, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 2 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r14, r30 + // AVR-NEXT: movw r16, r24 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ld r18, Z + // AVR-NEXT: ldd r19, Z+1 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 4 + // AVR-NEXT: movw r30, r14 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ldd r20, Z+2 + // AVR-NEXT: ldd r21, Z+3 + // AVR-NEXT: movw r26, r24 + // AVR-NEXT: adiw r26, 6 + // AVR-NEXT: movw r30, r14 + // AVR-NEXT: std Z+1, r27 + // AVR-NEXT: st Z, r26 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ldd r22, Z+4 + // AVR-NEXT: ldd r23, Z+5 + // AVR-NEXT: adiw r24, 8 + // AVR-NEXT: movw r30, r14 + // AVR-NEXT: std Z+1, r25 + // AVR-NEXT: st Z, r24 + // AVR-NEXT: movw r30, r16 + // AVR-NEXT: ldd r24, Z+6 + // AVR-NEXT: ldd r25, Z+7 + // AVR-NEXT: pop r17 + // AVR-NEXT: pop r16 + // AVR-NEXT: pop r15 + // AVR-NEXT: pop r14 + // AVR-NEXT: ret + va_arg(ap) +} + +#[unsafe(no_mangle)] +unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { + // AVR: read_ptr = pm(read_i16) + va_arg(ap) +} diff --git a/tests/assembly-llvm/c-variadic/sparc.rs b/tests/assembly-llvm/c-variadic/sparc.rs index 59f039e7df28b..6ce25119a135c 100644 --- a/tests/assembly-llvm/c-variadic/sparc.rs +++ b/tests/assembly-llvm/c-variadic/sparc.rs @@ -7,6 +7,7 @@ //@ [SPARC64] compile-flags: -Copt-level=3 --target sparc64-unknown-linux-gnu //@ [SPARC64] needs-llvm-components: sparc #![feature(c_variadic, no_core, lang_items, intrinsics, rustc_attrs, asm_experimental_arch)] +#![cfg_attr(target_arch = "sparc", feature(c_variadic_experimental_arch))] #![no_core] #![crate_type = "lib"] From df8d02901415b91a7fe113a439c79f59cffc2952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Wed, 29 Apr 2026 12:11:15 +0200 Subject: [PATCH 14/17] rustc: target_features: allow for cfg-only stable target_features --- .../rustc_codegen_ssa/src/target_features.rs | 7 +++-- compiler/rustc_target/src/target_features.rs | 30 +++++++++++++++++-- 2 files changed, 31 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 24f731c01996d..47a262a10a44f 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -62,7 +62,7 @@ pub(crate) fn from_target_feature_attr( feature: feature_str, reason, }); - } else if let Some(nightly_feature) = stability.requires_nightly() + } else if let Some(nightly_feature) = stability.requires_nightly(/* in_cfg */ false) && !rust_features.enabled(nightly_feature) { feature_err( @@ -315,7 +315,7 @@ pub fn cfg_target_feature<'a, const N: usize>( enabled: if enable { "enabled" } else { "disabled" }, reason, }); - } else if stability.requires_nightly().is_some() { + } else if stability.requires_nightly(/* in_cfg */ false).is_some() { // An unstable feature. Warn about using it. It makes little sense // to hard-error here since we just warn about fully unknown // features above. @@ -346,7 +346,8 @@ pub fn cfg_target_feature<'a, const N: usize>( // "forbidden" features. if allow_unstable || (gate.in_cfg() - && (sess.is_nightly_build() || gate.requires_nightly().is_none())) + && (sess.is_nightly_build() + || gate.requires_nightly(/* in_cfg */ true).is_none())) { Some(Symbol::intern(feature)) } else { diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 963b167be424d..fedf9983fd703 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -17,6 +17,13 @@ pub enum Stability { /// This target feature is stable, it can be used in `#[target_feature]` and /// `#[cfg(target_feature)]`. Stable, + /// This target feature is cfg-stable. It can be used for `#[cfg(target_feature)]` on stable, + /// but using it in `#[target_feature]` requires the given nightly feature. + CfgStableToggleUnstable( + /// This must be a *language* feature, or else rustc will ICE when reporting a missing + /// feature gate! + Symbol, + ), /// This target feature is unstable. It is only present in `#[cfg(target_feature)]` on /// nightly and using it in `#[target_feature]` requires enabling the given nightly feature. Unstable( @@ -37,7 +44,12 @@ impl Stability { /// (It might still be nightly-only even if this returns `true`, so make sure to also check /// `requires_nightly`.) pub fn in_cfg(&self) -> bool { - matches!(self, Stability::Stable | Stability::Unstable { .. }) + matches!( + self, + Stability::Stable + | Stability::CfgStableToggleUnstable { .. } + | Stability::Unstable { .. } + ) } /// Returns the nightly feature that is required to toggle this target feature via @@ -48,9 +60,19 @@ impl Stability { /// Before calling this, ensure the feature is even permitted for this use: /// - for `#[target_feature]`/`-Ctarget-feature`, check `toggle_allowed()` /// - for `cfg(target_feature)`, check `in_cfg()` - pub fn requires_nightly(&self) -> Option { + /// + /// The `in_cfg` parameter is used to determine whether it will be used in + /// `cfg(target_feature)` (true) or `#[target_feature]`/`-Ctarget-feature` (false) + pub fn requires_nightly(&self, in_cfg: bool) -> Option { match *self { Stability::Unstable(nightly_feature) => Some(nightly_feature), + Stability::CfgStableToggleUnstable(nightly_feature) => { + if in_cfg { + None + } else { + Some(nightly_feature) + } + } Stability::Stable { .. } => None, Stability::Forbidden { .. } => panic!("forbidden features should not reach this far"), } @@ -61,7 +83,9 @@ impl Stability { /// `requires_nightly`.) pub fn toggle_allowed(&self) -> Result<(), &'static str> { match self { - Stability::Unstable(_) | Stability::Stable { .. } => Ok(()), + Stability::Unstable(_) + | Stability::CfgStableToggleUnstable(_) + | Stability::Stable { .. } => Ok(()), Stability::Forbidden { reason } => Err(reason), } } From ee9a01aecfc495260404096dca70e0cab7e91dc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rom=C3=A1n=20C=C3=A1rdenas=20Rodr=C3=ADguez?= Date: Mon, 4 May 2026 17:28:35 +0200 Subject: [PATCH 15/17] rustc: target_features: adapt compile errors and warnings for cfg-only stable features --- compiler/rustc_codegen_ssa/src/errors.rs | 3 ++- .../rustc_codegen_ssa/src/target_features.rs | 24 ++++++++++++------- compiler/rustc_target/src/target_features.rs | 6 +++++ 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs index f1112510af0f0..e6c8e5a4e3923 100644 --- a/compiler/rustc_codegen_ssa/src/errors.rs +++ b/compiler/rustc_codegen_ssa/src/errors.rs @@ -1194,9 +1194,10 @@ pub(crate) struct UnknownCTargetFeature<'a> { #[derive(Diagnostic)] #[diag("unstable feature specified for `-Ctarget-feature`: `{$feature}`")] -#[note("this feature is not stably supported; its behavior can change in the future")] +#[note("{$note}; its behavior can change in the future")] pub(crate) struct UnstableCTargetFeature<'a> { pub feature: &'a str, + pub note: &'a str, } #[derive(Diagnostic)] diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index 47a262a10a44f..b8adad9e71777 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -65,13 +65,12 @@ pub(crate) fn from_target_feature_attr( } else if let Some(nightly_feature) = stability.requires_nightly(/* in_cfg */ false) && !rust_features.enabled(nightly_feature) { - feature_err( - &tcx.sess, - nightly_feature, - feature_span, - format!("the target feature `{feature}` is currently unstable"), - ) - .emit(); + let explain = if stability.is_cfg_stable_toggle_unstable() { + format!("the target feature `{feature}` is allowed in cfg but unstable otherwise") + } else { + format!("the target feature `{feature}` is currently unstable") + }; + feature_err(&tcx.sess, nightly_feature, feature_span, explain).emit(); } else { // Add this and the implied features. for &name in tcx.implied_target_features(feature) { @@ -319,8 +318,15 @@ pub fn cfg_target_feature<'a, const N: usize>( // An unstable feature. Warn about using it. It makes little sense // to hard-error here since we just warn about fully unknown // features above. - sess.dcx() - .emit_warn(errors::UnstableCTargetFeature { feature: base_feature }); + let note = if stability.is_cfg_stable_toggle_unstable() { + "this feature is allowed in cfg but unstable otherwise" + } else { + "this feature is not stably supported" + }; + sess.dcx().emit_warn(errors::UnstableCTargetFeature { + feature: base_feature, + note, + }); } } } diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index fedf9983fd703..b1e365e2c821b 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -78,6 +78,12 @@ impl Stability { } } + /// Returns whether the feature is cfg-stable but still requires a nightly feature gate to + /// be used in `#[target_feature]`/`-Ctarget-feature`. + pub fn is_cfg_stable_toggle_unstable(&self) -> bool { + matches!(self, Stability::CfgStableToggleUnstable { .. }) + } + /// Returns whether the feature may be toggled via `#[target_feature]` or `-Ctarget-feature`. /// (It might still be nightly-only even if this returns `true`, so make sure to also check /// `requires_nightly`.) From 71177d1b669c32bcf668c81f4840b543f5352435 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 May 2026 10:30:16 +0200 Subject: [PATCH 16/17] Add NodeId to ModuleKind --- .../rustc_resolve/src/build_reduced_graph.rs | 18 ++++++---- compiler/rustc_resolve/src/diagnostics.rs | 28 ++++++++-------- compiler/rustc_resolve/src/ident.rs | 2 +- compiler/rustc_resolve/src/late.rs | 3 +- compiler/rustc_resolve/src/lib.rs | 33 ++++++++++++------- compiler/rustc_resolve/src/macros.rs | 2 +- 6 files changed, 51 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 4c307e8a6a3d7..524c9ce8ad5d7 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -9,8 +9,9 @@ use std::sync::Arc; use rustc_ast::visit::{self, AssocCtxt, Visitor, WalkItemKind}; use rustc_ast::{ - self as ast, AssocItem, AssocItemKind, Block, ConstItem, Delegation, Fn, ForeignItem, - ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, + self as ast, AssocItem, AssocItemKind, Block, ConstItem, DUMMY_NODE_ID, Delegation, Fn, + ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, + TyAlias, }; use rustc_attr_parsing::AttributeParser; use rustc_expand::base::ResolverExpand; @@ -168,7 +169,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let expn_id = self.cstore().expn_that_defined_untracked(self.tcx, def_id); let module = self.new_extern_module( parent, - ModuleKind::Def(def_kind, def_id, Some(self.tcx.item_name(def_id))), + ModuleKind::Def( + def_kind, + def_id, + DUMMY_NODE_ID, + Some(self.tcx.item_name(def_id)), + ), expn_id, self.def_span(def_id), // FIXME: Account for `#[no_implicit_prelude]` attributes. @@ -251,7 +257,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Any inherited visibility resolved directly inside an enum or trait // (i.e. variants, fields, and trait items) inherits from the visibility // of the enum or trait. - ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _) => { + ModuleKind::Def(DefKind::Enum | DefKind::Trait, def_id, _, _) => { self.tcx.visibility(def_id).expect_local() } // Otherwise, the visibility is restricted to the nearest parent `mod` item. @@ -848,7 +854,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } let module = self.r.new_local_module( Some(parent), - ModuleKind::Def(def_kind, def_id, Some(ident.name)), + ModuleKind::Def(def_kind, def_id, item.id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude @@ -882,7 +888,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { let module = self.r.new_local_module( Some(parent), - ModuleKind::Def(def_kind, def_id, Some(ident.name)), + ModuleKind::Def(def_kind, def_id, item.id, Some(ident.name)), expansion.to_expn_id(), item.span, parent.no_implicit_prelude, diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 7e1dd19167899..f891622d0baea 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -242,7 +242,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let container = match old_binding.parent_module.unwrap().kind { // Avoid using TyCtxt::def_kind_descr in the resolver, because it // indirectly *calls* the resolver, and would cause a query cycle. - ModuleKind::Def(kind, def_id, _) => kind.descr(def_id), + ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id), ModuleKind::Block => "block", }; @@ -1764,7 +1764,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } if ident.name == kw::Default - && let ModuleKind::Def(DefKind::Enum, def_id, _) = parent_scope.module.kind + && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind { let span = self.def_span(def_id); let source_map = self.tcx.sess.source_map(); @@ -1892,19 +1892,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { missing a `derive` attribute", ident.name, ); - let sugg_span = if let ModuleKind::Def(DefKind::Enum, id, _) = parent_scope.module.kind - { - let span = self.def_span(id); - if span.from_expansion() { - None + let sugg_span = + if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind { + let span = self.def_span(id); + if span.from_expansion() { + None + } else { + // For enum variants sugg_span is empty but we can get the enum's Span. + Some(span.shrink_to_lo()) + } } else { - // For enum variants sugg_span is empty but we can get the enum's Span. - Some(span.shrink_to_lo()) - } - } else { - // For items this `Span` will be populated, everything else it'll be None. - sugg_span - }; + // For items this `Span` will be populated, everything else it'll be None. + sugg_span + }; match sugg_span { Some(span) => { err.span_suggestion_verbose( diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 658e36083b0ad..1c43ca431d8bf 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -644,7 +644,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } Scope::ModuleGlobs(module, _) - if let ModuleKind::Def(_, def_id, _) = module.kind + if let ModuleKind::Def(_, def_id, _, _) = module.kind && !def_id.is_local() => { // Fast path: external module decoding only creates non-glob declarations. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 014a472c2c1bb..29a151b277d55 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1941,7 +1941,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { && let Some((module, _)) = &self.current_trait_ref && let Some(ty) = &self.diag_metadata.current_self_type && Some(true) == self.diag_metadata.in_non_gat_assoc_type - && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind + && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _, _) = + module.kind { if def_id_matches_path( self.r.tcx, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index b15e4b1b72774..af9a72b13c1d1 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -543,7 +543,7 @@ enum ModuleKind { /// The crate root will have `None` for the symbol. /// * A trait or an enum (it implicitly contains associated types, methods and variant /// constructors). - Def(DefKind, DefId, Option), + Def(DefKind, DefId, NodeId, Option), } impl ModuleKind { @@ -557,7 +557,7 @@ impl ModuleKind { fn opt_def_id(&self) -> Option { match self { - ModuleKind::Def(_, def_id, _) => Some(*def_id), + ModuleKind::Def(_, def_id, _, _) => Some(*def_id), _ => None, } } @@ -726,7 +726,7 @@ impl<'ra> ModuleData<'ra> { self_decl: Option>, ) -> Self { let is_foreign = match kind { - ModuleKind::Def(_, def_id, _) => !def_id.is_local(), + ModuleKind::Def(_, def_id, _, _) => !def_id.is_local(), ModuleKind::Block => false, }; ModuleData { @@ -756,7 +756,7 @@ impl<'ra> ModuleData<'ra> { fn res(&self) -> Option { match self.kind { - ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)), + ModuleKind::Def(kind, def_id, _, _) => Some(Res::Def(kind, def_id)), _ => None, } } @@ -813,11 +813,11 @@ impl<'ra> Module<'ra> { // `self` resolves to the first module ancestor that `is_normal`. fn is_normal(self) -> bool { - matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _)) + matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _, _)) } fn is_trait(self) -> bool { - matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _)) + matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _, _)) } fn nearest_item_scope(self) -> Module<'ra> { @@ -833,11 +833,20 @@ impl<'ra> Module<'ra> { /// This may be the crate root. fn nearest_parent_mod(self) -> DefId { match self.kind { - ModuleKind::Def(DefKind::Mod, def_id, _) => def_id, + ModuleKind::Def(DefKind::Mod, def_id, _, _) => def_id, _ => self.parent.expect("non-root module without parent").nearest_parent_mod(), } } + /// The [`NodeId`] of the nearest `mod` item ancestor (which may be this module). + /// This may be the crate root. + fn nearest_parent_mod_node_id(self) -> NodeId { + match self.kind { + ModuleKind::Def(DefKind::Mod, _, node_id, _) => node_id, + _ => self.parent.expect("non-root module without parent").nearest_parent_mod_node_id(), + } + } + fn is_ancestor_of(self, mut other: Self) -> bool { while self != other { if let Some(parent) = other.parent { @@ -852,7 +861,7 @@ impl<'ra> Module<'ra> { #[track_caller] fn expect_local(self) -> LocalModule<'ra> { match self.kind { - ModuleKind::Def(_, def_id, _) if !def_id.is_local() => { + ModuleKind::Def(_, def_id, _, _) if !def_id.is_local() => { panic!("`Module::expect_local` is called on a non-local module: {self:?}") } ModuleKind::Def(..) | ModuleKind::Block => LocalModule(self.0), @@ -862,7 +871,7 @@ impl<'ra> Module<'ra> { #[track_caller] fn expect_extern(self) -> ExternModule<'ra> { match self.kind { - ModuleKind::Def(_, def_id, _) if !def_id.is_local() => ExternModule(self.0), + ModuleKind::Def(_, def_id, _, _) if !def_id.is_local() => ExternModule(self.0), ModuleKind::Def(..) | ModuleKind::Block => { panic!("`Module::expect_extern` is called on a local module: {self:?}") } @@ -1551,7 +1560,7 @@ impl<'ra> ResolverArenas<'ra> { no_implicit_prelude: bool, ) -> Module<'ra> { let self_decl = match kind { - ModuleKind::Def(def_kind, def_id, _) => Some(self.new_def_decl( + ModuleKind::Def(def_kind, def_id, _, _) => Some(self.new_def_decl( Res::Def(def_kind, def_id), vis, span, @@ -1732,7 +1741,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let root_def_id = CRATE_DEF_ID.to_def_id(); let graph_root = arenas.new_module( None, - ModuleKind::Def(DefKind::Mod, root_def_id, None), + ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None), Visibility::Public, ExpnId::root(), crate_span, @@ -1743,7 +1752,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let local_module_map = FxIndexMap::from_iter([(CRATE_DEF_ID, graph_root)]); let empty_module = arenas.new_module( None, - ModuleKind::Def(DefKind::Mod, root_def_id, None), + ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None), Visibility::Public, ExpnId::root(), DUMMY_SP, diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index dd9f500ff88d0..d4349b9d73a77 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1185,7 +1185,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.get_mut().record_use(ident, fallback_binding, Used::Other); } else { let location = match parent_scope.module.kind { - ModuleKind::Def(kind, def_id, name) => { + ModuleKind::Def(kind, def_id, _, name) => { if let Some(name) = name { format!("{} `{name}`", kind.descr(def_id)) } else { From fd701b79a71a93a4df5f60262e249e23aa1648cb Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 May 2026 10:37:46 +0200 Subject: [PATCH 17/17] Remove most uses of `def_id_to_node_id` Especially those happening during normal resolving, where we are actually looking at current parent scopes --- compiler/rustc_resolve/src/diagnostics.rs | 15 ++++++++------- compiler/rustc_resolve/src/late.rs | 8 ++++---- compiler/rustc_resolve/src/lib.rs | 4 ++-- 3 files changed, 14 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index f891622d0baea..c082455380ce7 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -5,7 +5,8 @@ use std::ops::ControlFlow; use itertools::Itertools as _; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{ - self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path, join_path_idents, + self as ast, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, ItemKind, ModKind, NodeId, Path, + join_path_idents, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; @@ -192,11 +193,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } fn report_with_use_injections(&mut self, krate: &Crate) { - for UseError { mut err, candidates, def_id, instead, suggestion, path, is_call } in + for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in mem::take(&mut self.use_injections) { - let (span, found_use) = if let Some(def_id) = def_id.as_local() { - UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)) + let (span, found_use) = if node_id != DUMMY_NODE_ID { + UsePlacementFinder::check(krate, node_id) } else { (None, FoundUse::No) }; @@ -1705,9 +1706,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let import_suggestions = self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected); - let (span, found_use) = match parent_scope.module.nearest_parent_mod().as_local() { - Some(def_id) => UsePlacementFinder::check(krate, self.def_id_to_node_id(def_id)), - None => (None, FoundUse::No), + let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() { + DUMMY_NODE_ID => (None, FoundUse::No), + node_id => UsePlacementFinder::check(krate, node_id), }; show_candidates( self.tcx, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 29a151b277d55..3337a4626b040 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4515,7 +4515,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { parent_qself, ); - let def_id = this.parent_scope.module.nearest_parent_mod(); + let node_id = this.parent_scope.module.nearest_parent_mod_node_id(); let instead = res.is_some(); let (suggestion, const_err) = if let Some((start, end)) = this.diag_metadata.in_range @@ -4557,7 +4557,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let ue = UseError { err, candidates, - def_id, + node_id, instead, suggestion, path: path.into(), @@ -4646,7 +4646,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { parent_err.cancel(); - let def_id = this.parent_scope.module.nearest_parent_mod(); + let node_id = this.parent_scope.module.nearest_parent_mod_node_id(); if this.should_report_errs() { if candidates.is_empty() { @@ -4671,7 +4671,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.r.use_injections.push(UseError { err, candidates, - def_id, + node_id, instead: false, suggestion: None, path: prefix_path.into(), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index af9a72b13c1d1..f5f063ecaf458 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1001,8 +1001,8 @@ struct UseError<'a> { err: Diag<'a>, /// Candidates which user could `use` to access the missing type. candidates: Vec, - /// The `DefId` of the module to place the use-statements in. - def_id: DefId, + /// The `NodeId` of the module to place the use-statements in. + node_id: NodeId, /// Whether the diagnostic should say "instead" (as in `consider importing ... instead`). instead: bool, /// Extra free-form suggestion.