From 87f9e6ed761e906bef9f11432773343de292218e Mon Sep 17 00:00:00 2001 From: Aelin Reidel Date: Sun, 11 Oct 2026 00:24:44 +0200 Subject: [PATCH 01/16] tests: Ignore dynamic-loading-cdylib on musl hosts This test assumes that dlclose runs the destructors of thread locals and is more than the no-op implementation that musl provides. There is not a lot of value in this test on musl hosts, so ignoring it seems appropriate to me. See https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries for more details on dlclose in musl. --- tests/run-make/dynamic-loading-cdylib/rmake.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/run-make/dynamic-loading-cdylib/rmake.rs b/tests/run-make/dynamic-loading-cdylib/rmake.rs index ffd91e4a6ebc0..59c1135b08bad 100644 --- a/tests/run-make/dynamic-loading-cdylib/rmake.rs +++ b/tests/run-make/dynamic-loading-cdylib/rmake.rs @@ -4,8 +4,12 @@ // // - `foo.rs` is a cdylib. // - `load_and_unload.rs` is a binary that loads and unloads the cdylib. +// +// This test is ignored on musl hosts because musl's dlclose is a no-op and +// therefore destructors won't run when the library is unloaded. //@ ignore-cross-compile +//@ ignore-musl use run_make_support::{diff, run_with_args, rustc}; From 250643c0b1fbd1405208c4fdbdce98d468314bca Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 11 Oct 2026 20:45:08 +0200 Subject: [PATCH 02/16] More `tests/rustdoc-html` cleanups --- tests/rustdoc-html/README.md | 4 ++++ .../{ => display}/auxiliary/ext-repr.rs | 0 tests/rustdoc-html/{ => display}/repr.rs | 0 .../rustdoc-html/{ => display}/test-parens.rs | 0 tests/rustdoc-html/{ => fn}/const-fn-76501.rs | 0 .../rustdoc-html/{ => fn}/const-fn-effects.rs | 0 tests/rustdoc-html/{ => fn}/const-fn.rs | 0 tests/rustdoc-html/{ => fn}/fn-bound.rs | 0 .../{ => fn}/fn-pointer-arg-name.rs | 0 tests/rustdoc-html/{ => fn}/fn-type.rs | 0 .../intra-doc/auxiliary/all-item-types.rs | 22 +++++++++++++++++++ .../{ => intra-doc}/cross-crate-links.rs | 0 .../{ => struct}/empty-tuple-struct-118180.rs | 0 .../{ => struct}/tuple-struct-fields-doc.rs | 0 .../tuple-struct-where-clause-34928.rs | 0 15 files changed, 26 insertions(+) rename tests/rustdoc-html/{ => display}/auxiliary/ext-repr.rs (100%) rename tests/rustdoc-html/{ => display}/repr.rs (100%) rename tests/rustdoc-html/{ => display}/test-parens.rs (100%) rename tests/rustdoc-html/{ => fn}/const-fn-76501.rs (100%) rename tests/rustdoc-html/{ => fn}/const-fn-effects.rs (100%) rename tests/rustdoc-html/{ => fn}/const-fn.rs (100%) rename tests/rustdoc-html/{ => fn}/fn-bound.rs (100%) rename tests/rustdoc-html/{ => fn}/fn-pointer-arg-name.rs (100%) rename tests/rustdoc-html/{ => fn}/fn-type.rs (100%) create mode 100644 tests/rustdoc-html/intra-doc/auxiliary/all-item-types.rs rename tests/rustdoc-html/{ => intra-doc}/cross-crate-links.rs (100%) rename tests/rustdoc-html/{ => struct}/empty-tuple-struct-118180.rs (100%) rename tests/rustdoc-html/{ => struct}/tuple-struct-fields-doc.rs (100%) rename tests/rustdoc-html/{ => struct}/tuple-struct-where-clause-34928.rs (100%) diff --git a/tests/rustdoc-html/README.md b/tests/rustdoc-html/README.md index 9ac5e8c36fd71..b681a7e9d4d8e 100644 --- a/tests/rustdoc-html/README.md +++ b/tests/rustdoc-html/README.md @@ -65,6 +65,10 @@ Contains tests for the rendering of enum types and in particular its variants. Contains tests to check how extern items (like `extern "C"` functions) are rendered. +## `tests/rustdoc-html/fn` + +Same as `tests/rustdoc-html/enum` but for function items. + ## `tests/rustdoc-html/footnote` Contains tests checking the markdown footnote features and how it is rendered. diff --git a/tests/rustdoc-html/auxiliary/ext-repr.rs b/tests/rustdoc-html/display/auxiliary/ext-repr.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/ext-repr.rs rename to tests/rustdoc-html/display/auxiliary/ext-repr.rs diff --git a/tests/rustdoc-html/repr.rs b/tests/rustdoc-html/display/repr.rs similarity index 100% rename from tests/rustdoc-html/repr.rs rename to tests/rustdoc-html/display/repr.rs diff --git a/tests/rustdoc-html/test-parens.rs b/tests/rustdoc-html/display/test-parens.rs similarity index 100% rename from tests/rustdoc-html/test-parens.rs rename to tests/rustdoc-html/display/test-parens.rs diff --git a/tests/rustdoc-html/const-fn-76501.rs b/tests/rustdoc-html/fn/const-fn-76501.rs similarity index 100% rename from tests/rustdoc-html/const-fn-76501.rs rename to tests/rustdoc-html/fn/const-fn-76501.rs diff --git a/tests/rustdoc-html/const-fn-effects.rs b/tests/rustdoc-html/fn/const-fn-effects.rs similarity index 100% rename from tests/rustdoc-html/const-fn-effects.rs rename to tests/rustdoc-html/fn/const-fn-effects.rs diff --git a/tests/rustdoc-html/const-fn.rs b/tests/rustdoc-html/fn/const-fn.rs similarity index 100% rename from tests/rustdoc-html/const-fn.rs rename to tests/rustdoc-html/fn/const-fn.rs diff --git a/tests/rustdoc-html/fn-bound.rs b/tests/rustdoc-html/fn/fn-bound.rs similarity index 100% rename from tests/rustdoc-html/fn-bound.rs rename to tests/rustdoc-html/fn/fn-bound.rs diff --git a/tests/rustdoc-html/fn-pointer-arg-name.rs b/tests/rustdoc-html/fn/fn-pointer-arg-name.rs similarity index 100% rename from tests/rustdoc-html/fn-pointer-arg-name.rs rename to tests/rustdoc-html/fn/fn-pointer-arg-name.rs diff --git a/tests/rustdoc-html/fn-type.rs b/tests/rustdoc-html/fn/fn-type.rs similarity index 100% rename from tests/rustdoc-html/fn-type.rs rename to tests/rustdoc-html/fn/fn-type.rs diff --git a/tests/rustdoc-html/intra-doc/auxiliary/all-item-types.rs b/tests/rustdoc-html/intra-doc/auxiliary/all-item-types.rs new file mode 100644 index 0000000000000..f94bd998717a0 --- /dev/null +++ b/tests/rustdoc-html/intra-doc/auxiliary/all-item-types.rs @@ -0,0 +1,22 @@ +#![feature(extern_types)] + +pub mod foo_mod {} +extern "C" { + pub fn foo_ffn(); + pub static FOO_FSTATIC: FooStruct; + pub type FooFType; +} +pub fn foo_fn() {} +pub trait FooTrait {} +pub struct FooStruct; +pub enum FooEnum {} +pub union FooUnion { + x: (), +} +pub type FooType = FooStruct; +pub static FOO_STATIC: FooStruct = FooStruct; +pub const FOO_CONSTANT: FooStruct = FooStruct; +#[macro_export] +macro_rules! foo_macro { + () => (); +} diff --git a/tests/rustdoc-html/cross-crate-links.rs b/tests/rustdoc-html/intra-doc/cross-crate-links.rs similarity index 100% rename from tests/rustdoc-html/cross-crate-links.rs rename to tests/rustdoc-html/intra-doc/cross-crate-links.rs diff --git a/tests/rustdoc-html/empty-tuple-struct-118180.rs b/tests/rustdoc-html/struct/empty-tuple-struct-118180.rs similarity index 100% rename from tests/rustdoc-html/empty-tuple-struct-118180.rs rename to tests/rustdoc-html/struct/empty-tuple-struct-118180.rs diff --git a/tests/rustdoc-html/tuple-struct-fields-doc.rs b/tests/rustdoc-html/struct/tuple-struct-fields-doc.rs similarity index 100% rename from tests/rustdoc-html/tuple-struct-fields-doc.rs rename to tests/rustdoc-html/struct/tuple-struct-fields-doc.rs diff --git a/tests/rustdoc-html/tuple-struct-where-clause-34928.rs b/tests/rustdoc-html/struct/tuple-struct-where-clause-34928.rs similarity index 100% rename from tests/rustdoc-html/tuple-struct-where-clause-34928.rs rename to tests/rustdoc-html/struct/tuple-struct-where-clause-34928.rs From f3ace4091aa71d30602780fe6fe86db89dcd7a14 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Oct 2026 02:31:12 +0000 Subject: [PATCH 03/16] Tweak wording to not mention closures unnecessarily Modify `on_unimplemented` attribute wording for `Fn*` traits. --- library/core/src/ops/function.rs | 12 +++++------ tests/ui/abi/bad-custom.rs | 2 +- tests/ui/abi/bad-custom.stderr | 2 +- .../normalization-ice-issue-149746.rs | 8 ++++---- .../normalization-ice-issue-149746.stderr | 16 +++++++-------- tests/ui/async-await/async-fn/impl-header.rs | 2 +- .../async-await/async-fn/impl-header.stderr | 4 ++-- tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs | 2 +- .../ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr | 4 ++-- tests/ui/closures/closure-expected.rs | 2 +- tests/ui/closures/closure-expected.stderr | 4 ++-- ...e-ref-fn-kind-mismatch-issue-161327.stderr | 12 +++++------ .../closures/coerce-unsafe-to-closure.stderr | 2 +- .../block_instead_of_closure_in_arg.rs | 2 +- .../block_instead_of_closure_in_arg.stderr | 4 ++-- .../ruby_style_closure_successful_parse.rs | 2 +- ...ruby_style_closure_successful_parse.stderr | 4 ++-- tests/ui/extern/extern-wrong-value-type.rs | 2 +- .../ui/extern/extern-wrong-value-type.stderr | 4 ++-- ...ture-gate-unboxed-closures-manual-impls.rs | 4 ++-- ...-gate-unboxed-closures-manual-impls.stderr | 8 ++++---- tests/ui/fn/fn-trait-formatting.rs | 2 +- tests/ui/fn/fn-trait-formatting.stderr | 4 ++-- tests/ui/fn/issue-39259.rs | 2 +- tests/ui/fn/issue-39259.stderr | 4 ++-- .../issue-68642-broken-llvm-ir.rs | 2 +- .../issue-68642-broken-llvm-ir.stderr | 4 ++-- .../issue-68643-broken-mir.rs | 2 +- .../issue-68643-broken-mir.stderr | 4 ++-- .../issue-68644-codegen-selection.rs | 2 +- .../issue-68644-codegen-selection.stderr | 4 ++-- .../issue-68645-codegen-fulfillment.rs | 2 +- .../issue-68645-codegen-fulfillment.stderr | 4 ++-- .../normalize-under-binder/issue-62529-3.rs | 2 +- .../issue-62529-3.stderr | 4 ++-- tests/ui/implied-bounds/issue-100690.rs | 2 +- tests/ui/implied-bounds/issue-100690.stderr | 4 ++-- tests/ui/intrinsics/const-eval-select-bad.rs | 4 ++-- .../intrinsics/const-eval-select-bad.stderr | 8 ++++---- .../fold-iterator-error-23966.stderr | 4 ++-- .../ui/lifetimes/issue-76168-hr-outlives-3.rs | 2 +- .../issue-76168-hr-outlives-3.stderr | 4 ++-- tests/ui/lifetimes/issue-95023.rs | 2 +- tests/ui/lifetimes/issue-95023.stderr | 4 ++-- tests/ui/methods/filter-relevant-fn-bounds.rs | 2 +- .../methods/filter-relevant-fn-bounds.stderr | 4 ++-- ...estion-trait-with-extra-generics-no-ice.rs | 2 +- ...on-trait-with-extra-generics-no-ice.stderr | 4 ++-- ...rg-type-mismatch-issue-45727.current.fixed | 4 ++-- ...-arg-type-mismatch-issue-45727.next.stderr | 8 ++++---- .../closure-arg-type-mismatch-issue-45727.rs | 4 ++-- .../suggest-option-asderef-unfixable.rs | 4 ++-- .../suggest-option-asderef-unfixable.stderr | 6 +++--- .../ui/trait-bounds/mismatch-fn-trait.stderr | 20 +++++++++---------- .../check-trait-object-bounds-2.rs | 2 +- .../check-trait-object-bounds-2.stderr | 4 ++-- tests/ui/traits/issue-87558.rs | 2 +- tests/ui/traits/issue-87558.stderr | 4 ++-- .../const-host-effect-hrtb-no-ice.rs | 2 +- .../const-host-effect-hrtb-no-ice.stderr | 4 ++-- tests/ui/traits/next-solver/fn-trait.rs | 8 ++++---- tests/ui/traits/next-solver/fn-trait.stderr | 12 +++++------ tests/ui/type-alias-impl-trait/issue-63279.rs | 4 ++-- .../type-alias-impl-trait/issue-63279.stderr | 8 ++++---- .../lazy_subtyping_of_opaques.rs | 4 ++-- .../lazy_subtyping_of_opaques.stderr | 8 ++++---- tests/ui/typeck/issue-116864.current.stderr | 4 ++-- tests/ui/typeck/issue-116864.next.stderr | 4 ++-- tests/ui/typeck/issue-116864.rs | 4 ++-- .../unboxed-closures-fnmut-as-fn.stderr | 4 ++-- .../unboxed-closures-unsafe-extern-fn.stderr | 6 +++--- .../unboxed-closures-wrong-abi.stderr | 12 +++++------ ...d-closures-wrong-arg-type-extern-fn.stderr | 6 +++--- ...losure-trait-ice-in-wfcheck-diagnostics.rs | 4 ++-- ...re-trait-ice-in-wfcheck-diagnostics.stderr | 8 ++++---- 75 files changed, 175 insertions(+), 175 deletions(-) diff --git a/library/core/src/ops/function.rs b/library/core/src/ops/function.rs index d40603e15bb1b..6c0d96ace2a4d 100644 --- a/library/core/src/ops/function.rs +++ b/library/core/src/ops/function.rs @@ -67,8 +67,8 @@ use crate::ptr::NonNull; // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" ), - message = "expected an `{This:resolved}` closure, found `{Self}`", - label = "expected an `{This:resolved}` closure, found `{Self}`" + message = "expected `{This:resolved}` signature, found `{Self}`", + label = "expected `{This:resolved}` signature, found `{Self}`" )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] @@ -154,8 +154,8 @@ pub const trait Fn: [const] FnMut { // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" ), - message = "expected an `{This:resolved}` closure, found `{Self}`", - label = "expected an `{This:resolved}` closure, found `{Self}`" + message = "expected `{This:resolved}` signature, found `{Self}`", + label = "expected `{This:resolved}` signature, found `{Self}`" )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] @@ -233,8 +233,8 @@ pub const trait FnMut: FnOnce { // SAFETY: tidy is not smart enough to tell that the below unsafe block is a string label = "call the function in a closure: `|| unsafe {{ /* code */ }}`" ), - message = "expected an `{This:resolved}` closure, found `{Self}`", - label = "expected an `{This:resolved}` closure, found `{Self}`" + message = "expected `{This:resolved}` signature, found `{Self}`", + label = "expected `{This:resolved}` signature, found `{Self}`" )] #[fundamental] // so that regex can rely that `&str: !FnMut` #[must_use = "closures are lazy and do nothing unless called"] diff --git a/tests/ui/abi/bad-custom.rs b/tests/ui/abi/bad-custom.rs index 93c054a8c900f..b4d2325683b44 100644 --- a/tests/ui/abi/bad-custom.rs +++ b/tests/ui/abi/bad-custom.rs @@ -142,7 +142,7 @@ async unsafe extern "custom" fn no_async_fn() { } fn no_promotion_to_fn_trait(f: unsafe extern "custom" fn()) -> impl Fn() { - //~^ ERROR expected an `Fn()` closure, found `unsafe extern "custom" fn()` + //~^ ERROR expected `Fn()` signature, found `unsafe extern "custom" fn()` f } diff --git a/tests/ui/abi/bad-custom.stderr b/tests/ui/abi/bad-custom.stderr index 472c0041234e6..64e2c642da0d8 100644 --- a/tests/ui/abi/bad-custom.stderr +++ b/tests/ui/abi/bad-custom.stderr @@ -418,7 +418,7 @@ LL | unsafe extern "custom" fn no_cold_attribute() { | | | `extern "custom"` because of this -error[E0277]: expected an `Fn()` closure, found `unsafe extern "custom" fn()` +error[E0277]: expected `Fn()` signature, found `unsafe extern "custom" fn()` --> $DIR/bad-custom.rs:144:64 | LL | fn no_promotion_to_fn_trait(f: unsafe extern "custom" fn()) -> impl Fn() { diff --git a/tests/ui/associated-types/normalization-ice-issue-149746.rs b/tests/ui/associated-types/normalization-ice-issue-149746.rs index 29661092b5751..b71342e959611 100644 --- a/tests/ui/associated-types/normalization-ice-issue-149746.rs +++ b/tests/ui/associated-types/normalization-ice-issue-149746.rs @@ -4,14 +4,14 @@ trait Owner { type Ty; } impl Owner for () { type Ty = T; } pub struct Warns { _significant_drop: <() as Owner>::Ty, - //~^ ERROR expected an `FnMut()` closure, found `T` + //~^ ERROR expected `FnMut()` signature, found `T` field: String, } pub fn test(w: Warns) { - //~^ ERROR expected an `FnMut()` closure, found `T` + //~^ ERROR expected `FnMut()` signature, found `T` _ = || w.field - //~^ ERROR expected an `FnMut()` closure, found `T` - //~| ERROR expected an `FnMut()` closure, found `T` + //~^ ERROR expected `FnMut()` signature, found `T` + //~| ERROR expected `FnMut()` signature, found `T` //~| WARN: changes to closure capture in Rust 2021 will affect drop order } fn main() {} diff --git a/tests/ui/associated-types/normalization-ice-issue-149746.stderr b/tests/ui/associated-types/normalization-ice-issue-149746.stderr index ae6f6bbbb52c9..491da39e425bf 100644 --- a/tests/ui/associated-types/normalization-ice-issue-149746.stderr +++ b/tests/ui/associated-types/normalization-ice-issue-149746.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnMut()` closure, found `T` +error[E0277]: expected `FnMut()` signature, found `T` --> $DIR/normalization-ice-issue-149746.rs:6:24 | LL | _significant_drop: <() as Owner>::Ty, - | ^^^^^^^^^^^^^^^^^^^^ expected an `FnMut()` closure, found `T` + | ^^^^^^^^^^^^^^^^^^^^ expected `FnMut()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Owner::Ty` @@ -35,11 +35,11 @@ help: add a dummy let to cause `w` to be fully captured LL | _ = || { let _ = &w; w.field } | +++++++++++++ + -error[E0277]: expected an `FnMut()` closure, found `T` +error[E0277]: expected `FnMut()` signature, found `T` --> $DIR/normalization-ice-issue-149746.rs:12:9 | LL | _ = || w.field - | ^^^^^^^^^^ expected an `FnMut()` closure, found `T` + | ^^^^^^^^^^ expected `FnMut()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Owner::Ty` @@ -48,11 +48,11 @@ note: required by a bound in `Owner::Ty` LL | trait Owner { type Ty; } | ^^^^^^^ required by this bound in `Owner::Ty` -error[E0277]: expected an `FnMut()` closure, found `T` +error[E0277]: expected `FnMut()` signature, found `T` --> $DIR/normalization-ice-issue-149746.rs:10:16 | LL | pub fn test(w: Warns) { - | ^ expected an `FnMut()` closure, found `T` + | ^ expected `FnMut()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Owner::Ty` @@ -61,11 +61,11 @@ note: required by a bound in `Owner::Ty` LL | trait Owner { type Ty; } | ^^^^^^^ required by this bound in `Owner::Ty` -error[E0277]: expected an `FnMut()` closure, found `T` +error[E0277]: expected `FnMut()` signature, found `T` --> $DIR/normalization-ice-issue-149746.rs:12:9 | LL | _ = || w.field - | ^^^^^^^^^^ expected an `FnMut()` closure, found `T` + | ^^^^^^^^^^ expected `FnMut()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Owner::Ty` diff --git a/tests/ui/async-await/async-fn/impl-header.rs b/tests/ui/async-await/async-fn/impl-header.rs index 349a875d4a6c4..ceb85c82f6f71 100644 --- a/tests/ui/async-await/async-fn/impl-header.rs +++ b/tests/ui/async-await/async-fn/impl-header.rs @@ -6,7 +6,7 @@ impl async Fn<()> for F {} //~^ ERROR `async` trait implementations are unsupported //~| ERROR the precise format of `Fn`-family traits' type parameters is subject to change //~| ERROR manual implementations of `Fn` are experimental -//~| ERROR expected an `FnMut()` closure, found `F` +//~| ERROR expected `FnMut()` signature, found `F` //~| ERROR not all trait items implemented, missing: `call` fn main() {} diff --git a/tests/ui/async-await/async-fn/impl-header.stderr b/tests/ui/async-await/async-fn/impl-header.stderr index 3f35b9d99d1e5..bed40c4aea3f0 100644 --- a/tests/ui/async-await/async-fn/impl-header.stderr +++ b/tests/ui/async-await/async-fn/impl-header.stderr @@ -30,11 +30,11 @@ LL | impl async Fn<()> for F {} | = help: implement the missing item: `fn call(&self, _: ()) -> >::Output { todo!() }` (unstable, requires feature `fn_traits`) -error[E0277]: expected an `FnMut()` closure, found `F` +error[E0277]: expected `FnMut()` signature, found `F` --> $DIR/impl-header.rs:5:23 | LL | impl async Fn<()> for F {} - | ^ expected an `FnMut()` closure, found `F` + | ^ expected `FnMut()` signature, found `F` | help: the trait `FnMut()` is not implemented for `F` --> $DIR/impl-header.rs:3:1 diff --git a/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs index d966781f90d9f..ad86c1a1ebd3b 100644 --- a/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs +++ b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.rs @@ -4,6 +4,6 @@ fn main() { let ptr: *mut () = core::ptr::null_mut(); let _: &mut dyn Fn() = unsafe { &mut *(ptr as *mut dyn Fn()) - //~^ ERROR expected an `Fn()` closure, found `()` + //~^ ERROR expected `Fn()` signature, found `()` }; } diff --git a/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr index a830ddc4468ff..e747ef059c195 100644 --- a/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr +++ b/tests/ui/cast/raw-ptr-to-dyn-fn-raw-ptr.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `()` +error[E0277]: expected `Fn()` signature, found `()` --> $DIR/raw-ptr-to-dyn-fn-raw-ptr.rs:6:16 | LL | &mut *(ptr as *mut dyn Fn()) - | ^^^ expected an `Fn()` closure, found `()` + | ^^^ expected `Fn()` signature, found `()` | = help: the trait `Fn()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` diff --git a/tests/ui/closures/closure-expected.rs b/tests/ui/closures/closure-expected.rs index 4fc1b3a1fd006..7c3b703bcaadb 100644 --- a/tests/ui/closures/closure-expected.rs +++ b/tests/ui/closures/closure-expected.rs @@ -1,5 +1,5 @@ fn main() { let x = Some(1); let y = x.or_else(4); - //~^ ERROR expected an `FnOnce()` closure, found `{integer}` + //~^ ERROR expected `FnOnce()` signature, found `{integer}` } diff --git a/tests/ui/closures/closure-expected.stderr b/tests/ui/closures/closure-expected.stderr index 490988f247cdd..c6d414c705efa 100644 --- a/tests/ui/closures/closure-expected.stderr +++ b/tests/ui/closures/closure-expected.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnOnce()` closure, found `{integer}` +error[E0277]: expected `FnOnce()` signature, found `{integer}` --> $DIR/closure-expected.rs:3:23 | LL | let y = x.or_else(4); - | ------- ^ expected an `FnOnce()` closure, found `{integer}` + | ------- ^ expected `FnOnce()` signature, found `{integer}` | | | required by a bound introduced by this call | diff --git a/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr index dfc657f6c3a00..4e1ce7b78b7b1 100644 --- a/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr +++ b/tests/ui/closures/closure-ref-fn-kind-mismatch-issue-161327.stderr @@ -79,11 +79,11 @@ note: required by a bound in `req_fn` LL | fn req_fn(_: impl Fn(&'static str) -> String) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `req_fn` -error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` +error[E0277]: expected `Fn(&'static str)` signature, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:46:12 | LL | req_fn(&mut pure_closure); - | ------ ^^^^^^^^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` + | ------ ^^^^^^^^^^^^^^^^^ expected `Fn(&'static str)` signature, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:45:28: 45:45}` | | | required by a bound introduced by this call | @@ -99,11 +99,11 @@ LL - req_fn(&mut pure_closure); LL + req_fn(pure_closure); | -error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` +error[E0277]: expected `Fn(&'static str)` signature, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:59:12 | LL | req_fn(&mut outer); - | ------ ^^^^^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` + | ------ ^^^^^^^^^^ expected `Fn(&'static str)` signature, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:53:21: 53:25}` | | | required by a bound introduced by this call | @@ -119,11 +119,11 @@ LL - req_fn(&mut outer); LL + req_fn(outer); | -error[E0277]: expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` +error[E0277]: expected `Fn(&'static str)` signature, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` --> $DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:69:12 | LL | req_fn(&mut c); - | ------ ^^^^^^ expected an `Fn(&'static str)` closure, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` + | ------ ^^^^^^ expected `Fn(&'static str)` signature, found `&mut {closure@$DIR/closure-ref-fn-kind-mismatch-issue-161327.rs:65:17: 65:21}` | | | required by a bound introduced by this call | diff --git a/tests/ui/closures/coerce-unsafe-to-closure.stderr b/tests/ui/closures/coerce-unsafe-to-closure.stderr index 2bf2739be52d6..b232b4e46d462 100644 --- a/tests/ui/closures/coerce-unsafe-to-closure.stderr +++ b/tests/ui/closures/coerce-unsafe-to-closure.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `FnOnce(&str)` closure, found `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` +error[E0277]: expected `FnOnce(&str)` signature, found `unsafe fn(_) -> _ {std::intrinsics::transmute::<_, _>}` --> $DIR/coerce-unsafe-to-closure.rs:2:44 | LL | let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); diff --git a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.rs b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.rs index 94c6c85d28d27..310ad21bbf910 100644 --- a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.rs +++ b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.rs @@ -1,6 +1,6 @@ fn main() { let number = 2; - Some(true).filter({ //~ ERROR expected an `FnOnce(&bool)` closure, found `bool` + Some(true).filter({ //~ ERROR expected `FnOnce(&bool)` signature, found `bool` if number % 2 == 0 { number == 0 } else { diff --git a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr index b8b4a0a17bcf6..df7103f857303 100644 --- a/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr +++ b/tests/ui/expr/malformed_closure/block_instead_of_closure_in_arg.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `FnOnce(&bool)` closure, found `bool` +error[E0277]: expected `FnOnce(&bool)` signature, found `bool` --> $DIR/block_instead_of_closure_in_arg.rs:3:23 | LL | Some(true).filter({ @@ -12,7 +12,7 @@ LL | || number != 0 LL | || } | ||_________- this tail expression is of type `bool` LL | | }); - | |______^ expected an `FnOnce(&bool)` closure, found `bool` + | |______^ expected `FnOnce(&bool)` signature, found `bool` | = help: the trait `for<'a> FnOnce(&'a bool)` is not implemented for `bool` note: required by a bound in `Option::::filter` diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.rs b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.rs index faad88764bf98..4215d4469a303 100644 --- a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.rs +++ b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.rs @@ -1,6 +1,6 @@ const x: usize =42; fn main() { - let p = Some(45).and_then({|x| //~ ERROR expected an `FnOnce({integer})` closure, found `Option` + let p = Some(45).and_then({|x| //~ ERROR expected `FnOnce({integer})` signature, found `Option` 1 + 1; Some(x * 2) }); diff --git a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr index ea41e77952ff5..0e4ac960e3c05 100644 --- a/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr +++ b/tests/ui/expr/malformed_closure/ruby_style_closure_successful_parse.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `FnOnce({integer})` closure, found `Option` +error[E0277]: expected `FnOnce({integer})` signature, found `Option` --> $DIR/ruby_style_closure_successful_parse.rs:3:31 | LL | let p = Some(45).and_then({|x| @@ -9,7 +9,7 @@ LL | | 1 + 1; LL | | Some(x * 2) | | ----------- this tail expression is of type `Option` LL | | }); - | |_____^ expected an `FnOnce({integer})` closure, found `Option` + | |_____^ expected `FnOnce({integer})` signature, found `Option` | = help: the trait `FnOnce({integer})` is not implemented for `Option` note: required by a bound in `Option::::and_then` diff --git a/tests/ui/extern/extern-wrong-value-type.rs b/tests/ui/extern/extern-wrong-value-type.rs index ae07a721e83ee..38a77a697fe51 100644 --- a/tests/ui/extern/extern-wrong-value-type.rs +++ b/tests/ui/extern/extern-wrong-value-type.rs @@ -7,5 +7,5 @@ fn main() { // extern functions are extern "C" fn let _x: extern "C" fn() = f; // OK is_fn(f); - //~^ ERROR expected an `Fn()` closure, found `extern "C" fn() {f}` + //~^ ERROR expected `Fn()` signature, found `extern "C" fn() {f}` } diff --git a/tests/ui/extern/extern-wrong-value-type.stderr b/tests/ui/extern/extern-wrong-value-type.stderr index e1686f8a3ab9b..0330992e62f06 100644 --- a/tests/ui/extern/extern-wrong-value-type.stderr +++ b/tests/ui/extern/extern-wrong-value-type.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `extern "C" fn() {f}` +error[E0277]: expected `Fn()` signature, found `extern "C" fn() {f}` --> $DIR/extern-wrong-value-type.rs:9:11 | LL | is_fn(f); - | ----- ^ expected an `Fn()` closure, found `extern "C" fn() {f}` + | ----- ^ expected `Fn()` signature, found `extern "C" fn() {f}` | | | required by a bound introduced by this call | diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs index d33625f06872e..9d77c4a818958 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs @@ -9,7 +9,7 @@ struct Foo; impl Fn<()> for Foo { //~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change //~| ERROR manual implementations of `Fn` are experimental - //~| ERROR expected an `FnMut()` closure, found `Foo` + //~| ERROR expected `FnMut()` signature, found `Foo` extern "rust-call" fn call(self, args: ()) -> () {} //~^ ERROR "rust-call" ABI is experimental and subject to change //~| ERROR `call` has an incompatible type for trait @@ -26,7 +26,7 @@ struct Bar; impl FnMut<()> for Bar { //~^ ERROR the precise format of `Fn`-family traits' type parameters is subject to change //~| ERROR manual implementations of `FnMut` are experimental - //~| ERROR expected an `FnOnce()` closure, found `Bar` + //~| ERROR expected `FnOnce()` signature, found `Bar` extern "rust-call" fn call_mut(&self, args: ()) -> () {} //~^ ERROR "rust-call" ABI is experimental and subject to change //~| ERROR incompatible type for trait diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr index 56cfd6d0c52b9..f844bdbc2cb21 100644 --- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr +++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr @@ -87,11 +87,11 @@ LL | impl FnMut<()> for Bar { | = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable -error[E0277]: expected an `FnMut()` closure, found `Foo` +error[E0277]: expected `FnMut()` signature, found `Foo` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:9:17 | LL | impl Fn<()> for Foo { - | ^^^ expected an `FnMut()` closure, found `Foo` + | ^^^ expected `FnMut()` signature, found `Foo` | help: the trait `FnMut()` is not implemented for `Foo` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:8:1 @@ -161,11 +161,11 @@ help: change the self-receiver type to match the trait LL | extern "rust-call" fn call_mut(&mut self, args: ()) -> () {} | +++ -error[E0277]: expected an `FnOnce()` closure, found `Bar` +error[E0277]: expected `FnOnce()` signature, found `Bar` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:26:20 | LL | impl FnMut<()> for Bar { - | ^^^ expected an `FnOnce()` closure, found `Bar` + | ^^^ expected `FnOnce()` signature, found `Bar` | help: the trait `FnOnce()` is not implemented for `Bar` --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:25:1 diff --git a/tests/ui/fn/fn-trait-formatting.rs b/tests/ui/fn/fn-trait-formatting.rs index a7b00491ade01..f04a0184b0be4 100644 --- a/tests/ui/fn/fn-trait-formatting.rs +++ b/tests/ui/fn/fn-trait-formatting.rs @@ -17,5 +17,5 @@ fn main() { //~| NOTE found struct `Box isize>` needs_fn(1); - //~^ ERROR expected an `Fn(isize)` closure, found `{integer}` + //~^ ERROR expected `Fn(isize)` signature, found `{integer}` } diff --git a/tests/ui/fn/fn-trait-formatting.stderr b/tests/ui/fn/fn-trait-formatting.stderr index 0b86634a52e56..b654b4a32c327 100644 --- a/tests/ui/fn/fn-trait-formatting.stderr +++ b/tests/ui/fn/fn-trait-formatting.stderr @@ -39,11 +39,11 @@ LL | let _: () = Box::new(|| -> isize { unimplemented!() }) as Box isize>` -error[E0277]: expected an `Fn(isize)` closure, found `{integer}` +error[E0277]: expected `Fn(isize)` signature, found `{integer}` --> $DIR/fn-trait-formatting.rs:19:14 | LL | needs_fn(1); - | -------- ^ expected an `Fn(isize)` closure, found `{integer}` + | -------- ^ expected `Fn(isize)` signature, found `{integer}` | | | required by a bound introduced by this call | diff --git a/tests/ui/fn/issue-39259.rs b/tests/ui/fn/issue-39259.rs index d2b545e000b97..3682da6c4403c 100644 --- a/tests/ui/fn/issue-39259.rs +++ b/tests/ui/fn/issue-39259.rs @@ -5,7 +5,7 @@ struct S; impl Fn(u32) -> u32 for S { //~^ ERROR associated item constraints are not allowed here [E0229] - //~| ERROR expected an `FnMut(u32)` closure, found `S` + //~| ERROR expected `FnMut(u32)` signature, found `S` fn call(&self) -> u32 { //~^ ERROR method `call` has 1 parameter but the declaration in trait `call` has 2 5 diff --git a/tests/ui/fn/issue-39259.stderr b/tests/ui/fn/issue-39259.stderr index 7f2f4ecdd8d9b..bc368e0d0a0f9 100644 --- a/tests/ui/fn/issue-39259.stderr +++ b/tests/ui/fn/issue-39259.stderr @@ -22,11 +22,11 @@ help: add the missing parameter from the trait LL | fn call(&self, args: Args) -> u32 { | ++++++++++++ -error[E0277]: expected an `FnMut(u32)` closure, found `S` +error[E0277]: expected `FnMut(u32)` signature, found `S` --> $DIR/issue-39259.rs:6:25 | LL | impl Fn(u32) -> u32 for S { - | ^ expected an `FnMut(u32)` closure, found `S` + | ^ expected `FnMut(u32)` signature, found `S` | help: the trait `FnMut(u32)` is not implemented for `S` --> $DIR/issue-39259.rs:4:1 diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs index edd9ad11ae778..96109bea4894f 100644 --- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.rs @@ -10,7 +10,7 @@ trait Fun { impl Fun for T { type F<'a> = Self; - //~^ ERROR expected an `Fn()` closure, found `T` + //~^ ERROR expected `Fn()` signature, found `T` } fn main() { diff --git a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr index a12f51a47eafb..6b1e739bb677f 100644 --- a/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr +++ b/tests/ui/generic-associated-types/issue-68642-broken-llvm-ir.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `T` +error[E0277]: expected `Fn()` signature, found `T` --> $DIR/issue-68642-broken-llvm-ir.rs:12:18 | LL | type F<'a> = Self; - | ^^^^ expected an `Fn()` closure, found `T` + | ^^^^ expected `Fn()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Fun::F` diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.rs b/tests/ui/generic-associated-types/issue-68643-broken-mir.rs index 23586f6af98bd..eb965f46f687c 100644 --- a/tests/ui/generic-associated-types/issue-68643-broken-mir.rs +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.rs @@ -10,7 +10,7 @@ trait Fun { impl Fun for T { type F<'a> = Self; - //~^ ERROR expected an `Fn()` closure, found `T` + //~^ ERROR expected `Fn()` signature, found `T` } pub fn main() { diff --git a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr index 8c2ba9e66e94e..493a1b72d6e8e 100644 --- a/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr +++ b/tests/ui/generic-associated-types/issue-68643-broken-mir.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `T` +error[E0277]: expected `Fn()` signature, found `T` --> $DIR/issue-68643-broken-mir.rs:12:18 | LL | type F<'a> = Self; - | ^^^^ expected an `Fn()` closure, found `T` + | ^^^^ expected `Fn()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Fun::F` diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs b/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs index 85b932a063c14..4862e6c0bb61a 100644 --- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.rs @@ -10,7 +10,7 @@ trait Fun { impl Fun for T { type F<'a> = Self; - //~^ ERROR expected an `Fn()` closure, found `T` + //~^ ERROR expected `Fn()` signature, found `T` } fn main() { diff --git a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr index 8d347ace78176..b3e42b06bc15c 100644 --- a/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr +++ b/tests/ui/generic-associated-types/issue-68644-codegen-selection.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `T` +error[E0277]: expected `Fn()` signature, found `T` --> $DIR/issue-68644-codegen-selection.rs:12:18 | LL | type F<'a> = Self; - | ^^^^ expected an `Fn()` closure, found `T` + | ^^^^ expected `Fn()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Fun::F` diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs index b8133148b1029..579aeb7b6f909 100644 --- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.rs @@ -10,7 +10,7 @@ trait Fun { impl Fun for T { type F<'a> = Self; - //~^ ERROR expected an `Fn()` closure, found `T` + //~^ ERROR expected `Fn()` signature, found `T` } fn main() { diff --git a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr index 750c4005bc607..f6b92e86089d6 100644 --- a/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr +++ b/tests/ui/generic-associated-types/issue-68645-codegen-fulfillment.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `T` +error[E0277]: expected `Fn()` signature, found `T` --> $DIR/issue-68645-codegen-fulfillment.rs:12:18 | LL | type F<'a> = Self; - | ^^^^ expected an `Fn()` closure, found `T` + | ^^^^ expected `Fn()` signature, found `T` | = note: wrap the `T` in a closure with no arguments: `|| { /* code */ }` note: required by a bound in `Fun::F` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs index 10bfc954a4742..10910ae899855 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.rs @@ -23,7 +23,7 @@ impl WithDefault for () { //f(()); // Going through another generic function works fine. call(f, ()); - //~^ ERROR expected a + //~^ ERROR expected } } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index 2671765ef8e6b..76f3a9494d52d 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn(<_ as ATC<'a>>::Type)` closure, found `F` +error[E0277]: expected `Fn(<_ as ATC<'a>>::Type)` signature, found `F` --> $DIR/issue-62529-3.rs:25:14 | LL | call(f, ()); - | ---- ^ expected an `Fn(<_ as ATC<'a>>::Type)` closure, found `F` + | ---- ^ expected `Fn(<_ as ATC<'a>>::Type)` signature, found `F` | | | required by a bound introduced by this call | diff --git a/tests/ui/implied-bounds/issue-100690.rs b/tests/ui/implied-bounds/issue-100690.rs index 4f8a2df9834f5..4e674a1f1f46c 100644 --- a/tests/ui/implied-bounds/issue-100690.rs +++ b/tests/ui/implied-bounds/issue-100690.rs @@ -32,7 +32,7 @@ impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandl F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static, { real_dispatch(f) - //~^ ERROR expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F` + //~^ ERROR expected `FnOnce(&mut UIView<'_, T>)` signature, found `F` } } diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index 23c9d61c76d3b..970bf7ca7ca13 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F` +error[E0277]: expected `FnOnce(&mut UIView<'_, T>)` signature, found `F` --> $DIR/issue-100690.rs:34:23 | LL | real_dispatch(f) - | ------------- ^ expected an `FnOnce(&mut UIView<'_, T>)` closure, found `F` + | ------------- ^ expected `FnOnce(&mut UIView<'_, T>)` signature, found `F` | | | required by a bound introduced by this call | diff --git a/tests/ui/intrinsics/const-eval-select-bad.rs b/tests/ui/intrinsics/const-eval-select-bad.rs index 23a7a4be7ff10..4e0e4757f599b 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.rs +++ b/tests/ui/intrinsics/const-eval-select-bad.rs @@ -7,8 +7,8 @@ const fn not_fn_items() { const_eval_select((), || {}, || {}); //~^ ERROR const FnOnce()` is not satisfied const_eval_select((), 42, 0xDEADBEEF); - //~^ ERROR expected an `FnOnce()` closure - //~| ERROR expected an `FnOnce()` closure + //~^ ERROR expected `FnOnce()` + //~| ERROR expected `FnOnce()` } const fn foo(n: i32) -> i32 { diff --git a/tests/ui/intrinsics/const-eval-select-bad.stderr b/tests/ui/intrinsics/const-eval-select-bad.stderr index 7880dfa36a8f4..fea147bf305d2 100644 --- a/tests/ui/intrinsics/const-eval-select-bad.stderr +++ b/tests/ui/intrinsics/const-eval-select-bad.stderr @@ -9,11 +9,11 @@ LL | const_eval_select((), || {}, || {}); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL -error[E0277]: expected an `FnOnce()` closure, found `{integer}` +error[E0277]: expected `FnOnce()` signature, found `{integer}` --> $DIR/const-eval-select-bad.rs:9:27 | LL | const_eval_select((), 42, 0xDEADBEEF); - | ----------------- ^^ expected an `FnOnce()` closure, found `{integer}` + | ----------------- ^^ expected `FnOnce()` signature, found `{integer}` | | | required by a bound introduced by this call | @@ -22,11 +22,11 @@ LL | const_eval_select((), 42, 0xDEADBEEF); note: required by a bound in `const_eval_select` --> $SRC_DIR/core/src/intrinsics/mod.rs:LL:COL -error[E0277]: expected an `FnOnce()` closure, found `{integer}` +error[E0277]: expected `FnOnce()` signature, found `{integer}` --> $DIR/const-eval-select-bad.rs:9:31 | LL | const_eval_select((), 42, 0xDEADBEEF); - | ----------------- ^^^^^^^^^^ expected an `FnOnce()` closure, found `{integer}` + | ----------------- ^^^^^^^^^^ expected `FnOnce()` signature, found `{integer}` | | | required by a bound introduced by this call | diff --git a/tests/ui/iterators/fold-iterator-error-23966.stderr b/tests/ui/iterators/fold-iterator-error-23966.stderr index 2e27108e6a483..9e87a550eca62 100644 --- a/tests/ui/iterators/fold-iterator-error-23966.stderr +++ b/tests/ui/iterators/fold-iterator-error-23966.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnMut(_, char)` closure, found `()` +error[E0277]: expected `FnMut(_, char)` signature, found `()` --> $DIR/fold-iterator-error-23966.rs:3:32 | LL | "".chars().fold(|_, _| (), ()); - | ---- ^^ expected an `FnMut(_, char)` closure, found `()` + | ---- ^^ expected `FnMut(_, char)` signature, found `()` | | | required by a bound introduced by this call | diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs index d770208668986..f1f5ac111c5b5 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.rs @@ -4,7 +4,7 @@ use std::future::Future; async fn wrapper(f: F) -//~^ ERROR: expected an `FnOnce(&'a mut i32)` closure, found `i32` +//~^ ERROR: expected `FnOnce(&'a mut i32)` signature, found `i32` where F:, for<'a> >::Output: Future + 'a, diff --git a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr index 96059302fd0b2..73f831ebe3ccb 100644 --- a/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr +++ b/tests/ui/lifetimes/issue-76168-hr-outlives-3.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `FnOnce(&'a mut i32)` closure, found `i32` +error[E0277]: expected `FnOnce(&'a mut i32)` signature, found `i32` --> $DIR/issue-76168-hr-outlives-3.rs:6:1 | LL | / async fn wrapper(f: F) @@ -6,7 +6,7 @@ LL | | LL | | where LL | | F:, LL | | for<'a> >::Output: Future + 'a, - | |______________________________________________________________________________^ expected an `FnOnce(&'a mut i32)` closure, found `i32` + | |______________________________________________________________________________^ expected `FnOnce(&'a mut i32)` signature, found `i32` | = help: the trait `for<'a> FnOnce(&'a mut i32)` is not implemented for `i32` diff --git a/tests/ui/lifetimes/issue-95023.rs b/tests/ui/lifetimes/issue-95023.rs index d26317d2b9058..1dd50b5f908e4 100644 --- a/tests/ui/lifetimes/issue-95023.rs +++ b/tests/ui/lifetimes/issue-95023.rs @@ -4,7 +4,7 @@ impl Fn(&isize) for Error { //~^ ERROR manual implementations of `Fn` are experimental [E0183] //~| ERROR associated item constraints are not allowed here [E0229] //~| ERROR not all trait items implemented - //~| ERROR expected an `FnMut(&isize)` closure, found `Error` + //~| ERROR expected `FnMut(&isize)` signature, found `Error` fn foo(&self) -> Self::B<{ N }>; //~^ ERROR associated function in `impl` without body //~| ERROR method `foo` is not a member of trait `Fn` [E0407] diff --git a/tests/ui/lifetimes/issue-95023.stderr b/tests/ui/lifetimes/issue-95023.stderr index c05cea0dbe533..b60d9816a30b9 100644 --- a/tests/ui/lifetimes/issue-95023.stderr +++ b/tests/ui/lifetimes/issue-95023.stderr @@ -40,11 +40,11 @@ LL | impl Fn(&isize) for Error { | = help: implement the missing item: `fn call(&self, _: (&isize,)) -> >::Output { todo!() }` (unstable, requires feature `fn_traits`) -error[E0277]: expected an `FnMut(&isize)` closure, found `Error` +error[E0277]: expected `FnMut(&isize)` signature, found `Error` --> $DIR/issue-95023.rs:3:21 | LL | impl Fn(&isize) for Error { - | ^^^^^ expected an `FnMut(&isize)` closure, found `Error` + | ^^^^^ expected `FnMut(&isize)` signature, found `Error` | help: the trait `FnMut(&isize)` is not implemented for `Error` --> $DIR/issue-95023.rs:2:1 diff --git a/tests/ui/methods/filter-relevant-fn-bounds.rs b/tests/ui/methods/filter-relevant-fn-bounds.rs index a23f4600d6d1b..d84c195f9a3cb 100644 --- a/tests/ui/methods/filter-relevant-fn-bounds.rs +++ b/tests/ui/methods/filter-relevant-fn-bounds.rs @@ -16,5 +16,5 @@ impl Wrapper { fn main() { let mut wrapper = Wrapper; wrapper.do_something_wrapper(|value| ()); - //~^ ERROR expected an `FnOnce + //~^ ERROR expected `FnOnce } diff --git a/tests/ui/methods/filter-relevant-fn-bounds.stderr b/tests/ui/methods/filter-relevant-fn-bounds.stderr index f1676facdb2d4..7103d3ed712e4 100644 --- a/tests/ui/methods/filter-relevant-fn-bounds.stderr +++ b/tests/ui/methods/filter-relevant-fn-bounds.stderr @@ -12,11 +12,11 @@ help: consider further restricting type parameter `F` with trait `Output` LL | F: for<'a> FnOnce(>::Type) + for<'a> Output<'a>, | ++++++++++++++++++++ -error[E0277]: expected an `FnOnce(<{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41} as Output<'a>>::Type)` closure, found `{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41}` +error[E0277]: expected `FnOnce(<{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41} as Output<'a>>::Type)` signature, found `{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41}` --> $DIR/filter-relevant-fn-bounds.rs:18:34 | LL | wrapper.do_something_wrapper(|value| ()); - | -------------------- ^^^^^^^^^^ expected an `FnOnce(<{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41} as Output<'a>>::Type)` closure, found `{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41}` + | -------------------- ^^^^^^^^^^ expected `FnOnce(<{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41} as Output<'a>>::Type)` signature, found `{closure@$DIR/filter-relevant-fn-bounds.rs:18:34: 18:41}` | | | required by a bound introduced by this call | diff --git a/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.rs b/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.rs index f204e55f5a578..8685fec426595 100644 --- a/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.rs +++ b/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.rs @@ -16,7 +16,7 @@ struct Bar; fn main() { let foo: Box usize> = Box::new(Bar); - //~^ ERROR expected an `Fn(bool)` closure, found `Bar` + //~^ ERROR expected `Fn(bool)` signature, found `Bar` foo.borrow(); //~^ ERROR no method named `borrow` found foo.take() diff --git a/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.stderr b/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.stderr index 73f5f441b3fef..e4e595803b26f 100644 --- a/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.stderr +++ b/tests/ui/methods/method-suggestion-trait-with-extra-generics-no-ice.stderr @@ -22,11 +22,11 @@ help: there is a method `borrow_mut` with a similar name LL | foo.borrow_mut(); | ++++ -error[E0277]: expected an `Fn(bool)` closure, found `Bar` +error[E0277]: expected `Fn(bool)` signature, found `Bar` --> $DIR/method-suggestion-trait-with-extra-generics-no-ice.rs:18:43 | LL | let foo: Box usize> = Box::new(Bar); - | ^^^^^^^^^^^^^ expected an `Fn(bool)` closure, found `Bar` + | ^^^^^^^^^^^^^ expected `Fn(bool)` signature, found `Bar` | help: the trait `Fn(bool)` is not implemented for `Bar` --> $DIR/method-suggestion-trait-with-extra-generics-no-ice.rs:15:1 diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed index 1ff52c9e5a38a..b80ae7e9b42a7 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.current.fixed @@ -5,8 +5,8 @@ fn main() { let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments - //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found + //[next]~^^ ERROR: expected `FnMut(&{integer})` signature, found let _ = (-10..=10).find(|x: &i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments - //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found + //[next]~^^ ERROR: expected `FnMut(&{integer})` signature, found } diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr index 59a2255bc4fbf..96e32c58116fb 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` +error[E0277]: expected `FnMut(&{integer})` signature, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` --> $DIR/closure-arg-type-mismatch-issue-45727.rs:6:29 | LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^ expected `FnMut(&{integer})` signature, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:6:29: 6:37}` | | | required by a bound introduced by this call | @@ -16,11 +16,11 @@ LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL -error[E0277]: expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` +error[E0277]: expected `FnMut(&{integer})` signature, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` --> $DIR/closure-arg-type-mismatch-issue-45727.rs:9:29 | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnMut(&{integer})` closure, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FnMut(&{integer})` signature, found `{closure@$DIR/closure-arg-type-mismatch-issue-45727.rs:9:29: 9:40}` | | | required by a bound introduced by this call | diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs index 0a0abfafc45a2..04364da328f46 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.rs @@ -5,8 +5,8 @@ fn main() { let _ = (-10..=10).find(|x: i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments - //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found + //[next]~^^ ERROR: expected `FnMut(&{integer})` signature, found let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); //[current]~^ ERROR type mismatch in closure arguments - //[next]~^^ ERROR: expected an `FnMut(&{integer})` closure, found + //[next]~^^ ERROR: expected `FnMut(&{integer})` signature, found } diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs index 445a98cd49630..6dae9384ecba3 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs +++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.rs @@ -24,9 +24,9 @@ fn main() { let _ = produces_string().and_then(takes_str_but_too_many_refs); //~^ ERROR type mismatch in function arguments let _ = produces_string().and_then(takes_str_but_wrong_abi); - //~^ ERROR expected an `FnOnce(String)` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` + //~^ ERROR expected `FnOnce(String)` signature, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` let _ = produces_string().and_then(takes_str_but_unsafe); - //~^ ERROR expected an `FnOnce(String)` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}` + //~^ ERROR expected `FnOnce(String)` signature, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}` let _ = produces_string().and_then(no_args); //~^ ERROR function is expected to take 1 argument, but it takes 0 arguments let _ = Some(TypeWithoutDeref).and_then(takes_str_but_too_many_refs); diff --git a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr index 14c821b260299..56f6437f77b54 100644 --- a/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr +++ b/tests/ui/mismatched_types/suggest-option-asderef-unfixable.stderr @@ -18,11 +18,11 @@ help: consider wrapping the function in a closure LL | let _ = produces_string().and_then(|arg0: String| takes_str_but_too_many_refs(/* &&str */)); | ++++++++++++++ +++++++++++++ -error[E0277]: expected an `FnOnce(String)` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` +error[E0277]: expected `FnOnce(String)` signature, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` --> $DIR/suggest-option-asderef-unfixable.rs:26:40 | LL | let _ = produces_string().and_then(takes_str_but_wrong_abi); - | -------- ^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce(String)` closure, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` + | -------- ^^^^^^^^^^^^^^^^^^^^^^^ expected `FnOnce(String)` signature, found `for<'a> extern "C" fn(&'a str) -> Option<()> {takes_str_but_wrong_abi}` | | | required by a bound introduced by this call | @@ -30,7 +30,7 @@ LL | let _ = produces_string().and_then(takes_str_but_wrong_abi); note: required by a bound in `Option::::and_then` --> $SRC_DIR/core/src/option.rs:LL:COL -error[E0277]: expected an `FnOnce(String)` closure, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}` +error[E0277]: expected `FnOnce(String)` signature, found `for<'a> unsafe fn(&'a str) -> Option<()> {takes_str_but_unsafe}` --> $DIR/suggest-option-asderef-unfixable.rs:28:40 | LL | let _ = produces_string().and_then(takes_str_but_unsafe); diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr index a7805e25f651e..a230ad0192d1c 100644 --- a/tests/ui/trait-bounds/mismatch-fn-trait.stderr +++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnMut(i32)` closure, found `impl FnMut(u32)` +error[E0277]: expected `FnMut(i32)` signature, found `impl FnMut(u32)` --> $DIR/mismatch-fn-trait.rs:4:10 | LL | take(f) - | ---- ^ expected an `FnMut(i32)` closure, found `impl FnMut(u32)` + | ---- ^ expected `FnMut(i32)` signature, found `impl FnMut(u32)` | | | required by a bound introduced by this call | @@ -14,11 +14,11 @@ note: required by a bound in `take` LL | fn take(_f: impl FnMut(i32)) {} | ^^^^^^^^^^ required by this bound in `take` -error[E0277]: expected an `FnMut(i32)` closure, found `impl FnMut(i32, i32)` +error[E0277]: expected `FnMut(i32)` signature, found `impl FnMut(i32, i32)` --> $DIR/mismatch-fn-trait.rs:9:10 | LL | take(f) - | ---- ^ expected an `FnMut(i32)` closure, found `impl FnMut(i32, i32)` + | ---- ^ expected `FnMut(i32)` signature, found `impl FnMut(i32, i32)` | | | required by a bound introduced by this call | @@ -29,11 +29,11 @@ note: required by a bound in `take` LL | fn take(_f: impl FnMut(i32)) {} | ^^^^^^^^^^ required by this bound in `take` -error[E0277]: expected an `FnMut(i32)` closure, found `impl FnMut()` +error[E0277]: expected `FnMut(i32)` signature, found `impl FnMut()` --> $DIR/mismatch-fn-trait.rs:14:10 | LL | take(f) - | ---- ^ expected an `FnMut(i32)` closure, found `impl FnMut()` + | ---- ^ expected `FnMut(i32)` signature, found `impl FnMut()` | | | required by a bound introduced by this call | @@ -44,11 +44,11 @@ note: required by a bound in `take` LL | fn take(_f: impl FnMut(i32)) {} | ^^^^^^^^^^ required by this bound in `take` -error[E0277]: expected an `FnMut(i32)` closure, found `impl FnOnce(i32)` +error[E0277]: expected `FnMut(i32)` signature, found `impl FnOnce(i32)` --> $DIR/mismatch-fn-trait.rs:19:10 | LL | take(f) - | ---- ^ expected an `FnMut(i32)` closure, found `impl FnOnce(i32)` + | ---- ^ expected `FnMut(i32)` signature, found `impl FnOnce(i32)` | | | required by a bound introduced by this call | @@ -59,11 +59,11 @@ note: required by a bound in `take` LL | fn take(_f: impl FnMut(i32)) {} | ^^^^^^^^^^ required by this bound in `take` -error[E0277]: expected an `FnMut(i32)` closure, found `impl FnOnce(u32)` +error[E0277]: expected `FnMut(i32)` signature, found `impl FnOnce(u32)` --> $DIR/mismatch-fn-trait.rs:24:10 | LL | take(f) - | ---- ^ expected an `FnMut(i32)` closure, found `impl FnOnce(u32)` + | ---- ^ expected `FnMut(i32)` signature, found `impl FnOnce(u32)` | | | required by a bound introduced by this call | diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs index f19c9da7c5eb5..68de971eea598 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.rs @@ -11,5 +11,5 @@ fn f X<'r> + ?Sized>() { fn main() { f:: X<'x, F = i32>>(); - //~^ ERROR expected an `FnOnce(&i32)` closure, found `i32` + //~^ ERROR expected `FnOnce(&i32)` signature, found `i32` } diff --git a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr index c4bc50746ebba..7f0185f6c03ca 100644 --- a/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr +++ b/tests/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `FnOnce(&i32)` closure, found `i32` +error[E0277]: expected `FnOnce(&i32)` signature, found `i32` --> $DIR/check-trait-object-bounds-2.rs:13:9 | LL | f:: X<'x, F = i32>>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce(&i32)` closure, found `i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FnOnce(&i32)` signature, found `i32` | = help: the trait `for<'a> FnOnce(&'a i32)` is not implemented for `i32` note: required by a bound in `f` diff --git a/tests/ui/traits/issue-87558.rs b/tests/ui/traits/issue-87558.rs index 61a24f6b96714..2118d4cfda159 100644 --- a/tests/ui/traits/issue-87558.rs +++ b/tests/ui/traits/issue-87558.rs @@ -3,7 +3,7 @@ struct Error(ErrorKind); impl Fn(&isize) for Error { //~^ ERROR manual implementations of `Fn` are experimental //~| ERROR associated item constraints are not allowed here - //~| ERROR closure, found `Error` + //~| ERROR signature, found `Error` //~| ERROR not all trait items implemented, missing: `call` fn from() {} //~ ERROR method `from` is not a member of trait `Fn` } diff --git a/tests/ui/traits/issue-87558.stderr b/tests/ui/traits/issue-87558.stderr index 0238e4ae18685..73e5f9d5fcc11 100644 --- a/tests/ui/traits/issue-87558.stderr +++ b/tests/ui/traits/issue-87558.stderr @@ -32,11 +32,11 @@ LL | impl Fn(&isize) for Error { | = help: implement the missing item: `fn call(&self, _: (&isize,)) -> >::Output { todo!() }` (unstable, requires feature `fn_traits`) -error[E0277]: expected an `FnMut(&isize)` closure, found `Error` +error[E0277]: expected `FnMut(&isize)` signature, found `Error` --> $DIR/issue-87558.rs:3:21 | LL | impl Fn(&isize) for Error { - | ^^^^^ expected an `FnMut(&isize)` closure, found `Error` + | ^^^^^ expected `FnMut(&isize)` signature, found `Error` | help: the trait `FnMut(&isize)` is not implemented for `Error` --> $DIR/issue-87558.rs:2:1 diff --git a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs index b53d30e5f5c9c..6637d5744a4e2 100644 --- a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs +++ b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.rs @@ -7,7 +7,7 @@ const fn with_positive [const] Fn(&'a ())>() {} const _: () = { with_positive::<()>(); - //~^ ERROR expected an `Fn(&'a ())` closure, found `()` + //~^ ERROR expected `Fn(&'a ())` signature, found `()` }; fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr index 3b1126e253abd..2f7eb281894aa 100644 --- a/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr +++ b/tests/ui/traits/next-solver/diagnostics/const-host-effect-hrtb-no-ice.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn(&'a ())` closure, found `()` +error[E0277]: expected `Fn(&'a ())` signature, found `()` --> $DIR/const-host-effect-hrtb-no-ice.rs:9:21 | LL | with_positive::<()>(); - | ^^ expected an `Fn(&'a ())` closure, found `()` + | ^^ expected `Fn(&'a ())` signature, found `()` | = help: the trait `for<'a> Fn(&'a ())` is not implemented for `()` note: required by a bound in `with_positive` diff --git a/tests/ui/traits/next-solver/fn-trait.rs b/tests/ui/traits/next-solver/fn-trait.rs index e31d4d2b580a5..9d3d5ce904c87 100644 --- a/tests/ui/traits/next-solver/fn-trait.rs +++ b/tests/ui/traits/next-solver/fn-trait.rs @@ -18,11 +18,11 @@ fn main() { require_fn(f); require_fn(f as fn() -> i32); require_fn(f as unsafe fn() -> i32); - //~^ ERROR: expected an `Fn()` closure, found `unsafe fn() -> i32` + //~^ ERROR: expected `Fn()` signature, found `unsafe fn() -> i32` require_fn(g); - //~^ ERROR: expected an `Fn()` closure, found `extern "C" fn() -> i32 {g}` + //~^ ERROR: expected `Fn()` signature, found `extern "C" fn() -> i32 {g}` require_fn(g as extern "C" fn() -> i32); - //~^ ERROR: expected an `Fn()` closure, found `extern "C" fn() -> i32` + //~^ ERROR: expected `Fn()` signature, found `extern "C" fn() -> i32` require_fn(h); - //~^ ERROR: expected an `Fn()` closure, found `unsafe fn() -> i32 {h}` + //~^ ERROR: expected `Fn()` signature, found `unsafe fn() -> i32 {h}` } diff --git a/tests/ui/traits/next-solver/fn-trait.stderr b/tests/ui/traits/next-solver/fn-trait.stderr index 6218928b309f7..ec3a4dc54cca8 100644 --- a/tests/ui/traits/next-solver/fn-trait.stderr +++ b/tests/ui/traits/next-solver/fn-trait.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `Fn()` closure, found `unsafe fn() -> i32` +error[E0277]: expected `Fn()` signature, found `unsafe fn() -> i32` --> $DIR/fn-trait.rs:20:16 | LL | require_fn(f as unsafe fn() -> i32); @@ -15,11 +15,11 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0277]: expected an `Fn()` closure, found `extern "C" fn() -> i32 {g}` +error[E0277]: expected `Fn()` signature, found `extern "C" fn() -> i32 {g}` --> $DIR/fn-trait.rs:22:16 | LL | require_fn(g); - | ---------- ^ expected an `Fn()` closure, found `extern "C" fn() -> i32 {g}` + | ---------- ^ expected `Fn()` signature, found `extern "C" fn() -> i32 {g}` | | | required by a bound introduced by this call | @@ -31,11 +31,11 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0277]: expected an `Fn()` closure, found `extern "C" fn() -> i32` +error[E0277]: expected `Fn()` signature, found `extern "C" fn() -> i32` --> $DIR/fn-trait.rs:24:16 | LL | require_fn(g as extern "C" fn() -> i32); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `Fn()` closure, found `extern "C" fn() -> i32` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Fn()` signature, found `extern "C" fn() -> i32` | | | required by a bound introduced by this call | @@ -47,7 +47,7 @@ note: required by a bound in `require_fn` LL | fn require_fn(_: impl Fn() -> i32) {} | ^^^^^^^^^^^ required by this bound in `require_fn` -error[E0277]: expected an `Fn()` closure, found `unsafe fn() -> i32 {h}` +error[E0277]: expected `Fn()` signature, found `unsafe fn() -> i32 {h}` --> $DIR/fn-trait.rs:26:16 | LL | require_fn(h); diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs index 50d4a42e1f355..7f532fd02f6af 100644 --- a/tests/ui/type-alias-impl-trait/issue-63279.rs +++ b/tests/ui/type-alias-impl-trait/issue-63279.rs @@ -4,11 +4,11 @@ type Closure = impl FnOnce(); #[define_opaque(Closure)] fn c() -> Closure { - //~^ ERROR: expected an `FnOnce()` closure, found `()` + //~^ ERROR: expected `FnOnce()` signature, found `()` || -> Closure { || () } //~^ ERROR: mismatched types //~| ERROR: mismatched types - //~| ERROR: expected an `FnOnce()` closure, found `()` + //~| ERROR: expected `FnOnce()` signature, found `()` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr index 165c1c25280bd..19860f414c9cb 100644 --- a/tests/ui/type-alias-impl-trait/issue-63279.stderr +++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr @@ -1,17 +1,17 @@ -error[E0277]: expected an `FnOnce()` closure, found `()` +error[E0277]: expected `FnOnce()` signature, found `()` --> $DIR/issue-63279.rs:6:11 | LL | fn c() -> Closure { - | ^^^^^^^ expected an `FnOnce()` closure, found `()` + | ^^^^^^^ expected `FnOnce()` signature, found `()` | = help: the trait `FnOnce()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` -error[E0277]: expected an `FnOnce()` closure, found `()` +error[E0277]: expected `FnOnce()` signature, found `()` --> $DIR/issue-63279.rs:8:11 | LL | || -> Closure { || () } - | ^^^^^^^ expected an `FnOnce()` closure, found `()` + | ^^^^^^^ expected `FnOnce()` signature, found `()` | = help: the trait `FnOnce()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs index aec311ede864f..64910983e6694 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs @@ -8,10 +8,10 @@ type Tait = impl FnOnce() -> (); #[define_opaque(Tait)] fn reify_as_tait() -> Thunk { - //~^ ERROR: expected an `FnOnce()` closure, found `()` + //~^ ERROR: expected `FnOnce()` signature, found `()` Thunk::new(|cont| cont) //~^ ERROR: mismatched types - //~| ERROR: expected an `FnOnce()` closure, found `()` + //~| ERROR: expected `FnOnce()` signature, found `()` } struct Thunk(F); diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr index 22d16e39fc404..4d530455182b9 100644 --- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr +++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr @@ -10,20 +10,20 @@ LL | Thunk::new(|cont| cont) = note: expected struct `Thunk<_>` found unit type `()` -error[E0277]: expected an `FnOnce()` closure, found `()` +error[E0277]: expected `FnOnce()` signature, found `()` --> $DIR/lazy_subtyping_of_opaques.rs:12:23 | LL | Thunk::new(|cont| cont) - | ^^^^ expected an `FnOnce()` closure, found `()` + | ^^^^ expected `FnOnce()` signature, found `()` | = help: the trait `FnOnce()` is not implemented for `()` = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }` -error[E0277]: expected an `FnOnce()` closure, found `()` +error[E0277]: expected `FnOnce()` signature, found `()` --> $DIR/lazy_subtyping_of_opaques.rs:10:23 | LL | fn reify_as_tait() -> Thunk { - | ^^^^^^^^^^^ expected an `FnOnce()` closure, found `()` + | ^^^^^^^^^^^ expected `FnOnce()` signature, found `()` LL | LL | Thunk::new(|cont| cont) | ----------------------- return type was inferred to be `{type error}` here diff --git a/tests/ui/typeck/issue-116864.current.stderr b/tests/ui/typeck/issue-116864.current.stderr index 7337bf56a6b9d..0eabb9719b1a6 100644 --- a/tests/ui/typeck/issue-116864.current.stderr +++ b/tests/ui/typeck/issue-116864.current.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +error[E0277]: expected `FnMut(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` --> $DIR/issue-116864.rs:29:1 | LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) @@ -6,7 +6,7 @@ LL | | LL | | LL | | where LL | | BAZ: Baz, - | |__________________________^ expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | |__________________________^ expected `FnMut(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` | = note: expected a closure with signature `for<'any> fn(&'any i32)` found a closure with signature `fn(&::Param)` diff --git a/tests/ui/typeck/issue-116864.next.stderr b/tests/ui/typeck/issue-116864.next.stderr index 1a04243c2f6ba..a585b3596689a 100644 --- a/tests/ui/typeck/issue-116864.next.stderr +++ b/tests/ui/typeck/issue-116864.next.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +error[E0277]: expected `FnOnce(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` --> $DIR/issue-116864.rs:29:1 | LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) @@ -6,7 +6,7 @@ LL | | LL | | LL | | where LL | | BAZ: Baz, - | |__________________________^ expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` + | |__________________________^ expected `FnOnce(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` | = note: expected a closure with signature `for<'any> fn(&'any i32)` found a closure with signature `fn(&::Param)` diff --git a/tests/ui/typeck/issue-116864.rs b/tests/ui/typeck/issue-116864.rs index a16731174b2be..8eaa63e1e0740 100644 --- a/tests/ui/typeck/issue-116864.rs +++ b/tests/ui/typeck/issue-116864.rs @@ -27,8 +27,8 @@ where } async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) -//[next]~^ ERROR: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` -//[current]~^^ ERROR: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +//[next]~^ ERROR: expected `FnOnce(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` +//[current]~^^ ERROR: expected `FnMut(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` where BAZ: Baz, { diff --git a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr index d579b5bd75002..bb50394232980 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-fnmut-as-fn.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn(isize)` closure, found `S` +error[E0277]: expected `Fn(isize)` signature, found `S` --> $DIR/unboxed-closures-fnmut-as-fn.rs:27:21 | LL | let x = call_it(&S, 22); - | ------- ^^ expected an `Fn(isize)` closure, found `S` + | ------- ^^ expected `Fn(isize)` signature, found `S` | | | required by a bound introduced by this call | diff --git a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr index a637b180e31e7..6b5508efe1290 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-unsafe-extern-fn.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `Fn(&isize)` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` +error[E0277]: expected `Fn(&isize)` signature, found `for<'a> unsafe fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:20:21 | LL | let x = call_it(&square, 22); @@ -14,7 +14,7 @@ note: required by a bound in `call_it` LL | fn call_it isize>(_: &F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` -error[E0277]: expected an `FnMut(&isize)` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` +error[E0277]: expected `FnMut(&isize)` signature, found `for<'a> unsafe fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); @@ -30,7 +30,7 @@ note: required by a bound in `call_it_mut` LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` -error[E0277]: expected an `FnOnce(&isize)` closure, found `for<'a> unsafe fn(&'a isize) -> isize {square}` +error[E0277]: expected `FnOnce(&isize)` signature, found `for<'a> unsafe fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-unsafe-extern-fn.rs:30:26 | LL | let z = call_it_once(square, 22); diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr index 25cf793ca00e8..80c368fa46b5f 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-abi.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn(&isize)` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` +error[E0277]: expected `Fn(&isize)` signature, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:20:21 | LL | let x = call_it(&square, 22); - | ------- ^^^^^^^ expected an `Fn(&isize)` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + | ------- ^^^^^^^ expected `Fn(&isize)` signature, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` | | | required by a bound introduced by this call | @@ -13,11 +13,11 @@ note: required by a bound in `call_it` LL | fn call_it isize>(_: &F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` -error[E0277]: expected an `FnMut(&isize)` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` +error[E0277]: expected `FnMut(&isize)` signature, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:25:25 | LL | let y = call_it_mut(&mut square, 22); - | ----------- ^^^^^^^^^^^ expected an `FnMut(&isize)` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + | ----------- ^^^^^^^^^^^ expected `FnMut(&isize)` signature, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` | | | required by a bound introduced by this call | @@ -28,11 +28,11 @@ note: required by a bound in `call_it_mut` LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` -error[E0277]: expected an `FnOnce(&isize)` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` +error[E0277]: expected `FnOnce(&isize)` signature, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-abi.rs:30:26 | LL | let z = call_it_once(square, 22); - | ------------ ^^^^^^ expected an `FnOnce(&isize)` closure, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` + | ------------ ^^^^^^ expected `FnOnce(&isize)` signature, found `for<'a> extern "C" fn(&'a isize) -> isize {square}` | | | required by a bound introduced by this call | diff --git a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr index e09eda3b99d29..476689a273faf 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-wrong-arg-type-extern-fn.stderr @@ -1,4 +1,4 @@ -error[E0277]: expected an `Fn(&isize)` closure, found `unsafe fn(isize) -> isize {square}` +error[E0277]: expected `Fn(&isize)` signature, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:21:21 | LL | let x = call_it(&square, 22); @@ -14,7 +14,7 @@ note: required by a bound in `call_it` LL | fn call_it isize>(_: &F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it` -error[E0277]: expected an `FnMut(&isize)` closure, found `unsafe fn(isize) -> isize {square}` +error[E0277]: expected `FnMut(&isize)` signature, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:26:25 | LL | let y = call_it_mut(&mut square, 22); @@ -30,7 +30,7 @@ note: required by a bound in `call_it_mut` LL | fn call_it_mut isize>(_: &mut F, _: isize) -> isize { | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call_it_mut` -error[E0277]: expected an `FnOnce(&isize)` closure, found `unsafe fn(isize) -> isize {square}` +error[E0277]: expected `FnOnce(&isize)` signature, found `unsafe fn(isize) -> isize {square}` --> $DIR/unboxed-closures-wrong-arg-type-extern-fn.rs:31:26 | LL | let z = call_it_once(square, 22); diff --git a/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs index 47e3fa477ea69..3e886e8120eb1 100644 --- a/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs +++ b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.rs @@ -9,8 +9,8 @@ trait Tr {} trait Foo { fn foo() -> impl Sized - //~^ ERROR: expected an `FnOnce<&'a i32>` closure, found `()` - //~| ERROR: expected an `FnOnce<&'a i32>` closure, found `()` + //~^ ERROR: expected `FnOnce<&'a i32>` signature, found `()` + //~| ERROR: expected `FnOnce<&'a i32>` signature, found `()` where for<'a> <() as FnOnce<&'a i32>>::Output: Tr, { diff --git a/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr index 7457f76eb39f6..6da4b26f912a4 100644 --- a/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr +++ b/tests/ui/wf/closure-trait-ice-in-wfcheck-diagnostics.stderr @@ -1,12 +1,12 @@ -error[E0277]: expected an `FnOnce<&'a i32>` closure, found `()` +error[E0277]: expected `FnOnce<&'a i32>` signature, found `()` --> $DIR/closure-trait-ice-in-wfcheck-diagnostics.rs:11:17 | LL | fn foo() -> impl Sized - | ^^^^^^^^^^ expected an `FnOnce<&'a i32>` closure, found `()` + | ^^^^^^^^^^ expected `FnOnce<&'a i32>` signature, found `()` | = help: the trait `for<'a> FnOnce<&'a i32>` is not implemented for `()` -error[E0277]: expected an `FnOnce<&'a i32>` closure, found `()` +error[E0277]: expected `FnOnce<&'a i32>` signature, found `()` --> $DIR/closure-trait-ice-in-wfcheck-diagnostics.rs:11:5 | LL | / fn foo() -> impl Sized @@ -14,7 +14,7 @@ LL | | LL | | LL | | where LL | | for<'a> <() as FnOnce<&'a i32>>::Output: Tr, - | |____________________________________________________^ expected an `FnOnce<&'a i32>` closure, found `()` + | |____________________________________________________^ expected `FnOnce<&'a i32>` signature, found `()` | = help: the trait `for<'a> FnOnce<&'a i32>` is not implemented for `()` From dc2da078ef9197a2b9abb99467e70a2cb6cf1ee5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 12 Oct 2026 02:33:41 +0000 Subject: [PATCH 04/16] Be more accurate on expected and found signatures ``` error[E0277]: expected `Fn(<_ as ATC<'a>>::Type)` signature, found `F` --> $DIR/issue-62529-3.rs:25:14 | LL | call(f, ()); | ---- ^ expected `Fn(<_ as ATC<'a>>::Type)` signature, found `F` | | | required by a bound introduced by this call | = note: expected type with signature `for<'a> fn(<_ as ATC<'a>>::Type)` found type parameter with signature `fn(())` note: required by a bound in `call` --> $DIR/issue-62529-3.rs:9:36 | LL | fn call<'b, T: for<'a> ATC<'a>, F: for<'a> Fn(>::Type)>( | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `call` ``` --- .../traits/fulfillment_errors.rs | 7 ++++-- .../issue-62529-3.stderr | 4 ++-- tests/ui/implied-bounds/issue-100690.stderr | 4 ++-- ...-arg-type-mismatch-issue-45727.next.stderr | 8 +++---- .../closure-mismatch.next.stderr | 8 +++---- .../rfc-2396-target_feature-11/fn-traits.rs | 14 ++++++------ .../fn-traits.stderr | 22 +++++++++---------- .../ui/trait-bounds/mismatch-fn-trait.stderr | 8 +++---- tests/ui/typeck/issue-116864.current.stderr | 4 ++-- tests/ui/typeck/issue-116864.next.stderr | 4 ++-- 10 files changed, 43 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 47d1f1b22c090..05185d9e08bce 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3632,9 +3632,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Print type mismatch let (expected_args, given_args) = self.cmp(expected_ty, given_ty); err.note_expected_found( - "a closure with signature", + "type with signature", expected_args, - "a closure with signature", + &format!( + "{} with signature", + trait_pred.self_ty().skip_binder().prefix_string(self.tcx) + ), given_args, ); } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr index 76f3a9494d52d..f9f39e34b658e 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-62529-3.stderr @@ -6,8 +6,8 @@ LL | call(f, ()); | | | required by a bound introduced by this call | - = note: expected a closure with signature `for<'a> fn(<_ as ATC<'a>>::Type)` - found a closure with signature `fn(())` + = note: expected type with signature `for<'a> fn(<_ as ATC<'a>>::Type)` + found type parameter with signature `fn(())` note: required by a bound in `call` --> $DIR/issue-62529-3.rs:9:36 | diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index 970bf7ca7ca13..69dee68a3c099 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -6,8 +6,8 @@ LL | real_dispatch(f) | | | required by a bound introduced by this call | - = note: expected a closure with signature `for<'a, 'b> fn(&'a mut UIView<'b, _>)` - found a closure with signature `fn(&mut UIView<'a, _>)` + = note: expected type with signature `for<'a, 'b> fn(&'a mut UIView<'b, _>)` + found type parameter with signature `fn(&mut UIView<'a, _>)` note: required by a bound in `real_dispatch` --> $DIR/issue-100690.rs:8:8 | diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr index 96e32c58116fb..983ecee825e6b 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch-issue-45727.next.stderr @@ -11,8 +11,8 @@ help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{ | LL | let _ = (-10..=10).find(|x: i32| x.signum() == 0); | ^^^^^^^^ - = note: expected a closure with signature `for<'a> fn(&'a {integer})` - found a closure with signature `fn(i32)` + = note: expected type with signature `for<'a> fn(&'a {integer})` + found closure with signature `fn(i32)` note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL @@ -29,8 +29,8 @@ help: the trait `for<'a> FnMut(&'a {integer})` is not implemented for closure `{ | LL | let _ = (-10..=10).find(|x: &&&i32| x.signum() == 0); | ^^^^^^^^^^^ - = note: expected a closure with signature `for<'a> fn(&'a {integer})` - found a closure with signature `fn(&&&i32)` + = note: expected type with signature `for<'a> fn(&'a {integer})` + found closure with signature `fn(&&&i32)` note: required by a bound in `find` --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL diff --git a/tests/ui/mismatched_types/closure-mismatch.next.stderr b/tests/ui/mismatched_types/closure-mismatch.next.stderr index 0d6ca6d7bfca8..aaddbbb9fbee6 100644 --- a/tests/ui/mismatched_types/closure-mismatch.next.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.next.stderr @@ -11,8 +11,8 @@ help: the trait `for<'a> FnOnce(&'a ())` is not implemented for closure `{closur | LL | baz(|_| ()); | ^^^ - = note: expected a closure with signature `for<'a> fn(&'a ())` - found a closure with signature `fn(&())` + = note: expected type with signature `for<'a> fn(&'a ())` + found closure with signature `fn(&())` note: required for `{closure@$DIR/closure-mismatch.rs:12:9: 12:12}` to implement `Foo` --> $DIR/closure-mismatch.rs:7:18 | @@ -39,8 +39,8 @@ help: the trait `for<'a> FnOnce(&'a ())` is not implemented for closure `{closur | LL | baz(|x| ()); | ^^^ - = note: expected a closure with signature `for<'a> fn(&'a ())` - found a closure with signature `fn(&())` + = note: expected type with signature `for<'a> fn(&'a ())` + found closure with signature `fn(&())` note: required for `{closure@$DIR/closure-mismatch.rs:16:9: 16:12}` to implement `Foo` --> $DIR/closure-mismatch.rs:7:18 | diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs index 778a3fb7bbbd7..455d161cbcb9a 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.rs @@ -26,15 +26,15 @@ fn call_once_i32(f: impl FnOnce(i32)) { } fn main() { - call(foo); //~ ERROR expected an `Fn()` closure, found `#[target_feature(..)] fn() {foo}` - call_mut(foo); //~ ERROR expected an `FnMut()` closure, found `#[target_feature(..)] fn() {foo}` - call_once(foo); //~ ERROR expected an `FnOnce()` closure, found `#[target_feature(..)] fn() {foo}` - call_once_i32(bar); //~ ERROR expected an `FnOnce(i32)` closure, found `#[target_feature(..)] fn(i32) {bar}` + call(foo); //~ ERROR expected `Fn()` signature, found `#[target_feature(..)] fn() {foo}` + call_mut(foo); //~ ERROR expected `FnMut()` signature, found `#[target_feature(..)] fn() {foo}` + call_once(foo); //~ ERROR expected `FnOnce()` signature, found `#[target_feature(..)] fn() {foo}` + call_once_i32(bar); //~ ERROR expected `FnOnce(i32)` signature, found `#[target_feature(..)] fn(i32) {bar}` call(foo_unsafe); - //~^ ERROR expected an `Fn()` closure, found `unsafe fn() {foo_unsafe}` + //~^ ERROR expected `Fn()` signature, found `unsafe fn() {foo_unsafe}` call_mut(foo_unsafe); - //~^ ERROR expected an `FnMut()` closure, found `unsafe fn() {foo_unsafe}` + //~^ ERROR expected `FnMut()` signature, found `unsafe fn() {foo_unsafe}` call_once(foo_unsafe); - //~^ ERROR expected an `FnOnce()` closure, found `unsafe fn() {foo_unsafe}` + //~^ ERROR expected `FnOnce()` signature, found `unsafe fn() {foo_unsafe}` } diff --git a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr index 43744636be196..7eee2f7277247 100644 --- a/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr +++ b/tests/ui/rfcs/rfc-2396-target_feature-11/fn-traits.stderr @@ -1,8 +1,8 @@ -error[E0277]: expected an `Fn()` closure, found `#[target_feature(..)] fn() {foo}` +error[E0277]: expected `Fn()` signature, found `#[target_feature(..)] fn() {foo}` --> $DIR/fn-traits.rs:29:10 | LL | call(foo); - | ---- ^^^ expected an `Fn()` closure, found `#[target_feature(..)] fn() {foo}` + | ---- ^^^ expected `Fn()` signature, found `#[target_feature(..)] fn() {foo}` | | | required by a bound introduced by this call | @@ -16,11 +16,11 @@ note: required by a bound in `call` LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` -error[E0277]: expected an `FnMut()` closure, found `#[target_feature(..)] fn() {foo}` +error[E0277]: expected `FnMut()` signature, found `#[target_feature(..)] fn() {foo}` --> $DIR/fn-traits.rs:30:14 | LL | call_mut(foo); - | -------- ^^^ expected an `FnMut()` closure, found `#[target_feature(..)] fn() {foo}` + | -------- ^^^ expected `FnMut()` signature, found `#[target_feature(..)] fn() {foo}` | | | required by a bound introduced by this call | @@ -34,11 +34,11 @@ note: required by a bound in `call_mut` LL | fn call_mut(mut f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` -error[E0277]: expected an `FnOnce()` closure, found `#[target_feature(..)] fn() {foo}` +error[E0277]: expected `FnOnce()` signature, found `#[target_feature(..)] fn() {foo}` --> $DIR/fn-traits.rs:31:15 | LL | call_once(foo); - | --------- ^^^ expected an `FnOnce()` closure, found `#[target_feature(..)] fn() {foo}` + | --------- ^^^ expected `FnOnce()` signature, found `#[target_feature(..)] fn() {foo}` | | | required by a bound introduced by this call | @@ -52,11 +52,11 @@ note: required by a bound in `call_once` LL | fn call_once(f: impl FnOnce()) { | ^^^^^^^^ required by this bound in `call_once` -error[E0277]: expected an `FnOnce(i32)` closure, found `#[target_feature(..)] fn(i32) {bar}` +error[E0277]: expected `FnOnce(i32)` signature, found `#[target_feature(..)] fn(i32) {bar}` --> $DIR/fn-traits.rs:32:19 | LL | call_once_i32(bar); - | ------------- ^^^ expected an `FnOnce(i32)` closure, found `#[target_feature(..)] fn(i32) {bar}` + | ------------- ^^^ expected `FnOnce(i32)` signature, found `#[target_feature(..)] fn(i32) {bar}` | | | required by a bound introduced by this call | @@ -69,7 +69,7 @@ note: required by a bound in `call_once_i32` LL | fn call_once_i32(f: impl FnOnce(i32)) { | ^^^^^^^^^^^ required by this bound in `call_once_i32` -error[E0277]: expected an `Fn()` closure, found `unsafe fn() {foo_unsafe}` +error[E0277]: expected `Fn()` signature, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:34:10 | LL | call(foo_unsafe); @@ -88,7 +88,7 @@ note: required by a bound in `call` LL | fn call(f: impl Fn()) { | ^^^^ required by this bound in `call` -error[E0277]: expected an `FnMut()` closure, found `unsafe fn() {foo_unsafe}` +error[E0277]: expected `FnMut()` signature, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:36:14 | LL | call_mut(foo_unsafe); @@ -107,7 +107,7 @@ note: required by a bound in `call_mut` LL | fn call_mut(mut f: impl FnMut()) { | ^^^^^^^ required by this bound in `call_mut` -error[E0277]: expected an `FnOnce()` closure, found `unsafe fn() {foo_unsafe}` +error[E0277]: expected `FnOnce()` signature, found `unsafe fn() {foo_unsafe}` --> $DIR/fn-traits.rs:38:15 | LL | call_once(foo_unsafe); diff --git a/tests/ui/trait-bounds/mismatch-fn-trait.stderr b/tests/ui/trait-bounds/mismatch-fn-trait.stderr index a230ad0192d1c..59cff1c319fc9 100644 --- a/tests/ui/trait-bounds/mismatch-fn-trait.stderr +++ b/tests/ui/trait-bounds/mismatch-fn-trait.stderr @@ -6,8 +6,8 @@ LL | take(f) | | | required by a bound introduced by this call | - = note: expected a closure with signature `fn(i32)` - found a closure with signature `fn(u32)` + = note: expected type with signature `fn(i32)` + found type parameter with signature `fn(u32)` note: required by a bound in `take` --> $DIR/mismatch-fn-trait.rs:1:18 | @@ -68,8 +68,8 @@ LL | take(f) | required by a bound introduced by this call | = note: `impl FnOnce(u32)` implements `FnOnce`, but it must implement `FnMut`, which is more general - = note: expected a closure with signature `fn(i32)` - found a closure with signature `fn(u32)` + = note: expected type with signature `fn(i32)` + found type parameter with signature `fn(u32)` note: required by a bound in `take` --> $DIR/mismatch-fn-trait.rs:1:18 | diff --git a/tests/ui/typeck/issue-116864.current.stderr b/tests/ui/typeck/issue-116864.current.stderr index 0eabb9719b1a6..a65c22be840ff 100644 --- a/tests/ui/typeck/issue-116864.current.stderr +++ b/tests/ui/typeck/issue-116864.current.stderr @@ -8,8 +8,8 @@ LL | | where LL | | BAZ: Baz, | |__________________________^ expected `FnMut(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` | - = note: expected a closure with signature `for<'any> fn(&'any i32)` - found a closure with signature `fn(&::Param)` + = note: expected type with signature `for<'any> fn(&'any i32)` + found type parameter with signature `fn(&::Param)` note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` --> $DIR/issue-116864.rs:21:20 | diff --git a/tests/ui/typeck/issue-116864.next.stderr b/tests/ui/typeck/issue-116864.next.stderr index a585b3596689a..1b01e7a6a96df 100644 --- a/tests/ui/typeck/issue-116864.next.stderr +++ b/tests/ui/typeck/issue-116864.next.stderr @@ -8,8 +8,8 @@ LL | | where LL | | BAZ: Baz, | |__________________________^ expected `FnOnce(&'any i32)` signature, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` | - = note: expected a closure with signature `for<'any> fn(&'any i32)` - found a closure with signature `fn(&::Param)` + = note: expected type with signature `for<'any> fn(&'any i32)` + found type parameter with signature `fn(&::Param)` note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` --> $DIR/issue-116864.rs:21:20 | From 6314d17b5ef0983be410ad5982b27be4f1f7f0ef Mon Sep 17 00:00:00 2001 From: June Pyle Date: Tue, 29 Sep 2026 22:18:38 -0700 Subject: [PATCH 05/16] Implement attribute parser for #[rustc_assert_variance] --- compiler/rustc_attr_ir/src/data_structures.rs | 17 +++++ .../rustc_attr_ir/src/encode_cross_crate.rs | 2 + .../src/attributes/rustc_internal.rs | 69 ++++++++++++++++++- compiler/rustc_attr_parsing/src/context.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 1 + compiler/rustc_passes/src/check_attr.rs | 35 +++++++++- compiler/rustc_passes/src/diagnostics.rs | 14 ++++ compiler/rustc_span/src/symbol.rs | 4 ++ 8 files changed, 139 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 04fee06e2434c..55970e51dd354 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -718,6 +718,20 @@ impl fmt::Display for AutoDiffItem { } } +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(StableHash, Encodable, Decodable, PrintAttribute)] +pub struct RustcAssertVariance { + pub variances: FxIndexMap, +} + +#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(StableHash, Encodable, Decodable, PrintAttribute)] +pub enum RustcAssertVarianceKind { + Covariant, + Invariant, + Contravariant, +} + #[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)] pub struct UnstableRemovedFeature { pub feature: Symbol, @@ -1145,6 +1159,9 @@ pub enum AttributeKind { /// Represents `#[rustc_as_ptr]` (used by the `dangling_pointers_from_temporaries` lint). RustcAsPtr, + /// Represents `#[rustc_assert_variance]`. + RustcAssertVariance(RustcAssertVariance), + /// Represents `#[rustc_autodiff]`. RustcAutodiff(Option>), diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index b6733e8c1db54..0957a55732de8 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -109,6 +109,7 @@ impl AttributeKind { RustcAllowIncoherentImpl(..) => No, RustcAllowLifetimeDependentSpecialization => No, RustcAsPtr => Yes, + RustcAssertVariance(..) => No, RustcAutodiff(..) => Yes, RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, @@ -323,6 +324,7 @@ impl AttributeKind { RustcAllowIncoherentImpl(..) => false, RustcAllowLifetimeDependentSpecialization => false, RustcAsPtr => false, + RustcAssertVariance(..) => false, RustcAutodiff(..) => false, RustcBodyStability { .. } => false, RustcBuiltinMacro { .. } => false, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 70e5e4803c362..0f8887a54e24a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -3,10 +3,10 @@ use std::path::PathBuf; use rustc_ast::{GenericParamKind, ItemKind, LitIntType, LitKind, MetaItemLit}; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::{ - BorrowckGraphvizFormatKind, CguFields, CguKind, RustcCleanAttribute, RustcCleanQueries, - RustcMirKind, + BorrowckGraphvizFormatKind, CguFields, CguKind, RustcAssertVariance, RustcAssertVarianceKind, + RustcCleanAttribute, RustcCleanQueries, RustcMirKind, }; -use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; use rustc_feature::AttributeStability; use rustc_span::Symbol; @@ -1168,3 +1168,66 @@ impl NoArgsAttributeParser for RustcCanonicalSymbolParser { ); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCanonicalSymbol; } + +pub(crate) struct RustcAssertVarianceParser; + +impl CombineAttributeParser for RustcAssertVarianceParser { + const PATH: &[Symbol] = &[sym::rustc_assert_variance]; + + type Item = (Ident, RustcAssertVarianceKind); + + const CONVERT: ConvertFn = |items, _| { + let mut map = FxIndexMap::default(); + for item in items { + map.insert(item.0, item.1); + } + AttributeKind::RustcAssertVariance(RustcAssertVariance { variances: map }) + }; + const STABILITY: AttributeStability = unstable!(rustc_attrs); + + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ + Allow(Target::Enum), + Allow(Target::Struct), + Allow(Target::Union), + ]); + const TEMPLATE: AttributeTemplate = + template!(List: &[r#"Type1 = "variance", Type2 = "variance", ..."#]); + + fn extend( + cx: &mut AcceptContext<'_, '_>, + args: &ArgParser, + ) -> impl IntoIterator { + let Some(args) = cx.expect_list(args, cx.attr_span) else { return ThinVec::default() }; + + let mut result = ThinVec::default(); + for arg in args.mixed() { + let Some((ident, val)) = cx.expect_name_value(arg, arg.span(), None) else { + continue; + }; + let Some(val_sym) = val.value_as_str() else { + cx.adcx().expected_specific_argument_strings( + val.value_span, + &[sym::covariant, sym::invariant, sym::contravariant], + ); + continue; + }; + + let kind = match val_sym { + sym::covariant => RustcAssertVarianceKind::Covariant, + sym::invariant => RustcAssertVarianceKind::Invariant, + sym::contravariant => RustcAssertVarianceKind::Contravariant, + _ => { + cx.adcx().expected_specific_argument_strings( + val.value_span, + &[sym::covariant, sym::invariant, sym::contravariant], + ); + continue; + } + }; + + result.push((ident, kind)); + } + + result + } +} diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 060fd74c1db21..7c13c0f479aba 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -192,6 +192,7 @@ attribute_parsers!( Combine, Combine, Combine, + Combine, Combine, Combine, Combine, diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index bc8c8f4b2a764..85e94a6d88d6f 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -320,6 +320,7 @@ pub static BUILTIN_ATTRIBUTES: &[Symbol] = &[ // types (as well as any others in future). sym::rustc_lint_opt_deny_field_access, sym::rustc_diagnostic_opaque, + sym::rustc_assert_variance, // ========================================================================== // Internal attributes, Const related: diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3eb6892177b05..6a0f20ebf2c7e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -14,9 +14,10 @@ use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::target::{AssocCtxt, MethodKind, Target}; use rustc_attr_ir::{ Attribute, AttributeKind, DocAttribute, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, - OptimizeAttr, ReprAttr, find_attr, + OptimizeAttr, ReprAttr, RustcAssertVarianceKind, find_attr, }; use rustc_attr_parsing::AttributeParser; +use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{DiagCtxtHandle, IntoDiagArg}; use rustc_feature::BUILTIN_ATTRIBUTE_SET; @@ -223,6 +224,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Linkage(_linkage, span) => { self.check_linkage(*span, hir_id, target, item) } + AttributeKind::RustcAssertVariance(attr) => { + self.check_rustc_assert_variance(target, item, &attr.variances); + } // All of the following attributes have no specific checks. // tidy-alphabetical-start @@ -1417,6 +1421,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => {} } } + + fn check_rustc_assert_variance( + &self, + target: Target, + item: Option<&'tcx Item<'tcx>>, + map: &FxIndexMap, + ) { + // If the target is invalid the parser has already emitted an error + if !matches!(target, Target::Struct | Target::Enum | Target::Union) { + return; + } + + let (item_ident, generics) = match item { + Some(Item { kind: ItemKind::Struct(ident, generics, _), .. }) => (*ident, *generics), + Some(Item { kind: ItemKind::Enum(ident, generics, _), .. }) => (*ident, *generics), + Some(Item { kind: ItemKind::Union(ident, generics, _), .. }) => (*ident, *generics), + _ => return, + }; + + for ident in map.keys() { + if generics.get_named(ident.name).is_none() { + self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceInvalid { + span: ident.span, + invalid_ident: *ident, + item_ident, + }); + } + } + } } impl<'tcx> Visitor<'tcx> for CheckAttrVisitor<'tcx> { diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index b3094d8aaab73..d1a5a408b163c 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -1079,3 +1079,17 @@ pub(crate) struct RustcAtumSuggestion { )] pub unstable_mod_span: Span, } + +#[derive(Diagnostic)] +#[diag("{$invalid_ident} is not a generic type parameter of {$item_ident}")] +#[help( + r#"rustc_assert_variance arguments should be of the form `T = "variance"`, where + `T` is a generic type parameter of the attached item and `"variance"` is one of + `"covariant"`, `"invariant"`, or `"contravariant"`"# +)] +pub(crate) struct RustcAssertVarianceInvalid { + #[primary_span] + pub span: Span, + pub invalid_ident: Ident, + pub item_ident: Ident, +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a9275f489308a..ada44b605a2ac 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -747,6 +747,7 @@ symbols! { contracts_ensures, contracts_internals, contracts_requires, + contravariant, convert, coprocessor, copy, @@ -769,6 +770,7 @@ symbols! { coroutines, cos, count, + covariant, covariant_unsafe_cell, coverage, coverage_attribute, @@ -1189,6 +1191,7 @@ symbols! { into_try_type, intra_doc_pointers, intrinsics, + invariant, irrefutable_let_patterns, is, is_auto, @@ -1817,6 +1820,7 @@ symbols! { rustc_allowed_through_unstable_modules, rustc_always_gca, rustc_as_ptr, + rustc_assert_variance, rustc_attrs, rustc_autodiff, rustc_builtin_macro, From 5f5e9abe13dae0ea9f63f25826cc3076b3a8643e Mon Sep 17 00:00:00 2001 From: June Pyle Date: Wed, 30 Sep 2026 17:03:17 -0700 Subject: [PATCH 06/16] Fully implement rustc_assert_variance. Add additional span data to RustcAssertVariance for diagnostic purposes. --- compiler/rustc_attr_ir/src/data_structures.rs | 2 +- .../src/attributes/rustc_internal.rs | 6 +- compiler/rustc_passes/src/check_attr.rs | 56 +++++++++++++++++-- compiler/rustc_passes/src/diagnostics.rs | 22 ++++++++ compiler/rustc_span/src/symbol.rs | 1 + 5 files changed, 79 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 55970e51dd354..5cea9a0fb5ea7 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -721,7 +721,7 @@ impl fmt::Display for AutoDiffItem { #[derive(Clone, Debug, PartialEq, Eq)] #[derive(StableHash, Encodable, Decodable, PrintAttribute)] pub struct RustcAssertVariance { - pub variances: FxIndexMap, + pub variances: FxIndexMap, } #[derive(Clone, Debug, PartialEq, Eq)] diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 0f8887a54e24a..295f2fbef8808 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1174,12 +1174,12 @@ pub(crate) struct RustcAssertVarianceParser; impl CombineAttributeParser for RustcAssertVarianceParser { const PATH: &[Symbol] = &[sym::rustc_assert_variance]; - type Item = (Ident, RustcAssertVarianceKind); + type Item = (Ident, Span, RustcAssertVarianceKind); const CONVERT: ConvertFn = |items, _| { let mut map = FxIndexMap::default(); for item in items { - map.insert(item.0, item.1); + map.insert(item.0, (item.1, item.2)); } AttributeKind::RustcAssertVariance(RustcAssertVariance { variances: map }) }; @@ -1225,7 +1225,7 @@ impl CombineAttributeParser for RustcAssertVarianceParser { } }; - result.push((ident, kind)); + result.push((ident, cx.attr_span, kind)); } result diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 6a0f20ebf2c7e..0e46b9646781b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -38,7 +38,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::error::{ExpectedFound, TypeError}; -use rustc_middle::ty::{self, TyCtxt, TypingMode, Unnormalized}; +use rustc_middle::ty::{self, TyCtxt, TypingMode, Unnormalized, Variance}; use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, span_bug, sym}; @@ -225,7 +225,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_linkage(*span, hir_id, target, item) } AttributeKind::RustcAssertVariance(attr) => { - self.check_rustc_assert_variance(target, item, &attr.variances); + self.check_rustc_assert_variance(span, hir_id, target, item, &attr.variances); } // All of the following attributes have no specific checks. @@ -1424,9 +1424,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_rustc_assert_variance( &self, + span: Span, + hir_id: HirId, target: Target, item: Option<&'tcx Item<'tcx>>, - map: &FxIndexMap, + map: &FxIndexMap, ) { // If the target is invalid the parser has already emitted an error if !matches!(target, Target::Struct | Target::Enum | Target::Union) { @@ -1440,13 +1442,59 @@ impl<'tcx> CheckAttrVisitor<'tcx> { _ => return, }; + let mut asserted_params = ThinVec::default(); for ident in map.keys() { - if generics.get_named(ident.name).is_none() { + let Some(param) = generics.get_named(ident.name) else { self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceInvalid { span: ident.span, invalid_ident: *ident, item_ident, }); + continue; + }; + asserted_params.push(param); + } + + let variances = self.tcx.variances_of(hir_id.expect_owner().to_def_id()); + let asserts = generics.params.iter().zip(variances.iter()).filter(|(param, _)| { + asserted_params.iter().any(|assert_param| assert_param.def_id == param.def_id) + }); + + for (param, variance) in asserts { + let ident = param.name.ident(); + + match (map.get(&ident), variance) { + (Some((_, RustcAssertVarianceKind::Covariant)), Variance::Covariant) => {} + (Some((_, RustcAssertVarianceKind::Invariant)), Variance::Invariant) => {} + (Some((_, RustcAssertVarianceKind::Contravariant)), Variance::Contravariant) => {} + (asserted, actual) => { + let (attr_span, asserted) = asserted.expect( + "ident should be in rustc_assert_variance map due to previous filter", + ); + + let expected_variance = match asserted { + RustcAssertVarianceKind::Covariant => sym::covariant, + RustcAssertVarianceKind::Invariant => sym::invariant, + RustcAssertVarianceKind::Contravariant => sym::contravariant, + }; + + let actual_variance = match actual { + Variance::Covariant => sym::covariant, + Variance::Invariant => sym::invariant, + Variance::Contravariant => sym::contravariant, + Variance::Bivariant => sym::bivariant, + }; + + let span_note = diagnostics::RustcAssertVarianceFailedNote { span: *attr_span }; + self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceFailed { + span, + span_note, + param_ident: ident, + item_ident, + expected_variance, + actual_variance, + }); + } } } } diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index d1a5a408b163c..308e60bb59665 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -1093,3 +1093,25 @@ pub(crate) struct RustcAssertVarianceInvalid { pub invalid_ident: Ident, pub item_ident: Ident, } + +#[derive(Diagnostic)] +#[diag( + "{$item_ident} is {$actual_variance} in {$param_ident}; expected variance: {$expected_variance}" +)] +pub(crate) struct RustcAssertVarianceFailed { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub span_note: RustcAssertVarianceFailedNote, + pub param_ident: Ident, + pub item_ident: Ident, + pub expected_variance: Symbol, + pub actual_variance: Symbol, +} + +#[derive(Subdiagnostic)] +#[note("required by this annotation")] +pub(crate) struct RustcAssertVarianceFailedNote { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index ada44b605a2ac..6c54f4aaf1dd2 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -564,6 +564,7 @@ symbols! { bits, bitxor, bitxor_assign, + bivariant, black_box, block, blocking, From c56b6ee06703bdcef59bcbbd69b01c2818a12c3b Mon Sep 17 00:00:00 2001 From: June Pyle Date: Wed, 30 Sep 2026 17:54:29 -0700 Subject: [PATCH 07/16] Fix handling of lifetime names for rustc_assert_variance --- compiler/rustc_passes/src/check_attr.rs | 29 +++++++++++++++++-------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 0e46b9646781b..e78cfc79796a2 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1443,8 +1443,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }; let mut asserted_params = ThinVec::default(); + for ident in map.keys() { - let Some(param) = generics.get_named(ident.name) else { + let Some((param_ident, param)) = generics + .params + .iter() + .map(|param| (param.name.ident().without_first_quote(), param)) + .find(|(param_ident, _)| ident == param_ident) + else { self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceInvalid { span: ident.span, invalid_ident: *ident, @@ -1452,18 +1458,23 @@ impl<'tcx> CheckAttrVisitor<'tcx> { }); continue; }; - asserted_params.push(param); + asserted_params.push((param_ident, param)); } let variances = self.tcx.variances_of(hir_id.expect_owner().to_def_id()); - let asserts = generics.params.iter().zip(variances.iter()).filter(|(param, _)| { - asserted_params.iter().any(|assert_param| assert_param.def_id == param.def_id) - }); - for (param, variance) in asserts { - let ident = param.name.ident(); + // A lot of the finicky stuff here is just keeping the ident without first quote we got + // earlier around to avoid the cost of re-obtaining it + let asserts = + generics.params.iter().zip(variances.iter()).filter_map(|(param, variance)| { + asserted_params + .iter() + .find(|(_, assert_param)| assert_param.def_id == param.def_id) + .map(|(assert_ident, _)| (param, assert_ident, variance)) + }); - match (map.get(&ident), variance) { + for (param, ident, variance) in asserts { + match (map.get(ident), variance) { (Some((_, RustcAssertVarianceKind::Covariant)), Variance::Covariant) => {} (Some((_, RustcAssertVarianceKind::Invariant)), Variance::Invariant) => {} (Some((_, RustcAssertVarianceKind::Contravariant)), Variance::Contravariant) => {} @@ -1489,7 +1500,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceFailed { span, span_note, - param_ident: ident, + param_ident: param.name.ident(), item_ident, expected_variance, actual_variance, From 6abfa1ca67bc9e2c751f9e971681085995b8db99 Mon Sep 17 00:00:00 2001 From: June Pyle Date: Wed, 30 Sep 2026 19:46:42 -0700 Subject: [PATCH 08/16] - Box `RustcAssertVariance` in `AttributeKind` to prevent increasing the size of `AttributeKind` - Add ui test for #[rustc_assert_variance] --- compiler/rustc_attr_ir/src/data_structures.rs | 2 +- .../src/attributes/rustc_internal.rs | 2 +- tests/ui/attributes/rustc_assert_variance.rs | 87 +++++++++++ .../attributes/rustc_assert_variance.stderr | 135 ++++++++++++++++++ 4 files changed, 224 insertions(+), 2 deletions(-) create mode 100644 tests/ui/attributes/rustc_assert_variance.rs create mode 100644 tests/ui/attributes/rustc_assert_variance.stderr diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 5cea9a0fb5ea7..a3ce9ca2b88c4 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1160,7 +1160,7 @@ pub enum AttributeKind { RustcAsPtr, /// Represents `#[rustc_assert_variance]`. - RustcAssertVariance(RustcAssertVariance), + RustcAssertVariance(Box), /// Represents `#[rustc_autodiff]`. RustcAutodiff(Option>), diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 295f2fbef8808..984bbb104b484 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1181,7 +1181,7 @@ impl CombineAttributeParser for RustcAssertVarianceParser { for item in items { map.insert(item.0, (item.1, item.2)); } - AttributeKind::RustcAssertVariance(RustcAssertVariance { variances: map }) + AttributeKind::RustcAssertVariance(Box::new(RustcAssertVariance { variances: map })) }; const STABILITY: AttributeStability = unstable!(rustc_attrs); diff --git a/tests/ui/attributes/rustc_assert_variance.rs b/tests/ui/attributes/rustc_assert_variance.rs new file mode 100644 index 0000000000000..1ef8e782c1d0d --- /dev/null +++ b/tests/ui/attributes/rustc_assert_variance.rs @@ -0,0 +1,87 @@ +#![feature(rustc_attrs)] +#![allow(unused)] + +#[rustc_assert_variance] +//~^ ERROR malformed `rustc_assert_variance` attribute input +//~| NOTE expected this to be a list +//~| HELP must be of the form +struct Foo1 { + val: T, +} + +#[rustc_assert_variance(T)] +//~^ ERROR malformed `rustc_assert_variance` attribute input +//~| NOTE expected this to be of the form +//~| HELP must be of the form +struct Foo2 { + val: T, +} + +#[rustc_assert_variance(T = "nonsense")] +//~^ ERROR malformed `rustc_assert_variance` attribute input +//~| NOTE valid arguments are "covariant", "invariant" or "contravariant" +//~| HELP must be of the form +struct Foo3 { + val: T, +} + +#[rustc_assert_variance(T = "bivariant")] +//~^ ERROR malformed `rustc_assert_variance` attribute input +//~| NOTE valid arguments are "covariant", "invariant" or "contravariant" +//~| HELP must be of the form +struct Foo4 { + val: T, +} + +#[rustc_assert_variance(U = "covariant")] +//~^ ERROR not a generic type parameter of +//~| HELP rustc_assert_variance arguments should be of the form +struct Foo5 { + val: T, +} + +#[rustc_assert_variance(T = "invariant")] +//~^ NOTE required by this annotation +struct Foo6 { + val: T, +} +//~^^^ ERROR Foo6 is covariant in T; expected variance: invariant + +#[rustc_assert_variance(a = "invariant")] +//~^ NOTE required by this annotation +#[rustc_assert_variance(T = "covariant")] +//~^ NOTE required by this annotation +struct Foo7<'a, T> { + val: &'a mut T, +} +//~^^^ ERROR Foo7 is covariant in 'a; expected variance: invariant +//~| ERROR Foo7 is invariant in T; expected variance: covariant + +#[rustc_assert_variance(a = "contravariant", T = "contravariant")] +//~^ NOTE required by this annotation +//~| NOTE required by this annotation +struct Foo8<'a, T> { + val: &'a mut T, +} +//~^^^ ERROR Foo8 is covariant in 'a; expected variance: contravariant +//~| ERROR Foo8 is invariant in T; expected variance: contravariant + +// The following should all work + +#[rustc_assert_variance(T = "covariant")] +struct Bar1 { + val: T, +} + +#[rustc_assert_variance(T = "contravariant", U = "covariant")] +struct Bar2 { + val: fn(T) -> U, +} + +#[rustc_assert_variance(a = "covariant")] +#[rustc_assert_variance(T = "invariant")] +struct Bar3<'a, T> { + val: &'a mut T, +} + +fn main() {} diff --git a/tests/ui/attributes/rustc_assert_variance.stderr b/tests/ui/attributes/rustc_assert_variance.stderr new file mode 100644 index 0000000000000..5e7c524b174f7 --- /dev/null +++ b/tests/ui/attributes/rustc_assert_variance.stderr @@ -0,0 +1,135 @@ +error[E0539]: malformed `rustc_assert_variance` attribute input + --> $DIR/rustc_assert_variance.rs:4:3 + | +LL | #[rustc_assert_variance] + | ^^^^^^^^^^^^^^^^^^^^^ expected this to be a list + | +help: must be of the form + | +LL | #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] + | +++++++++++++++++++++++++++++++++++++++++++++ + +error[E0539]: malformed `rustc_assert_variance` attribute input + --> $DIR/rustc_assert_variance.rs:12:3 + | +LL | #[rustc_assert_variance(T)] + | ^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | expected this to be of the form `... = "..."` + | +help: must be of the form + | +LL | #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] + | ++++++++++++++++++++++++++++++++++++++++++ + +error[E0539]: malformed `rustc_assert_variance` attribute input + --> $DIR/rustc_assert_variance.rs:20:3 + | +LL | #[rustc_assert_variance(T = "nonsense")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^----------^ + | | + | valid arguments are "covariant", "invariant" or "contravariant" + | +help: must be of the form + | +LL - #[rustc_assert_variance(T = "nonsense")] +LL + #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] + | + +error[E0539]: malformed `rustc_assert_variance` attribute input + --> $DIR/rustc_assert_variance.rs:28:3 + | +LL | #[rustc_assert_variance(T = "bivariant")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^ + | | + | valid arguments are "covariant", "invariant" or "contravariant" + | +help: must be of the form + | +LL - #[rustc_assert_variance(T = "bivariant")] +LL + #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] + | + +error: U is not a generic type parameter of Foo5 + --> $DIR/rustc_assert_variance.rs:36:25 + | +LL | #[rustc_assert_variance(U = "covariant")] + | ^ + | + = help: rustc_assert_variance arguments should be of the form `T = "variance"`, where + `T` is a generic type parameter of the attached item and `"variance"` is one of + `"covariant"`, `"invariant"`, or `"contravariant"` + +error: Foo6 is covariant in T; expected variance: invariant + --> $DIR/rustc_assert_variance.rs:45:1 + | +LL | / struct Foo6 { +LL | | val: T, +LL | | } + | |_^ + | +note: required by this annotation + --> $DIR/rustc_assert_variance.rs:43:1 + | +LL | #[rustc_assert_variance(T = "invariant")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Foo7 is covariant in 'a; expected variance: invariant + --> $DIR/rustc_assert_variance.rs:54:1 + | +LL | / struct Foo7<'a, T> { +LL | | val: &'a mut T, +LL | | } + | |_^ + | +note: required by this annotation + --> $DIR/rustc_assert_variance.rs:50:1 + | +LL | #[rustc_assert_variance(a = "invariant")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Foo7 is invariant in T; expected variance: covariant + --> $DIR/rustc_assert_variance.rs:54:1 + | +LL | / struct Foo7<'a, T> { +LL | | val: &'a mut T, +LL | | } + | |_^ + | +note: required by this annotation + --> $DIR/rustc_assert_variance.rs:52:1 + | +LL | #[rustc_assert_variance(T = "covariant")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Foo8 is covariant in 'a; expected variance: contravariant + --> $DIR/rustc_assert_variance.rs:63:1 + | +LL | / struct Foo8<'a, T> { +LL | | val: &'a mut T, +LL | | } + | |_^ + | +note: required by this annotation + --> $DIR/rustc_assert_variance.rs:60:1 + | +LL | #[rustc_assert_variance(a = "contravariant", T = "contravariant")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: Foo8 is invariant in T; expected variance: contravariant + --> $DIR/rustc_assert_variance.rs:63:1 + | +LL | / struct Foo8<'a, T> { +LL | | val: &'a mut T, +LL | | } + | |_^ + | +note: required by this annotation + --> $DIR/rustc_assert_variance.rs:60:1 + | +LL | #[rustc_assert_variance(a = "contravariant", T = "contravariant")] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 10 previous errors + +For more information about this error, try `rustc --explain E0539`. From 576a9e5fa8323619f71ae2bbcc9bc47b4448c77d Mon Sep 17 00:00:00 2001 From: June Pyle Date: Thu, 1 Oct 2026 08:43:35 -0700 Subject: [PATCH 09/16] - Change rustc_assert_variance attribute to be attached to generic parameters instead of their parent ADTs - Add support for bivariance to rustc_assert_variance - Update rustc_assert_variance ui test accordingly and add case for const generic params - Minor diagnostic message fix --- compiler/rustc_attr_ir/src/data_structures.rs | 14 +- .../rustc_attr_ir/src/encode_cross_crate.rs | 4 +- .../src/attributes/rustc_internal.rs | 86 +++++----- compiler/rustc_attr_parsing/src/context.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 123 ++++++-------- compiler/rustc_passes/src/diagnostics.rs | 16 +- tests/ui/attributes/rustc_assert_variance.rs | 98 +++++------- .../attributes/rustc_assert_variance.stderr | 150 ++++++------------ 8 files changed, 191 insertions(+), 302 deletions(-) diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index a3ce9ca2b88c4..c2a3b8624f416 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -718,18 +718,13 @@ impl fmt::Display for AutoDiffItem { } } -#[derive(Clone, Debug, PartialEq, Eq)] -#[derive(StableHash, Encodable, Decodable, PrintAttribute)] -pub struct RustcAssertVariance { - pub variances: FxIndexMap, -} - -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] #[derive(StableHash, Encodable, Decodable, PrintAttribute)] pub enum RustcAssertVarianceKind { Covariant, Invariant, Contravariant, + Bivariant, } #[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute)] @@ -1160,7 +1155,10 @@ pub enum AttributeKind { RustcAsPtr, /// Represents `#[rustc_assert_variance]`. - RustcAssertVariance(Box), + RustcAssertVariance { + span: Span, + kind: RustcAssertVarianceKind, + }, /// Represents `#[rustc_autodiff]`. RustcAutodiff(Option>), diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index 0957a55732de8..57475d2dbe098 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -109,7 +109,7 @@ impl AttributeKind { RustcAllowIncoherentImpl(..) => No, RustcAllowLifetimeDependentSpecialization => No, RustcAsPtr => Yes, - RustcAssertVariance(..) => No, + RustcAssertVariance { .. } => No, RustcAutodiff(..) => Yes, RustcBodyStability { .. } => No, RustcBuiltinMacro { .. } => Yes, @@ -324,7 +324,7 @@ impl AttributeKind { RustcAllowIncoherentImpl(..) => false, RustcAllowLifetimeDependentSpecialization => false, RustcAsPtr => false, - RustcAssertVariance(..) => false, + RustcAssertVariance { .. } => false, RustcAutodiff(..) => false, RustcBodyStability { .. } => false, RustcBuiltinMacro { .. } => false, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 984bbb104b484..52422a85041a4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -3,10 +3,10 @@ use std::path::PathBuf; use rustc_ast::{GenericParamKind, ItemKind, LitIntType, LitKind, MetaItemLit}; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::{ - BorrowckGraphvizFormatKind, CguFields, CguKind, RustcAssertVariance, RustcAssertVarianceKind, - RustcCleanAttribute, RustcCleanQueries, RustcMirKind, + BorrowckGraphvizFormatKind, CguFields, CguKind, RustcAssertVarianceKind, RustcCleanAttribute, + RustcCleanQueries, RustcMirKind, }; -use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; +use rustc_data_structures::fx::FxHashMap; use rustc_feature::AttributeStability; use rustc_span::Symbol; @@ -1171,63 +1171,51 @@ impl NoArgsAttributeParser for RustcCanonicalSymbolParser { pub(crate) struct RustcAssertVarianceParser; -impl CombineAttributeParser for RustcAssertVarianceParser { +impl SingleAttributeParser for RustcAssertVarianceParser { const PATH: &[Symbol] = &[sym::rustc_assert_variance]; - type Item = (Ident, Span, RustcAssertVarianceKind); - - const CONVERT: ConvertFn = |items, _| { - let mut map = FxIndexMap::default(); - for item in items { - map.insert(item.0, (item.1, item.2)); - } - AttributeKind::RustcAssertVariance(Box::new(RustcAssertVariance { variances: map })) - }; const STABILITY: AttributeStability = unstable!(rustc_attrs); const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::Enum), - Allow(Target::Struct), - Allow(Target::Union), + Allow(Target::TypeParam), + Allow(Target::LifetimeParam), + Allow(Target::ConstParam), ]); + const TEMPLATE: AttributeTemplate = - template!(List: &[r#"Type1 = "variance", Type2 = "variance", ..."#]); + template!(OneOf: &[sym::covariant, sym::invariant, sym::contravariant, sym::bivariant]); - fn extend( - cx: &mut AcceptContext<'_, '_>, - args: &ArgParser, - ) -> impl IntoIterator { - let Some(args) = cx.expect_list(args, cx.attr_span) else { return ThinVec::default() }; + fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { + let arg = cx.expect_single_element_list(args, cx.attr_span)?; - let mut result = ThinVec::default(); - for arg in args.mixed() { - let Some((ident, val)) = cx.expect_name_value(arg, arg.span(), None) else { - continue; - }; - let Some(val_sym) = val.value_as_str() else { - cx.adcx().expected_specific_argument_strings( - val.value_span, - &[sym::covariant, sym::invariant, sym::contravariant], - ); - continue; - }; + let mut fail_arg = |span| { + cx.adcx().expected_specific_argument( + span, + &[sym::covariant, sym::invariant, sym::contravariant, sym::bivariant], + ) + }; - let kind = match val_sym { - sym::covariant => RustcAssertVarianceKind::Covariant, - sym::invariant => RustcAssertVarianceKind::Invariant, - sym::contravariant => RustcAssertVarianceKind::Contravariant, - _ => { - cx.adcx().expected_specific_argument_strings( - val.value_span, - &[sym::covariant, sym::invariant, sym::contravariant], - ); - continue; - } - }; + let Some(arg) = arg.meta_item_no_args() else { + fail_arg(arg.span()); + return None; + }; - result.push((ident, cx.attr_span, kind)); - } + let Some(arg) = arg.ident() else { + fail_arg(arg.span()); + return None; + }; + + let kind = match arg.name { + sym::covariant => RustcAssertVarianceKind::Covariant, + sym::invariant => RustcAssertVarianceKind::Invariant, + sym::contravariant => RustcAssertVarianceKind::Contravariant, + sym::bivariant => RustcAssertVarianceKind::Bivariant, + _ => { + fail_arg(arg.span); + return None; + } + }; - result + Some(AttributeKind::RustcAssertVariance { span: cx.attr_span, kind }) } } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 7c13c0f479aba..25465bd50f8d3 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -192,7 +192,6 @@ attribute_parsers!( Combine, Combine, Combine, - Combine, Combine, Combine, Combine, @@ -233,6 +232,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index e78cfc79796a2..dbb2adf18fc6b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -17,7 +17,6 @@ use rustc_attr_ir::{ OptimizeAttr, ReprAttr, RustcAssertVarianceKind, find_attr, }; use rustc_attr_parsing::AttributeParser; -use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{DiagCtxtHandle, IntoDiagArg}; use rustc_feature::BUILTIN_ATTRIBUTE_SET; @@ -224,8 +223,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::Linkage(_linkage, span) => { self.check_linkage(*span, hir_id, target, item) } - AttributeKind::RustcAssertVariance(attr) => { - self.check_rustc_assert_variance(span, hir_id, target, item, &attr.variances); + AttributeKind::RustcAssertVariance { span: attr_span, kind } => { + self.check_rustc_assert_variance(span, *attr_span, hir_id, target, *kind); } // All of the following attributes have no specific checks. @@ -1425,87 +1424,61 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_rustc_assert_variance( &self, span: Span, + attr_span: Span, hir_id: HirId, target: Target, - item: Option<&'tcx Item<'tcx>>, - map: &FxIndexMap, + kind: RustcAssertVarianceKind, ) { // If the target is invalid the parser has already emitted an error - if !matches!(target, Target::Struct | Target::Enum | Target::Union) { + if !matches!(target, Target::TypeParam | Target::LifetimeParam | Target::ConstParam) { return; } - let (item_ident, generics) = match item { - Some(Item { kind: ItemKind::Struct(ident, generics, _), .. }) => (*ident, *generics), - Some(Item { kind: ItemKind::Enum(ident, generics, _), .. }) => (*ident, *generics), - Some(Item { kind: ItemKind::Union(ident, generics, _), .. }) => (*ident, *generics), - _ => return, - }; - - let mut asserted_params = ThinVec::default(); - - for ident in map.keys() { - let Some((param_ident, param)) = generics - .params - .iter() - .map(|param| (param.name.ident().without_first_quote(), param)) - .find(|(param_ident, _)| ident == param_ident) - else { - self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceInvalid { - span: ident.span, - invalid_ident: *ident, + let Node::GenericParam(param) = self.tcx.hir_node(hir_id) else { return }; + let owner = hir_id.owner.to_def_id(); + let variances = self.tcx.variances_of(owner); + let generics = self.tcx.generics_of(owner); + + let variance = generics + .own_params + .iter() + .zip(variances.iter()) + .filter(|(other_param, _)| other_param.def_id == param.def_id.to_def_id()) + .map(|(_, variance)| variance) + .nth(0) + .expect("generic parameter should have variance"); + + match (kind, variance) { + (RustcAssertVarianceKind::Covariant, Variance::Covariant) => {} + (RustcAssertVarianceKind::Invariant, Variance::Invariant) => {} + (RustcAssertVarianceKind::Contravariant, Variance::Contravariant) => {} + (RustcAssertVarianceKind::Bivariant, Variance::Bivariant) => {} + (asserted, actual) => { + let expected_variance = match asserted { + RustcAssertVarianceKind::Covariant => sym::covariant, + RustcAssertVarianceKind::Invariant => sym::invariant, + RustcAssertVarianceKind::Contravariant => sym::contravariant, + RustcAssertVarianceKind::Bivariant => sym::bivariant, + }; + + let actual_variance = match actual { + Variance::Covariant => sym::covariant, + Variance::Invariant => sym::invariant, + Variance::Contravariant => sym::contravariant, + Variance::Bivariant => sym::bivariant, + }; + + let item_ident = self.tcx.item_ident(owner); + + let span_note = diagnostics::RustcAssertVarianceFailedNote { span: attr_span }; + self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceFailed { + span, + span_note, + param_ident: param.name.ident(), item_ident, + expected_variance, + actual_variance, }); - continue; - }; - asserted_params.push((param_ident, param)); - } - - let variances = self.tcx.variances_of(hir_id.expect_owner().to_def_id()); - - // A lot of the finicky stuff here is just keeping the ident without first quote we got - // earlier around to avoid the cost of re-obtaining it - let asserts = - generics.params.iter().zip(variances.iter()).filter_map(|(param, variance)| { - asserted_params - .iter() - .find(|(_, assert_param)| assert_param.def_id == param.def_id) - .map(|(assert_ident, _)| (param, assert_ident, variance)) - }); - - for (param, ident, variance) in asserts { - match (map.get(ident), variance) { - (Some((_, RustcAssertVarianceKind::Covariant)), Variance::Covariant) => {} - (Some((_, RustcAssertVarianceKind::Invariant)), Variance::Invariant) => {} - (Some((_, RustcAssertVarianceKind::Contravariant)), Variance::Contravariant) => {} - (asserted, actual) => { - let (attr_span, asserted) = asserted.expect( - "ident should be in rustc_assert_variance map due to previous filter", - ); - - let expected_variance = match asserted { - RustcAssertVarianceKind::Covariant => sym::covariant, - RustcAssertVarianceKind::Invariant => sym::invariant, - RustcAssertVarianceKind::Contravariant => sym::contravariant, - }; - - let actual_variance = match actual { - Variance::Covariant => sym::covariant, - Variance::Invariant => sym::invariant, - Variance::Contravariant => sym::contravariant, - Variance::Bivariant => sym::bivariant, - }; - - let span_note = diagnostics::RustcAssertVarianceFailedNote { span: *attr_span }; - self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceFailed { - span, - span_note, - param_ident: param.name.ident(), - item_ident, - expected_variance, - actual_variance, - }); - } } } } diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 308e60bb59665..74c669da65d69 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -1080,23 +1080,9 @@ pub(crate) struct RustcAtumSuggestion { pub unstable_mod_span: Span, } -#[derive(Diagnostic)] -#[diag("{$invalid_ident} is not a generic type parameter of {$item_ident}")] -#[help( - r#"rustc_assert_variance arguments should be of the form `T = "variance"`, where - `T` is a generic type parameter of the attached item and `"variance"` is one of - `"covariant"`, `"invariant"`, or `"contravariant"`"# -)] -pub(crate) struct RustcAssertVarianceInvalid { - #[primary_span] - pub span: Span, - pub invalid_ident: Ident, - pub item_ident: Ident, -} - #[derive(Diagnostic)] #[diag( - "{$item_ident} is {$actual_variance} in {$param_ident}; expected variance: {$expected_variance}" + "`{$item_ident}` is {$actual_variance} in `{$param_ident}`; expected variance: {$expected_variance}" )] pub(crate) struct RustcAssertVarianceFailed { #[primary_span] diff --git a/tests/ui/attributes/rustc_assert_variance.rs b/tests/ui/attributes/rustc_assert_variance.rs index 1ef8e782c1d0d..616bfd5fded15 100644 --- a/tests/ui/attributes/rustc_assert_variance.rs +++ b/tests/ui/attributes/rustc_assert_variance.rs @@ -1,87 +1,77 @@ #![feature(rustc_attrs)] #![allow(unused)] -#[rustc_assert_variance] -//~^ ERROR malformed `rustc_assert_variance` attribute input -//~| NOTE expected this to be a list -//~| HELP must be of the form -struct Foo1 { +struct Foo1<#[rustc_assert_variance] T> { + //~^ ERROR malformed `rustc_assert_variance` attribute input + //~| NOTE expected this to be a list val: T, } -#[rustc_assert_variance(T)] -//~^ ERROR malformed `rustc_assert_variance` attribute input -//~| NOTE expected this to be of the form -//~| HELP must be of the form -struct Foo2 { +struct Foo2<#[rustc_assert_variance(nonsense)] T> { + //~^ ERROR malformed `rustc_assert_variance` attribute input + //~| NOTE valid arguments are `covariant`, `invariant`, `contravariant` or `bivariant` val: T, } -#[rustc_assert_variance(T = "nonsense")] -//~^ ERROR malformed `rustc_assert_variance` attribute input -//~| NOTE valid arguments are "covariant", "invariant" or "contravariant" -//~| HELP must be of the form -struct Foo3 { +struct Foo3<#[rustc_assert_variance(bivariant)] T> { + //~^ ERROR `Foo3` is covariant in `T`; expected variance: bivariant + //~| NOTE required by this annotation val: T, } -#[rustc_assert_variance(T = "bivariant")] -//~^ ERROR malformed `rustc_assert_variance` attribute input -//~| NOTE valid arguments are "covariant", "invariant" or "contravariant" -//~| HELP must be of the form -struct Foo4 { +struct Foo4<#[rustc_assert_variance(invariant)] T> { + //~^ ERROR `Foo4` is covariant in `T`; expected variance: invariant + //~| NOTE required by this annotation val: T, } -#[rustc_assert_variance(U = "covariant")] -//~^ ERROR not a generic type parameter of -//~| HELP rustc_assert_variance arguments should be of the form -struct Foo5 { - val: T, -} - -#[rustc_assert_variance(T = "invariant")] -//~^ NOTE required by this annotation -struct Foo6 { - val: T, -} -//~^^^ ERROR Foo6 is covariant in T; expected variance: invariant - -#[rustc_assert_variance(a = "invariant")] -//~^ NOTE required by this annotation -#[rustc_assert_variance(T = "covariant")] -//~^ NOTE required by this annotation -struct Foo7<'a, T> { +struct Foo5< + #[rustc_assert_variance(invariant)] + //~^ NOTE required by this annotation + 'a, + //~^ ERROR `Foo5` is covariant in `'a`; expected variance: invariant + #[rustc_assert_variance(covariant)] + //~^ NOTE required by this annotation + T, + //~^ ERROR `Foo5` is invariant in `T`; expected variance: covariant +> { val: &'a mut T, } -//~^^^ ERROR Foo7 is covariant in 'a; expected variance: invariant -//~| ERROR Foo7 is invariant in T; expected variance: covariant -#[rustc_assert_variance(a = "contravariant", T = "contravariant")] -//~^ NOTE required by this annotation -//~| NOTE required by this annotation -struct Foo8<'a, T> { +struct Foo6< + #[rustc_assert_variance(contravariant)] + //~^ NOTE required by this annotation + 'a, + //~^ ERROR `Foo6` is covariant in `'a`; expected variance: contravariant + #[rustc_assert_variance(contravariant)] + //~^ NOTE required by this annotation + T, + //~^ ERROR `Foo6` is invariant in `T`; expected variance: contravariant +> { val: &'a mut T, } -//~^^^ ERROR Foo8 is covariant in 'a; expected variance: contravariant -//~| ERROR Foo8 is invariant in T; expected variance: contravariant // The following should all work -#[rustc_assert_variance(T = "covariant")] -struct Bar1 { +struct Bar1<#[rustc_assert_variance(covariant)] T> { val: T, } -#[rustc_assert_variance(T = "contravariant", U = "covariant")] -struct Bar2 { +struct Bar2<#[rustc_assert_variance(contravariant)] T, #[rustc_assert_variance(covariant)] U> { val: fn(T) -> U, } -#[rustc_assert_variance(a = "covariant")] -#[rustc_assert_variance(T = "invariant")] -struct Bar3<'a, T> { +struct Bar3<#[rustc_assert_variance(covariant)] 'a, #[rustc_assert_variance(invariant)] T> { val: &'a mut T, } +struct Bar4<#[rustc_assert_variance(invariant)] const N: usize> {} + +struct Bar5<#[rustc_assert_variance(covariant)] T, #[rustc_assert_variance(bivariant)] U> +where + T: Iterator, +{ + val: T, +} + fn main() {} diff --git a/tests/ui/attributes/rustc_assert_variance.stderr b/tests/ui/attributes/rustc_assert_variance.stderr index 5e7c524b174f7..4055c39723673 100644 --- a/tests/ui/attributes/rustc_assert_variance.stderr +++ b/tests/ui/attributes/rustc_assert_variance.stderr @@ -1,135 +1,89 @@ error[E0539]: malformed `rustc_assert_variance` attribute input - --> $DIR/rustc_assert_variance.rs:4:3 + --> $DIR/rustc_assert_variance.rs:4:15 | -LL | #[rustc_assert_variance] - | ^^^^^^^^^^^^^^^^^^^^^ expected this to be a list - | -help: must be of the form - | -LL | #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] - | +++++++++++++++++++++++++++++++++++++++++++++ - -error[E0539]: malformed `rustc_assert_variance` attribute input - --> $DIR/rustc_assert_variance.rs:12:3 - | -LL | #[rustc_assert_variance(T)] - | ^^^^^^^^^^^^^^^^^^^^^^-^ - | | - | expected this to be of the form `... = "..."` - | -help: must be of the form - | -LL | #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] - | ++++++++++++++++++++++++++++++++++++++++++ +LL | struct Foo1<#[rustc_assert_variance] T> { + | ^^^^^^^^^^^^^^^^^^^^^ expected this to be a list error[E0539]: malformed `rustc_assert_variance` attribute input - --> $DIR/rustc_assert_variance.rs:20:3 - | -LL | #[rustc_assert_variance(T = "nonsense")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^----------^ - | | - | valid arguments are "covariant", "invariant" or "contravariant" - | -help: must be of the form - | -LL - #[rustc_assert_variance(T = "nonsense")] -LL + #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] + --> $DIR/rustc_assert_variance.rs:10:15 | +LL | struct Foo2<#[rustc_assert_variance(nonsense)] T> { + | ^^^^^^^^^^^^^^^^^^^^^^--------^ + | | + | valid arguments are `covariant`, `invariant`, `contravariant` or `bivariant` -error[E0539]: malformed `rustc_assert_variance` attribute input - --> $DIR/rustc_assert_variance.rs:28:3 - | -LL | #[rustc_assert_variance(T = "bivariant")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^-----------^ - | | - | valid arguments are "covariant", "invariant" or "contravariant" +error: `Foo3` is covariant in `T`; expected variance: bivariant + --> $DIR/rustc_assert_variance.rs:16:49 | -help: must be of the form +LL | struct Foo3<#[rustc_assert_variance(bivariant)] T> { + | ^ | -LL - #[rustc_assert_variance(T = "bivariant")] -LL + #[rustc_assert_variance(Type1 = "variance", Type2 = "variance", ...)] - | - -error: U is not a generic type parameter of Foo5 - --> $DIR/rustc_assert_variance.rs:36:25 - | -LL | #[rustc_assert_variance(U = "covariant")] - | ^ +note: required by this annotation + --> $DIR/rustc_assert_variance.rs:16:13 | - = help: rustc_assert_variance arguments should be of the form `T = "variance"`, where - `T` is a generic type parameter of the attached item and `"variance"` is one of - `"covariant"`, `"invariant"`, or `"contravariant"` +LL | struct Foo3<#[rustc_assert_variance(bivariant)] T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Foo6 is covariant in T; expected variance: invariant - --> $DIR/rustc_assert_variance.rs:45:1 +error: `Foo4` is covariant in `T`; expected variance: invariant + --> $DIR/rustc_assert_variance.rs:22:49 | -LL | / struct Foo6 { -LL | | val: T, -LL | | } - | |_^ +LL | struct Foo4<#[rustc_assert_variance(invariant)] T> { + | ^ | note: required by this annotation - --> $DIR/rustc_assert_variance.rs:43:1 + --> $DIR/rustc_assert_variance.rs:22:13 | -LL | #[rustc_assert_variance(T = "invariant")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | struct Foo4<#[rustc_assert_variance(invariant)] T> { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Foo7 is covariant in 'a; expected variance: invariant - --> $DIR/rustc_assert_variance.rs:54:1 +error: `Foo5` is covariant in `'a`; expected variance: invariant + --> $DIR/rustc_assert_variance.rs:31:5 | -LL | / struct Foo7<'a, T> { -LL | | val: &'a mut T, -LL | | } - | |_^ +LL | 'a, + | ^^ | note: required by this annotation - --> $DIR/rustc_assert_variance.rs:50:1 + --> $DIR/rustc_assert_variance.rs:29:5 | -LL | #[rustc_assert_variance(a = "invariant")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_assert_variance(invariant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Foo7 is invariant in T; expected variance: covariant - --> $DIR/rustc_assert_variance.rs:54:1 +error: `Foo5` is invariant in `T`; expected variance: covariant + --> $DIR/rustc_assert_variance.rs:35:5 | -LL | / struct Foo7<'a, T> { -LL | | val: &'a mut T, -LL | | } - | |_^ +LL | T, + | ^ | note: required by this annotation - --> $DIR/rustc_assert_variance.rs:52:1 + --> $DIR/rustc_assert_variance.rs:33:5 | -LL | #[rustc_assert_variance(T = "covariant")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_assert_variance(covariant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Foo8 is covariant in 'a; expected variance: contravariant - --> $DIR/rustc_assert_variance.rs:63:1 +error: `Foo6` is covariant in `'a`; expected variance: contravariant + --> $DIR/rustc_assert_variance.rs:44:5 | -LL | / struct Foo8<'a, T> { -LL | | val: &'a mut T, -LL | | } - | |_^ +LL | 'a, + | ^^ | note: required by this annotation - --> $DIR/rustc_assert_variance.rs:60:1 + --> $DIR/rustc_assert_variance.rs:42:5 | -LL | #[rustc_assert_variance(a = "contravariant", T = "contravariant")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_assert_variance(contravariant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: Foo8 is invariant in T; expected variance: contravariant - --> $DIR/rustc_assert_variance.rs:63:1 +error: `Foo6` is invariant in `T`; expected variance: contravariant + --> $DIR/rustc_assert_variance.rs:48:5 | -LL | / struct Foo8<'a, T> { -LL | | val: &'a mut T, -LL | | } - | |_^ +LL | T, + | ^ | note: required by this annotation - --> $DIR/rustc_assert_variance.rs:60:1 + --> $DIR/rustc_assert_variance.rs:46:5 | -LL | #[rustc_assert_variance(a = "contravariant", T = "contravariant")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | #[rustc_assert_variance(contravariant)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 10 previous errors +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0539`. From 6d5354fa557544e70643e3a2f496a9ea3fb06594 Mon Sep 17 00:00:00 2001 From: June Pyle Date: Fri, 2 Oct 2026 20:29:29 -0700 Subject: [PATCH 10/16] Improve diagnostic messages for rustc_assert_variance and update ui test accordingly --- compiler/rustc_passes/src/check_attr.rs | 7 +- compiler/rustc_passes/src/diagnostics.rs | 12 +- tests/ui/attributes/rustc_assert_variance.rs | 30 +++-- .../attributes/rustc_assert_variance.stderr | 118 ++++++++++++------ 4 files changed, 105 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index dbb2adf18fc6b..af61cca62122a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1470,11 +1470,12 @@ impl<'tcx> CheckAttrVisitor<'tcx> { let item_ident = self.tcx.item_ident(owner); - let span_note = diagnostics::RustcAssertVarianceFailedNote { span: attr_span }; + let note = diagnostics::RustcAssertVarianceFailedNote { span: attr_span }; self.tcx.dcx().emit_err(diagnostics::RustcAssertVarianceFailed { - span, - span_note, + item_span: self.tcx.def_span(owner), + note, param_ident: param.name.ident(), + param_span: span, item_ident, expected_variance, actual_variance, diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 74c669da65d69..9ec4e10c5fa64 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -1081,14 +1081,14 @@ pub(crate) struct RustcAtumSuggestion { } #[derive(Diagnostic)] -#[diag( - "`{$item_ident}` is {$actual_variance} in `{$param_ident}`; expected variance: {$expected_variance}" -)] +#[diag("`{$item_ident}` is expected to be {$expected_variance} in `{$param_ident}` but is not")] pub(crate) struct RustcAssertVarianceFailed { #[primary_span] - pub span: Span, + pub item_span: Span, #[subdiagnostic] - pub span_note: RustcAssertVarianceFailedNote, + pub note: RustcAssertVarianceFailedNote, + #[label("`{$item_ident}` is {$actual_variance} in `{$param_ident}`")] + pub param_span: Span, pub param_ident: Ident, pub item_ident: Ident, pub expected_variance: Symbol, @@ -1096,7 +1096,7 @@ pub(crate) struct RustcAssertVarianceFailed { } #[derive(Subdiagnostic)] -#[note("required by this annotation")] +#[note("required by this attribute")] pub(crate) struct RustcAssertVarianceFailedNote { #[primary_span] pub span: Span, diff --git a/tests/ui/attributes/rustc_assert_variance.rs b/tests/ui/attributes/rustc_assert_variance.rs index 616bfd5fded15..648fe6499df73 100644 --- a/tests/ui/attributes/rustc_assert_variance.rs +++ b/tests/ui/attributes/rustc_assert_variance.rs @@ -14,39 +14,45 @@ struct Foo2<#[rustc_assert_variance(nonsense)] T> { } struct Foo3<#[rustc_assert_variance(bivariant)] T> { - //~^ ERROR `Foo3` is covariant in `T`; expected variance: bivariant - //~| NOTE required by this annotation + //~^ ERROR `Foo3` is expected to be bivariant in `T` but is not + //~| NOTE `Foo3` is covariant in `T` + //~| NOTE required by this attribute val: T, } struct Foo4<#[rustc_assert_variance(invariant)] T> { - //~^ ERROR `Foo4` is covariant in `T`; expected variance: invariant - //~| NOTE required by this annotation + //~^ ERROR `Foo4` is expected to be invariant in `T` but is not + //~| NOTE `Foo4` is covariant in `T` + //~| NOTE required by this attribute val: T, } struct Foo5< + //~^ ERROR `Foo5` is expected to be invariant in `'a` but is not + //~| ERROR `Foo5` is expected to be covariant in `T` but is not #[rustc_assert_variance(invariant)] - //~^ NOTE required by this annotation + //~^ NOTE required by this attribute 'a, - //~^ ERROR `Foo5` is covariant in `'a`; expected variance: invariant + //~^ NOTE `Foo5` is covariant in `'a` #[rustc_assert_variance(covariant)] - //~^ NOTE required by this annotation + //~^ NOTE required by this attribute T, - //~^ ERROR `Foo5` is invariant in `T`; expected variance: covariant + //~^ NOTE `Foo5` is invariant in `T` > { val: &'a mut T, } struct Foo6< + //~^ ERROR `Foo6` is expected to be contravariant in `'a` but is not + //~| ERROR `Foo6` is expected to be contravariant in `T` but is not #[rustc_assert_variance(contravariant)] - //~^ NOTE required by this annotation + //~^ NOTE required by this attribute 'a, - //~^ ERROR `Foo6` is covariant in `'a`; expected variance: contravariant + //~^ NOTE `Foo6` is covariant in `'a` #[rustc_assert_variance(contravariant)] - //~^ NOTE required by this annotation + //~^ NOTE required by this attribute T, - //~^ ERROR `Foo6` is invariant in `T`; expected variance: contravariant + //~^ NOTE `Foo6` is invariant in `T` > { val: &'a mut T, } diff --git a/tests/ui/attributes/rustc_assert_variance.stderr b/tests/ui/attributes/rustc_assert_variance.stderr index 4055c39723673..c41e502e998c7 100644 --- a/tests/ui/attributes/rustc_assert_variance.stderr +++ b/tests/ui/attributes/rustc_assert_variance.stderr @@ -12,74 +12,110 @@ LL | struct Foo2<#[rustc_assert_variance(nonsense)] T> { | | | valid arguments are `covariant`, `invariant`, `contravariant` or `bivariant` -error: `Foo3` is covariant in `T`; expected variance: bivariant - --> $DIR/rustc_assert_variance.rs:16:49 +error: `Foo3` is expected to be bivariant in `T` but is not + --> $DIR/rustc_assert_variance.rs:16:1 | LL | struct Foo3<#[rustc_assert_variance(bivariant)] T> { - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | `Foo3` is covariant in `T` | -note: required by this annotation +note: required by this attribute --> $DIR/rustc_assert_variance.rs:16:13 | LL | struct Foo3<#[rustc_assert_variance(bivariant)] T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `Foo4` is covariant in `T`; expected variance: invariant - --> $DIR/rustc_assert_variance.rs:22:49 +error: `Foo4` is expected to be invariant in `T` but is not + --> $DIR/rustc_assert_variance.rs:23:1 | LL | struct Foo4<#[rustc_assert_variance(invariant)] T> { - | ^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^ + | | + | `Foo4` is covariant in `T` | -note: required by this annotation - --> $DIR/rustc_assert_variance.rs:22:13 +note: required by this attribute + --> $DIR/rustc_assert_variance.rs:23:13 | LL | struct Foo4<#[rustc_assert_variance(invariant)] T> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `Foo5` is covariant in `'a`; expected variance: invariant - --> $DIR/rustc_assert_variance.rs:31:5 - | -LL | 'a, - | ^^ - | -note: required by this annotation - --> $DIR/rustc_assert_variance.rs:29:5 +error: `Foo5` is expected to be invariant in `'a` but is not + --> $DIR/rustc_assert_variance.rs:30:1 + | +LL | / struct Foo5< +LL | | +LL | | +LL | | #[rustc_assert_variance(invariant)] +LL | | +LL | | 'a, + | | -- `Foo5` is covariant in `'a` +... | +LL | | > { + | |_^ + | +note: required by this attribute + --> $DIR/rustc_assert_variance.rs:33:5 | LL | #[rustc_assert_variance(invariant)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `Foo5` is invariant in `T`; expected variance: covariant - --> $DIR/rustc_assert_variance.rs:35:5 - | -LL | T, - | ^ - | -note: required by this annotation - --> $DIR/rustc_assert_variance.rs:33:5 +error: `Foo5` is expected to be covariant in `T` but is not + --> $DIR/rustc_assert_variance.rs:30:1 + | +LL | / struct Foo5< +LL | | +LL | | +LL | | #[rustc_assert_variance(invariant)] +... | +LL | | T, + | | - `Foo5` is invariant in `T` +LL | | +LL | | > { + | |_^ + | +note: required by this attribute + --> $DIR/rustc_assert_variance.rs:37:5 | LL | #[rustc_assert_variance(covariant)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `Foo6` is covariant in `'a`; expected variance: contravariant - --> $DIR/rustc_assert_variance.rs:44:5 - | -LL | 'a, - | ^^ - | -note: required by this annotation - --> $DIR/rustc_assert_variance.rs:42:5 +error: `Foo6` is expected to be contravariant in `'a` but is not + --> $DIR/rustc_assert_variance.rs:45:1 + | +LL | / struct Foo6< +LL | | +LL | | +LL | | #[rustc_assert_variance(contravariant)] +LL | | +LL | | 'a, + | | -- `Foo6` is covariant in `'a` +... | +LL | | > { + | |_^ + | +note: required by this attribute + --> $DIR/rustc_assert_variance.rs:48:5 | LL | #[rustc_assert_variance(contravariant)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: `Foo6` is invariant in `T`; expected variance: contravariant - --> $DIR/rustc_assert_variance.rs:48:5 - | -LL | T, - | ^ - | -note: required by this annotation - --> $DIR/rustc_assert_variance.rs:46:5 +error: `Foo6` is expected to be contravariant in `T` but is not + --> $DIR/rustc_assert_variance.rs:45:1 + | +LL | / struct Foo6< +LL | | +LL | | +LL | | #[rustc_assert_variance(contravariant)] +... | +LL | | T, + | | - `Foo6` is invariant in `T` +LL | | +LL | | > { + | |_^ + | +note: required by this attribute + --> $DIR/rustc_assert_variance.rs:52:5 | LL | #[rustc_assert_variance(contravariant)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 07c2c7c0bd55f15840de6bb81fcb39a7a84c3d16 Mon Sep 17 00:00:00 2001 From: June Pyle Date: Fri, 2 Oct 2026 21:39:21 -0700 Subject: [PATCH 11/16] Annotate std types with rustc_assert_variance: phantom variance marker types, cell types, sync lock and guard types, Arc, Rc, Unique, Box, and NonNull --- library/alloc/src/boxed.rs | 2 +- library/alloc/src/rcs/arc.rs | 2 +- library/alloc/src/rcs/rc.rs | 4 ++-- library/core/src/cell.rs | 8 +++---- .../core/src/cell/covariant_unsafe_cell.rs | 2 +- library/core/src/cell/lazy.rs | 5 ++++- library/core/src/cell/once.rs | 2 +- library/core/src/marker/variance.rs | 20 ++++++++--------- library/core/src/mem/drop_guard.rs | 2 +- library/core/src/ptr/non_null.rs | 2 +- library/std/src/sync/lazy_lock.rs | 2 +- library/std/src/sync/nonpoison/mutex.rs | 12 +++++++--- library/std/src/sync/nonpoison/rwlock.rs | 22 ++++++++++++++----- library/std/src/sync/once_lock.rs | 2 +- library/std/src/sync/poison/mutex.rs | 12 +++++++--- library/std/src/sync/poison/rwlock.rs | 22 ++++++++++++++----- library/std/src/sync/reentrant_lock.rs | 7 ++++-- .../ui/typeck/assign-non-lval-derefmut.stderr | 2 ++ 18 files changed, 87 insertions(+), 43 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index f426345f9fc62..22d6b6027e00a 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -299,7 +299,7 @@ impl From> for NonNull { // The declaration of the `Box` struct must be kept in sync with the // compiler or ICEs will happen. pub struct Box< - T: ?Sized, + #[rustc_assert_variance(covariant)] T: ?Sized, #[stable(feature = "allocator_api", since = "1.100.0")] A: Allocator = Global, >(BoxRaw, A); diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index 8ae3c094b2910..b852891076e29 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -263,7 +263,7 @@ macro_rules! acquire { note = "consider using `Arc::clone`" )] pub struct Arc< - T: ?Sized, + #[rustc_assert_variance(covariant)] T: ?Sized, // FIXME: When stabilizing this parameter, the `AllocatorNightly` // bound on the `From` impl *must* be weaked to `Allocator`, // as `Box` is fundamental! diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 696bd733b992d..26538f2123ffc 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -283,7 +283,7 @@ use crate::vec::Vec; // repr(align(2)) (forcing alignment to at least 2) is required because usize // has 1-byte alignment on AVR. #[repr(C, align(2))] -struct RcInner { +struct RcInner<#[rustc_assert_variance(covariant)] T: ?Sized> { strong: Cell, weak: Cell, value: T, @@ -323,7 +323,7 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { )] pub struct Rc< - T: ?Sized, + #[rustc_assert_variance(covariant)] T: ?Sized, // FIXME: When stabilizing this parameter, the `AllocatorNightly` // bound on the `From` impl *must* be weaked to `Allocator`, // as `Box` is fundamental! diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 3dcf033bbd757..d37f0eaa512a6 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -312,7 +312,7 @@ pub use once::OnceCell; #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct Cell { +pub struct Cell<#[rustc_assert_variance(invariant)] T: ?Sized> { value: UnsafeCell, } @@ -849,7 +849,7 @@ impl Cell { /// See the [module-level documentation](self) for more. #[rustc_diagnostic_item = "RefCell"] #[stable(feature = "rust1", since = "1.0.0")] -pub struct RefCell { +pub struct RefCell<#[rustc_assert_variance(invariant)] T: ?Sized> { borrow: Cell, // Stores the location of the earliest currently active borrow. // This gets updated whenever we go from having zero borrows @@ -2308,7 +2308,7 @@ impl fmt::Display for RefMut<'_, T> { #[stable(feature = "rust1", since = "1.0.0")] #[repr(transparent)] #[rustc_pub_transparent] -pub struct UnsafeCell { +pub struct UnsafeCell<#[rustc_assert_variance(invariant)] T: ?Sized> { value: T, } @@ -2603,7 +2603,7 @@ impl, U> DispatchFromDyn> for UnsafeCell #[repr(transparent)] #[rustc_diagnostic_item = "SyncUnsafeCell"] #[rustc_pub_transparent] -pub struct SyncUnsafeCell { +pub struct SyncUnsafeCell<#[rustc_assert_variance(invariant)] T: ?Sized> { value: UnsafeCell, } diff --git a/library/core/src/cell/covariant_unsafe_cell.rs b/library/core/src/cell/covariant_unsafe_cell.rs index 11ac9b58bbb90..bd38fb303d914 100644 --- a/library/core/src/cell/covariant_unsafe_cell.rs +++ b/library/core/src/cell/covariant_unsafe_cell.rs @@ -17,7 +17,7 @@ use crate::ptr::{self, NonNull}; // hardcode its variance to be **co**variant in `T`, even though it is wrapping `UnsafeCell` which // is **in**variant in `T`. #[lang = "covariant_unsafe_cell"] -pub struct CovariantUnsafeCell(UnsafeCell); +pub struct CovariantUnsafeCell<#[rustc_assert_variance(covariant)] T: ?Sized>(UnsafeCell); #[unstable(feature = "covariant_unsafe_cell", issue = "159735")] impl !Sync for CovariantUnsafeCell {} diff --git a/library/core/src/cell/lazy.rs b/library/core/src/cell/lazy.rs index ba32fff2284fd..fc96376cbe70d 100644 --- a/library/core/src/cell/lazy.rs +++ b/library/core/src/cell/lazy.rs @@ -51,7 +51,10 @@ enum State { /// // 92 /// ``` #[stable(feature = "lazy_cell", since = "1.80.0")] -pub struct LazyCell T> { +pub struct LazyCell< + #[rustc_assert_variance(invariant)] T, + #[rustc_assert_variance(invariant)] F = fn() -> T, +> { state: UnsafeCell>, } diff --git a/library/core/src/cell/once.rs b/library/core/src/cell/once.rs index 01ba604e67949..6df10de2d5aae 100644 --- a/library/core/src/cell/once.rs +++ b/library/core/src/cell/once.rs @@ -32,7 +32,7 @@ use crate::{fmt, mem}; /// assert!(cell.get().is_some()); /// ``` #[stable(feature = "once_cell", since = "1.70.0")] -pub struct OnceCell { +pub struct OnceCell<#[rustc_assert_variance(invariant)] T> { // Invariant: written to at most once. inner: UnsafeCell>, } diff --git a/library/core/src/marker/variance.rs b/library/core/src/marker/variance.rs index 9e135e89c451e..67dcdb5513027 100644 --- a/library/core/src/marker/variance.rs +++ b/library/core/src/marker/variance.rs @@ -16,10 +16,10 @@ macro_rules! first_token { macro_rules! phantom_type { ($( $(#[$attr:meta])* - pub struct $name:ident <$t:ident> ($($inner:tt)*); + pub struct $name:ident <$(#[$param_attr:meta])? $t:ident> ($($inner:tt)*); )*) => {$( $(#[$attr])* - pub struct $name<$t>($($inner)*) where $t: ?Sized; + pub struct $name<$(#[$param_attr])? $t>($($inner)*) where $t: ?Sized; impl $name where T: ?Sized @@ -101,11 +101,11 @@ macro_rules! phantom_type { macro_rules! phantom_lifetime { ($( $(#[$attr:meta])* - pub struct $name:ident <$lt:lifetime> ($($inner:tt)*); + pub struct $name:ident <$(#[$param_attr:meta])? $lt:lifetime> ($($inner:tt)*); )*) => {$( $(#[$attr])* #[derive(Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)] - pub struct $name<$lt>($($inner)*); + pub struct $name<$(#[$param_attr])? $lt>($($inner)*); impl $name<'_> { /// Constructs a new instance of the variance marker. @@ -144,7 +144,7 @@ phantom_lifetime! { /// * `align_of::>() == 1` #[rustc_pub_transparent] #[repr(transparent)] - pub struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>); + pub struct PhantomCovariantLifetime<#[rustc_assert_variance(covariant)] 'a>(PhantomCovariant<&'a ()>); /// Zero-sized type used to mark a lifetime as contravariant. /// /// Contravariant lifetimes must live at most as long as declared. See [the reference][1] for @@ -161,7 +161,7 @@ phantom_lifetime! { /// * `align_of::>() == 1` #[rustc_pub_transparent] #[repr(transparent)] - pub struct PhantomContravariantLifetime<'a>(PhantomContravariant<&'a ()>); + pub struct PhantomContravariantLifetime<#[rustc_assert_variance(contravariant)] 'a>(PhantomContravariant<&'a ()>); /// Zero-sized type used to mark a lifetime as invariant. /// /// Invariant lifetimes must be live for the exact length declared, neither shorter nor longer. @@ -176,7 +176,7 @@ phantom_lifetime! { /// * `align_of::>() == 1` #[rustc_pub_transparent] #[repr(transparent)] - pub struct PhantomInvariantLifetime<'a>(PhantomInvariant<&'a ()>); + pub struct PhantomInvariantLifetime<#[rustc_assert_variance(invariant)] 'a>(PhantomInvariant<&'a ()>); } phantom_type! { @@ -197,7 +197,7 @@ phantom_type! { /// * `align_of::>() == 1` #[rustc_pub_transparent] #[repr(transparent)] - pub struct PhantomCovariant(PhantomData T>); + pub struct PhantomCovariant<#[rustc_assert_variance(covariant)] T>(PhantomData T>); /// Zero-sized type used to mark a type parameter as contravariant. /// /// Types passed as arguments to a function are contravariant. If the type is _also_ part of the @@ -215,7 +215,7 @@ phantom_type! { /// * `align_of::>() == 1` #[rustc_pub_transparent] #[repr(transparent)] - pub struct PhantomContravariant(PhantomData); + pub struct PhantomContravariant<#[rustc_assert_variance(contravariant)] T>(PhantomData); /// Zero-sized type used to mark a type parameter as invariant. /// /// Types that are both passed as an argument _and_ used as part of the return value from a @@ -230,7 +230,7 @@ phantom_type! { /// * `align_of::>() == 1` #[rustc_pub_transparent] #[repr(transparent)] - pub struct PhantomInvariant(PhantomData T>); + pub struct PhantomInvariant<#[rustc_assert_variance(invariant)] T>(PhantomData T>); } mod private_items { diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 81104ccce29f1..d997ab680e354 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -30,7 +30,7 @@ use crate::ops::{Deref, DerefMut}; #[stable(feature = "drop_guard", since = "1.100.0")] #[doc(alias = "ScopeGuard")] #[doc(alias = "defer")] -pub struct DropGuard +pub struct DropGuard<#[rustc_assert_variance(covariant)] T, #[rustc_assert_variance(covariant)] F> where F: FnOnce(T), { diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index dc67d94d6e08e..3cec204fd54cc 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -75,7 +75,7 @@ use crate::{fmt, hash, intrinsics, mem, ptr}; #[repr(transparent)] #[rustc_nonnull_optimization_guaranteed] #[lang = "non_null"] -pub struct NonNull { +pub struct NonNull<#[rustc_assert_variance(covariant)] T: PointeeSized> { pointer: crate::pattern_type!(*const T is !null), } diff --git a/library/std/src/sync/lazy_lock.rs b/library/std/src/sync/lazy_lock.rs index d1e5fd0af66f1..4462e8f7c193a 100644 --- a/library/std/src/sync/lazy_lock.rs +++ b/library/std/src/sync/lazy_lock.rs @@ -78,7 +78,7 @@ union Data { /// } /// ``` #[stable(feature = "lazy_cell", since = "1.80.0")] -pub struct LazyLock T> { +pub struct LazyLock<#[rustc_assert_variance(invariant)] T, F = fn() -> T> { // FIXME(nonpoison_once): if possible, switch to nonpoison version once it is available once: Once, data: UnsafeCell>, diff --git a/library/std/src/sync/nonpoison/mutex.rs b/library/std/src/sync/nonpoison/mutex.rs index a4ba86e38516c..c494234ddb357 100644 --- a/library/std/src/sync/nonpoison/mutex.rs +++ b/library/std/src/sync/nonpoison/mutex.rs @@ -47,7 +47,7 @@ use crate::sys::sync as sys; /// ``` #[unstable(feature = "nonpoison_mutex", issue = "134645")] #[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonMutex")] -pub struct Mutex { +pub struct Mutex<#[rustc_assert_variance(invariant)] T: ?Sized> { inner: sys::Mutex, data: UnsafeCell, } @@ -96,7 +96,10 @@ unsafe impl Sync for Mutex {} #[unstable(feature = "nonpoison_mutex", issue = "134645")] #[clippy::has_significant_drop] #[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonMutexGuard")] -pub struct MutexGuard<'a, T: ?Sized + 'a> { +pub struct MutexGuard< + #[rustc_assert_variance(covariant)] 'a, + #[rustc_assert_variance(invariant)] T: ?Sized + 'a, +> { lock: &'a Mutex, } @@ -138,7 +141,10 @@ unsafe impl Sync for MutexGuard<'_, T> {} #[unstable(feature = "mapped_lock_guards", issue = "117108")] // #[unstable(feature = "nonpoison_mutex", issue = "134645")] #[clippy::has_significant_drop] -pub struct MappedMutexGuard<'a, T: ?Sized + 'a> { +pub struct MappedMutexGuard< + #[rustc_assert_variance(covariant)] 'a, + #[rustc_assert_variance(invariant)] T: ?Sized + 'a, +> { // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a // `MappedMutexGuard` argument doesn't hold uniqueness for its whole scope, only until it drops. // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field diff --git a/library/std/src/sync/nonpoison/rwlock.rs b/library/std/src/sync/nonpoison/rwlock.rs index 19064fdd1ce10..857d7c085b3e4 100644 --- a/library/std/src/sync/nonpoison/rwlock.rs +++ b/library/std/src/sync/nonpoison/rwlock.rs @@ -40,7 +40,7 @@ use crate::sys::sync as sys; /// ``` #[unstable(feature = "nonpoison_rwlock", issue = "134645")] #[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonRwLock")] -pub struct RwLock { +pub struct RwLock<#[rustc_assert_variance(invariant)] T: ?Sized> { /// The inner [`sys::RwLock`] that synchronizes thread access to the protected data. inner: sys::RwLock, /// The lock-protected data. @@ -72,7 +72,10 @@ unsafe impl Sync for RwLock {} #[unstable(feature = "nonpoison_rwlock", issue = "134645")] #[clippy::has_significant_drop] #[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonRwLockReadGuard")] -pub struct RwLockReadGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct RwLockReadGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(covariant)] T: ?Sized + 'rwlock, +> { /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of /// `&'rwlock T` to avoid `noalias` violations, because a `RwLockReadGuard` instance only holds /// immutability until it drops, not for its whole scope. @@ -104,7 +107,10 @@ unsafe impl Sync for RwLockReadGuard<'_, T> {} #[unstable(feature = "nonpoison_rwlock", issue = "134645")] #[clippy::has_significant_drop] #[cfg_attr(not(test), rustc_diagnostic_item = "NonPoisonRwLockWriteGuard")] -pub struct RwLockWriteGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct RwLockWriteGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(invariant)] T: ?Sized + 'rwlock, +> { /// A reference to the [`RwLock`] that we have write-locked. lock: &'rwlock RwLock, } @@ -130,7 +136,10 @@ unsafe impl Sync for RwLockWriteGuard<'_, T> {} #[unstable(feature = "mapped_lock_guards", issue = "117108")] // #[unstable(feature = "nonpoison_rwlock", issue = "134645")] #[clippy::has_significant_drop] -pub struct MappedRwLockReadGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct MappedRwLockReadGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(covariant)] T: ?Sized + 'rwlock, +> { /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of /// `&'rwlock T` to avoid `noalias` violations, because a `MappedRwLockReadGuard` instance only /// holds immutability until it drops, not for its whole scope. @@ -164,7 +173,10 @@ unsafe impl Sync for MappedRwLockReadGuard<'_, T> {} #[unstable(feature = "mapped_lock_guards", issue = "117108")] // #[unstable(feature = "nonpoison_rwlock", issue = "134645")] #[clippy::has_significant_drop] -pub struct MappedRwLockWriteGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct MappedRwLockWriteGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(invariant)] T: ?Sized + 'rwlock, +> { /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of /// `&'rwlock T` to avoid `noalias` violations, because a `MappedRwLockWriteGuard` instance only /// holds uniquneness until it drops, not for its whole scope. diff --git a/library/std/src/sync/once_lock.rs b/library/std/src/sync/once_lock.rs index e8e8f869dd038..3519adab66c4e 100644 --- a/library/std/src/sync/once_lock.rs +++ b/library/std/src/sync/once_lock.rs @@ -106,7 +106,7 @@ use crate::sync::Once; /// /// ``` #[stable(feature = "once_cell", since = "1.70.0")] -pub struct OnceLock { +pub struct OnceLock<#[rustc_assert_variance(invariant)] T> { // FIXME(nonpoison_once): switch to nonpoison version once it is available once: Once, // Whether or not the value is initialized is tracked by `once.is_completed()`. diff --git a/library/std/src/sync/poison/mutex.rs b/library/std/src/sync/poison/mutex.rs index 42c5fcf3e27c0..2bb4af20140cd 100644 --- a/library/std/src/sync/poison/mutex.rs +++ b/library/std/src/sync/poison/mutex.rs @@ -224,7 +224,7 @@ use crate::sys::sync as sys; /// #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "Mutex")] -pub struct Mutex { +pub struct Mutex<#[rustc_assert_variance(invariant)] T: ?Sized> { inner: sys::Mutex, poison: poison::Flag, data: UnsafeCell, @@ -274,7 +274,10 @@ unsafe impl Sync for Mutex {} #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] #[cfg_attr(not(test), rustc_diagnostic_item = "MutexGuard")] -pub struct MutexGuard<'a, T: ?Sized + 'a> { +pub struct MutexGuard< + #[rustc_assert_variance(covariant)] 'a, + #[rustc_assert_variance(invariant)] T: ?Sized + 'a, +> { lock: &'a Mutex, poison: poison::Guard, } @@ -317,7 +320,10 @@ unsafe impl Sync for MutexGuard<'_, T> {} and cause Futures to not implement `Send`"] #[unstable(feature = "mapped_lock_guards", issue = "117108")] #[clippy::has_significant_drop] -pub struct MappedMutexGuard<'a, T: ?Sized + 'a> { +pub struct MappedMutexGuard< + #[rustc_assert_variance(covariant)] 'a, + #[rustc_assert_variance(invariant)] T: ?Sized + 'a, +> { // NB: we use a pointer instead of `&'a mut T` to avoid `noalias` violations, because a // `MappedMutexGuard` argument doesn't hold uniqueness for its whole scope, only until it drops. // `NonNull` is covariant over `T`, so we add a `PhantomData<&'a mut T>` field diff --git a/library/std/src/sync/poison/rwlock.rs b/library/std/src/sync/poison/rwlock.rs index de1fedf88f63a..686ac71d8227b 100644 --- a/library/std/src/sync/poison/rwlock.rs +++ b/library/std/src/sync/poison/rwlock.rs @@ -91,7 +91,7 @@ use crate::sys::sync as sys; /// [`Mutex`]: super::Mutex #[stable(feature = "rust1", since = "1.0.0")] #[cfg_attr(not(test), rustc_diagnostic_item = "RwLock")] -pub struct RwLock { +pub struct RwLock<#[rustc_assert_variance(invariant)] T: ?Sized> { /// The inner [`sys::RwLock`] that synchronizes thread access to the protected data. inner: sys::RwLock, /// A flag denoting if this `RwLock` has been poisoned. @@ -125,7 +125,10 @@ unsafe impl Sync for RwLock {} #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] #[cfg_attr(not(test), rustc_diagnostic_item = "RwLockReadGuard")] -pub struct RwLockReadGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct RwLockReadGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(covariant)] T: ?Sized + 'rwlock, +> { /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of /// `&'rwlock T` to avoid `noalias` violations, because a `RwLockReadGuard` instance only holds /// immutability until it drops, not for its whole scope. @@ -157,7 +160,10 @@ unsafe impl Sync for RwLockReadGuard<'_, T> {} #[stable(feature = "rust1", since = "1.0.0")] #[clippy::has_significant_drop] #[cfg_attr(not(test), rustc_diagnostic_item = "RwLockWriteGuard")] -pub struct RwLockWriteGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct RwLockWriteGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(invariant)] T: ?Sized + 'rwlock, +> { /// A reference to the [`RwLock`] that we have write-locked. lock: &'rwlock RwLock, /// The poison guard. See the [`poison`] module for more information. @@ -184,7 +190,10 @@ unsafe impl Sync for RwLockWriteGuard<'_, T> {} and cause Futures to not implement `Send`"] #[unstable(feature = "mapped_lock_guards", issue = "117108")] #[clippy::has_significant_drop] -pub struct MappedRwLockReadGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct MappedRwLockReadGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(covariant)] T: ?Sized + 'rwlock, +> { /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of /// `&'rwlock T` to avoid `noalias` violations, because a `MappedRwLockReadGuard` instance only /// holds immutability until it drops, not for its whole scope. @@ -215,7 +224,10 @@ unsafe impl Sync for MappedRwLockReadGuard<'_, T> {} and cause Future's to not implement `Send`"] #[unstable(feature = "mapped_lock_guards", issue = "117108")] #[clippy::has_significant_drop] -pub struct MappedRwLockWriteGuard<'rwlock, T: ?Sized + 'rwlock> { +pub struct MappedRwLockWriteGuard< + #[rustc_assert_variance(covariant)] 'rwlock, + #[rustc_assert_variance(invariant)] T: ?Sized + 'rwlock, +> { /// A pointer to the data protected by the `RwLock`. Note that we use a pointer here instead of /// `&'rwlock T` to avoid `noalias` violations, because a `MappedRwLockWriteGuard` instance only /// holds uniquneness until it drops, not for its whole scope. diff --git a/library/std/src/sync/reentrant_lock.rs b/library/std/src/sync/reentrant_lock.rs index faa1bba1f5389..225bb19c7318d 100644 --- a/library/std/src/sync/reentrant_lock.rs +++ b/library/std/src/sync/reentrant_lock.rs @@ -78,7 +78,7 @@ use crate::thread::{ThreadId, current_id}; // we don't need to further synchronize the TID accesses, so they can be regular 64-bit // non-atomic accesses. #[unstable(feature = "reentrant_lock", issue = "121440")] -pub struct ReentrantLock { +pub struct ReentrantLock<#[rustc_assert_variance(covariant)] T: ?Sized> { mutex: sys::Mutex, owner: Tid, lock_count: UnsafeCell, @@ -204,7 +204,10 @@ impl RefUnwindSafe for ReentrantLock {} /// the guarded data. #[must_use = "if unused the ReentrantLock will immediately unlock"] #[unstable(feature = "reentrant_lock", issue = "121440")] -pub struct ReentrantLockGuard<'a, T: ?Sized + 'a> { +pub struct ReentrantLockGuard< + #[rustc_assert_variance(covariant)] 'a, + #[rustc_assert_variance(covariant)] T: ?Sized + 'a, +> { lock: &'a ReentrantLock, } diff --git a/tests/ui/typeck/assign-non-lval-derefmut.stderr b/tests/ui/typeck/assign-non-lval-derefmut.stderr index a0ba0eae1e443..a6015ec16447b 100644 --- a/tests/ui/typeck/assign-non-lval-derefmut.stderr +++ b/tests/ui/typeck/assign-non-lval-derefmut.stderr @@ -21,6 +21,7 @@ LL | x.lock().unwrap() += 1; | note: `std::sync::MutexGuard<'_, usize>` does not implement `AddAssign<{integer}>` --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL + ::: $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL | = note: `std::sync::MutexGuard<'_, usize>` is defined in another crate help: `+=` can be used on `usize` if you dereference the left-hand side @@ -53,6 +54,7 @@ LL | y += 1; | note: `std::sync::MutexGuard<'_, usize>` does not implement `AddAssign<{integer}>` --> $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL + ::: $SRC_DIR/std/src/sync/poison/mutex.rs:LL:COL | = note: `std::sync::MutexGuard<'_, usize>` is defined in another crate help: `+=` can be used on `usize` if you dereference the left-hand side From b138c7b3a533970f6a7a243ba4bd0f407d657ba1 Mon Sep 17 00:00:00 2001 From: June Pyle Date: Sat, 3 Oct 2026 10:40:01 -0700 Subject: [PATCH 12/16] Add positive test case for a bivariant lifetime parameter in tests/ui/attributes/rustc_assert_variance.rs --- tests/ui/attributes/rustc_assert_variance.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/tests/ui/attributes/rustc_assert_variance.rs b/tests/ui/attributes/rustc_assert_variance.rs index 648fe6499df73..cad6cd528de15 100644 --- a/tests/ui/attributes/rustc_assert_variance.rs +++ b/tests/ui/attributes/rustc_assert_variance.rs @@ -80,4 +80,11 @@ where val: T, } +struct Bar6<#[rustc_assert_variance(bivariant)] 'a, #[rustc_assert_variance(covariant)] T> +where + T: Iterator, +{ + val: T, +} + fn main() {} From 46395c59f91f799980c6d1a04e6ae7eb5ffd91bb Mon Sep 17 00:00:00 2001 From: danieljhkim Date: Sun, 11 Oct 2026 23:36:12 -0700 Subject: [PATCH 13/16] bootstrap: add an rpath to LLVM library for LLVM tools Extract the rpath logic shared by `Llvm`, `Lld` and `OmpOffload` into `llvm_lib_rpath`. --- src/bootstrap/download-ci-llvm-stamp | 2 +- src/bootstrap/src/core/build_steps/llvm.rs | 58 +++++++++++++--------- 2 files changed, 35 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/download-ci-llvm-stamp b/src/bootstrap/download-ci-llvm-stamp index 58691539edfa3..325719ec7d347 100644 --- a/src/bootstrap/download-ci-llvm-stamp +++ b/src/bootstrap/download-ci-llvm-stamp @@ -1,4 +1,4 @@ Change this file to make users of the `download-ci-llvm` configuration download a new version of LLVM from CI, even if the LLVM submodule hasn’t changed. -Last change is for: https://github.com/rust-lang/rust/pull/163954 +Last change is for: https://github.com/rust-lang/rust/pull/164134 diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 8885a7bd89afb..01b7edafc5a65 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -566,6 +566,16 @@ impl CommandLineStep for Llvm { // Keep the pre-LLVM23 behavior for now. cfg.define("LLVM_VERSIONED_DYLIB_NAME_ON_DARWIN", "OFF"); + if link_shared { + // We inform LLVM tools where they can find the LLVM library + // by adding an rpath entry to the expected parent `lib` directory, + // e.g. `rust-objcopy` is shipped in `lib/rustlib//bin`. + if let Some(rpath) = llvm_lib_rpath(builder, target) { + ldflags.exe.push(" "); + ldflags.exe.push(rpath); + } + } + if (target.starts_with("csky") || target.starts_with("riscv") || target.starts_with("sparc-")) @@ -1162,6 +1172,23 @@ fn get_var(var_base: &str, host: &str, target: &str) -> Option { .or_else(|| env::var_os(var_base)) } +/// Generate a RPATH entry for a binary that will link to LLVM (libLLVM.so) dynamically. +/// This will make it possible to execute the binary outside Rustup, so that it can still find the libLLVM.so file. +fn llvm_lib_rpath(builder: &Builder<'_>, target: TargetSelection) -> Option<&'static str> { + if builder.config.rpath_enabled(target) && helpers::use_host_linker(target) { + // Be careful when changing this path, we need to ensure it's quoted or escaped: + // `$ORIGIN` would otherwise be expanded when the `LdFlags` are passed verbatim to + // cmake. + if target.contains("linux") { + return Some("-Wl,-rpath,'$ORIGIN/../../../'"); + } + if target.contains("apple-darwin") { + return Some("-Wl,-rpath,'@loader_path/../../../'"); + } + } + None +} + #[derive(Clone)] pub struct BuiltRustOffload { /// Path to the rust offload dylib @@ -1436,19 +1463,12 @@ impl CommandLineStep for OmpOffload { ldflags.push_all(format!("-L{}", dir.display())); } - if builder.config.rpath_enabled(target) - && helpers::use_host_linker(target) - && llvm_output.link_shared() - && target.contains("linux") - { - // Same logic as in Lld::run + if llvm_output.link_shared() { // We inform libomptarget.so where it can find LLVM's libraries // by adding an rpath entry to the expected parent `lib` directory. - // - // Be careful when changing this path, we need to ensure it's quoted or escaped: - // `$ORIGIN` would otherwise be expanded when the `LdFlags` are passed verbatim to - // cmake. - ldflags.push_all("-Wl,-rpath,'$ORIGIN/../../../'"); + if let Some(rpath) = llvm_lib_rpath(builder, target) { + ldflags.push_all(rpath); + } } configure_cmake(builder, target, &mut cfg, true, ldflags, cflags, &[]); @@ -1724,21 +1744,11 @@ impl CommandLineStep for Lld { // component installed, one can successfully invoke `rust-lld` directly without rustup's // `LD_LIBRARY_PATH` overrides) // - if builder.config.rpath_enabled(target) - && helpers::use_host_linker(target) - && llvm_output.link_shared() - { + if llvm_output.link_shared() { // So we inform LLD where it can find LLVM's libraries by adding an rpath entry to the // expected parent `lib` directory. - // - // Be careful when changing this path, we need to ensure it's quoted or escaped: - // `$ORIGIN` would otherwise be expanded when the `LdFlags` are passed verbatim to - // cmake. - if target.contains("linux") { - ldflags.push_all("-Wl,-rpath,'$ORIGIN/../../../'"); - } - if target.contains("apple-darwin") { - ldflags.push_all("-Wl,-rpath,'@loader_path/../../../'"); + if let Some(rpath) = llvm_lib_rpath(builder, target) { + ldflags.push_all(rpath); } } From d0fa9667ee1dbaf865f4efc8050707030e142cdf Mon Sep 17 00:00:00 2001 From: Aelin Reidel Date: Mon, 12 Oct 2026 19:00:00 +0200 Subject: [PATCH 14/16] Add the link to the musl website --- tests/run-make/dynamic-loading-cdylib/rmake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-make/dynamic-loading-cdylib/rmake.rs b/tests/run-make/dynamic-loading-cdylib/rmake.rs index 59c1135b08bad..975722da75d6b 100644 --- a/tests/run-make/dynamic-loading-cdylib/rmake.rs +++ b/tests/run-make/dynamic-loading-cdylib/rmake.rs @@ -7,6 +7,7 @@ // // This test is ignored on musl hosts because musl's dlclose is a no-op and // therefore destructors won't run when the library is unloaded. +// See https://wiki.musl-libc.org/functional-differences-from-glibc.html#Unloading-libraries //@ ignore-cross-compile //@ ignore-musl From 1f3611e180568df31c7c466f6ea4f49c6354792c Mon Sep 17 00:00:00 2001 From: Abhinav Srivastav Date: Mon, 12 Oct 2026 23:42:03 +0530 Subject: [PATCH 15/16] tests: cover dead_code_pub_in_binary expectations with --test --- .../dead-code-pub-in-binary/binary-normal.rs | 9 ++++++++ .../dead-code-pub-in-binary/binary-test.rs | 7 ++++++ .../dead-code-pub-in-binary/library-normal.rs | 6 +++++ .../library-normal.stderr | 23 +++++++++++++++++++ .../dead-code-pub-in-binary/library-test.rs | 9 ++++++++ .../test-no-crate-type.rs | 7 ++++++ 6 files changed, 61 insertions(+) create mode 100644 tests/ui/lint/dead-code-pub-in-binary/binary-normal.rs create mode 100644 tests/ui/lint/dead-code-pub-in-binary/binary-test.rs create mode 100644 tests/ui/lint/dead-code-pub-in-binary/library-normal.rs create mode 100644 tests/ui/lint/dead-code-pub-in-binary/library-normal.stderr create mode 100644 tests/ui/lint/dead-code-pub-in-binary/library-test.rs create mode 100644 tests/ui/lint/dead-code-pub-in-binary/test-no-crate-type.rs diff --git a/tests/ui/lint/dead-code-pub-in-binary/binary-normal.rs b/tests/ui/lint/dead-code-pub-in-binary/binary-normal.rs new file mode 100644 index 0000000000000..a3a66717d8d16 --- /dev/null +++ b/tests/ui/lint/dead-code-pub-in-binary/binary-normal.rs @@ -0,0 +1,9 @@ +//@ check-pass + +#![crate_type = "bin"] +#![expect(dead_code_pub_in_binary)] +#![deny(unfulfilled_lint_expectations)] + +pub fn unused_pub_fn() {} + +fn main() {} diff --git a/tests/ui/lint/dead-code-pub-in-binary/binary-test.rs b/tests/ui/lint/dead-code-pub-in-binary/binary-test.rs new file mode 100644 index 0000000000000..7a039ab50d88e --- /dev/null +++ b/tests/ui/lint/dead-code-pub-in-binary/binary-test.rs @@ -0,0 +1,7 @@ +//@ check-pass +//@ compile-flags: --test --crate-type=bin + +#![expect(dead_code_pub_in_binary)] +#![deny(unfulfilled_lint_expectations)] + +pub fn unused_pub_fn() {} diff --git a/tests/ui/lint/dead-code-pub-in-binary/library-normal.rs b/tests/ui/lint/dead-code-pub-in-binary/library-normal.rs new file mode 100644 index 0000000000000..179546182feb8 --- /dev/null +++ b/tests/ui/lint/dead-code-pub-in-binary/library-normal.rs @@ -0,0 +1,6 @@ +#![crate_type = "lib"] +#![expect(dead_code_pub_in_binary)] //~ ERROR this lint expectation is unfulfilled +#![deny(unfulfilled_lint_expectations)] +//~^^ WARN unused attribute + +pub fn unused_pub_fn() {} diff --git a/tests/ui/lint/dead-code-pub-in-binary/library-normal.stderr b/tests/ui/lint/dead-code-pub-in-binary/library-normal.stderr new file mode 100644 index 0000000000000..4c5a0134d2502 --- /dev/null +++ b/tests/ui/lint/dead-code-pub-in-binary/library-normal.stderr @@ -0,0 +1,23 @@ +warning: unused attribute + --> $DIR/library-normal.rs:2:1 + | +LL | #![expect(dead_code_pub_in_binary)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute + | + = note: the `dead_code_pub_in_binary` lint has no effect in library crates + = note: requested on the command line with `-W unused-attributes` + +error: this lint expectation is unfulfilled + --> $DIR/library-normal.rs:2:11 + | +LL | #![expect(dead_code_pub_in_binary)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/library-normal.rs:3:9 + | +LL | #![deny(unfulfilled_lint_expectations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + diff --git a/tests/ui/lint/dead-code-pub-in-binary/library-test.rs b/tests/ui/lint/dead-code-pub-in-binary/library-test.rs new file mode 100644 index 0000000000000..3a4383c4b979a --- /dev/null +++ b/tests/ui/lint/dead-code-pub-in-binary/library-test.rs @@ -0,0 +1,9 @@ +//@ check-pass +//@ compile-flags: --test --crate-type=lib + +#![expect(dead_code_pub_in_binary)] +#![deny(unfulfilled_lint_expectations)] + +// FIXME(#159078): `--test` causes the library crate to be treated as an +// executable, fulfilling this lint expectation incorrectly. +pub fn unused_pub_fn() {} diff --git a/tests/ui/lint/dead-code-pub-in-binary/test-no-crate-type.rs b/tests/ui/lint/dead-code-pub-in-binary/test-no-crate-type.rs new file mode 100644 index 0000000000000..ba828339f093d --- /dev/null +++ b/tests/ui/lint/dead-code-pub-in-binary/test-no-crate-type.rs @@ -0,0 +1,7 @@ +//@ check-pass +//@ compile-flags: --test + +#![expect(dead_code_pub_in_binary)] +#![deny(unfulfilled_lint_expectations)] + +pub fn unused_pub_fn() {} From 2b90a47296c3a909afe7c725749c409cd3747d99 Mon Sep 17 00:00:00 2001 From: Abhinav Srivastav Date: Mon, 5 Oct 2026 04:58:08 +0530 Subject: [PATCH 16/16] fix delegation generic parameter remapping ICEs --- compiler/rustc_hir_analysis/src/delegation.rs | 144 +++++++++++++----- .../rustc_hir_analysis/src/diagnostics.rs | 10 ++ ...t-param-trait-name-collision-ice-163868.rs | 18 +++ ...ram-trait-name-collision-ice-163868.stderr | 40 +++++ ...st-param-type-name-collision-ice-162776.rs | 16 ++ ...aram-type-name-collision-ice-162776.stderr | 63 ++++++++ 6 files changed, 254 insertions(+), 37 deletions(-) create mode 100644 tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.rs create mode 100644 tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.stderr create mode 100644 tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.rs create mode 100644 tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.stderr diff --git a/compiler/rustc_hir_analysis/src/delegation.rs b/compiler/rustc_hir_analysis/src/delegation.rs index 2ffd335fb67b9..56aa2334d939a 100644 --- a/compiler/rustc_hir_analysis/src/delegation.rs +++ b/compiler/rustc_hir_analysis/src/delegation.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{DelegationSelfTyPropagationKind, PathSegment}; use rustc_middle::ty::{ self, ConstKind, EarlyBinder, GenericArg, GenericArgKind, RegionKind, Ty, TyCtxt, TypeFoldable, - TypeFolder, TypeSuperFoldable, TypeVisitableExt, + TypeFolder, TypeSuperFoldable, TypeVisitableExt, Upcast, }; use rustc_span::{ErrorGuaranteed, Span, kw}; @@ -23,46 +23,65 @@ struct ParamIndexRemapper<'tcx> { tcx: TyCtxt<'tcx>, remap_table: RemapTable, delegation_parent_consts: FxHashSet, + arg_kinds: Vec>, } -impl<'tcx> TypeFolder> for ParamIndexRemapper<'tcx> { +impl<'tcx> ParamIndexRemapper<'tcx> { + fn try_remap( + &self, + source_index: u32, + expected_kind: ty::GenericArgKind<'tcx>, + ) -> Result { + self.remap_table + .get(&source_index) + .copied() + .filter(|&idx| { + self.arg_kinds.get(idx as usize).is_some_and(|kind| { + std::mem::discriminant(&expected_kind) == std::mem::discriminant(kind) + }) + }) + .ok_or(()) + } +} + +impl<'tcx> ty::FallibleTypeFolder> for ParamIndexRemapper<'tcx> { + type Error = (); + fn cx(&self) -> TyCtxt<'tcx> { self.tcx } - fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> { + fn try_fold_ty(&mut self, ty: Ty<'tcx>) -> Result, Self::Error> { if !ty.has_param() { - return ty; + return Ok(ty); } - if let ty::Param(param) = ty.kind() - && let Some(index) = self.remap_table.get(¶m.index) - { - return Ty::new_param(self.tcx, *index, param.name); + if let ty::Param(param) = ty.kind() { + let index = self.try_remap(param.index, ty::GenericArgKind::Type(ty))?; + return Ok(Ty::new_param(self.tcx, index, param.name)); } - ty.super_fold_with(self) + + ty.try_super_fold_with(self) } - fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> { - if let ty::ReEarlyParam(param) = r.kind() - && let Some(index) = self.remap_table.get(¶m.index).copied() - { - return ty::Region::new_early_param( + fn try_fold_region(&mut self, r: ty::Region<'tcx>) -> Result, Self::Error> { + if let ty::ReEarlyParam(param) = r.kind() { + let index = self.try_remap(param.index, ty::GenericArgKind::Lifetime(r))?; + return Ok(ty::Region::new_early_param( self.tcx, ty::EarlyParamRegion { index, name: param.name }, - ); + )); } - r + Ok(r) } - fn fold_const(&mut self, ct: ty::Const<'tcx>) -> ty::Const<'tcx> { - if let ty::ConstKind::Param(param) = ct.kind() - && let Some(idx) = self.remap_table.get(¶m.index) - { - let param = ty::ParamConst::new(*idx, param.name); - return ty::Const::new_param(self.tcx, param); + fn try_fold_const(&mut self, ct: ty::Const<'tcx>) -> Result, Self::Error> { + if let ty::ConstKind::Param(param) = ct.kind() { + let idx = self.try_remap(param.index, ty::GenericArgKind::Const(ct))?; + let param = ty::ParamConst::new(idx, param.name); + return Ok(ty::Const::new_param(self.tcx, param)); } - ct.super_fold_with(self) + ct.try_super_fold_with(self) } } @@ -479,7 +498,7 @@ pub(crate) fn inherit_clauses_for_delegation_item<'tcx>( mut self, f: impl Fn(DefId) -> ty::GenericClauses<'tcx>, def_id: DefId, - ) -> Self { + ) -> Result { let clauses = f(def_id); let args = self.args.as_slice(); @@ -521,8 +540,9 @@ pub(crate) fn inherit_clauses_for_delegation_item<'tcx>( // it came from delegation parent, and if so we do not process its `ConstArgHasType` // clause. // (Issue #158675). + let new_clause = clause.0.try_fold_with(&mut self.folder)?; if let ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(ct, _)) = - clause.0.as_predicate().fold_with(&mut self.folder).kind().skip_binder() + new_clause.as_predicate().kind().skip_binder() { let unnorm_const = EarlyBinder::bind(self.tcx, ct).instantiate(self.tcx, args); if let ty::ConstKind::Param(param) = unnorm_const.skip_norm_wip().kind() @@ -532,7 +552,6 @@ pub(crate) fn inherit_clauses_for_delegation_item<'tcx>( } } - let new_clause = clause.0.fold_with(&mut self.folder); self.clauses.push(( EarlyBinder::bind(self.tcx, new_clause) .instantiate(self.tcx, args) @@ -541,17 +560,17 @@ pub(crate) fn inherit_clauses_for_delegation_item<'tcx>( )); } - self + Ok(self) } fn with_clauses( mut self, f: impl Fn(DefId) -> ty::GenericClauses<'tcx> + Copy, def_id: DefId, - ) -> Self { + ) -> Result { let preds = f(def_id); if let Some(parent_def_id) = preds.parent { - self = self.with_own_clauses(f, parent_def_id); + self = self.with_own_clauses(f, parent_def_id)?; } self.with_own_clauses(f, def_id) @@ -572,7 +591,7 @@ pub(crate) fn inherit_clauses_for_delegation_item<'tcx>( // `explicit_clauses_of` is used here to avoid copying `Self: Trait` clause. // Note: `clauses_of` query can also add inferred outlives clauses, but that // is not the case here as `sig_id` is either a trait or a function. - let clauses = match inh_kind { + let collector = match inh_kind { InheritanceKind::WithParent(false) => { collector.with_clauses(|def_id| tcx.explicit_clauses_of(def_id), sig_id) } @@ -580,8 +599,39 @@ pub(crate) fn inherit_clauses_for_delegation_item<'tcx>( collector.with_clauses(|def_id| tcx.clauses_of(def_id), sig_id) } InheritanceKind::Own => collector.with_own_clauses(|def_id| tcx.clauses_of(def_id), sig_id), - } - .clauses; + }; + + let clauses = match collector { + Ok(collector) => collector.clauses, + Err(()) => { + tcx.dcx().emit_err(crate::diagnostics::DelegationInheritanceFailed { + span: tcx.def_span(def_id), + kind: "predicates", + callee_span: tcx.def_span(sig_id), + }); + + // Even on error, the delegated item's const parameters need their + // types in the parameter environment. + tcx.generics_of(def_id) + .own_params + .iter() + .filter_map(|param| { + if !matches!(param.kind, ty::GenericParamDefKind::Const { .. }) { + return None; + } + + let ct = + ty::Const::new_param(tcx, ty::ParamConst::new(param.index, param.name)); + let ct_ty = tcx.type_of(param.def_id).instantiate_identity().skip_norm_wip(); + + Some(( + ty::ClauseKind::ConstArgHasType(ct, ct_ty).upcast(tcx), + tcx.def_span(param.def_id), + )) + }) + .collect::>() + } + }; ty::GenericClauses { parent, clauses: tcx.arena.alloc_from_iter(clauses) } } @@ -607,7 +657,8 @@ fn create_folder_and_args<'tcx>( }) .collect(); - (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts }, args) + let arg_kinds = args.iter().map(|arg| arg.kind()).collect(); + (ParamIndexRemapper { tcx, remap_table, delegation_parent_consts, arg_kinds }, args) } fn check_constraints<'tcx>( @@ -633,6 +684,16 @@ fn check_constraints<'tcx>( ret } +fn error_sig_for_delegation<'tcx>( + tcx: TyCtxt<'tcx>, + sig_id: DefId, + err: ErrorGuaranteed, +) -> &'tcx [Ty<'tcx>] { + let sig_len = tcx.fn_sig(sig_id).instantiate_identity().skip_binder().inputs().len() + 1; + let err_type = Ty::new_error(tcx, err); + tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type)) +} + pub(crate) fn inherit_sig_for_delegation_item<'tcx>( tcx: TyCtxt<'tcx>, def_id: LocalDefId, @@ -640,14 +701,23 @@ pub(crate) fn inherit_sig_for_delegation_item<'tcx>( let sig_id = tcx.hir_opt_delegation_sig_id(def_id).expect("Delegation must have sig_id"); let caller_sig = tcx.fn_sig(sig_id); if let Err(err) = check_constraints(tcx, def_id, sig_id) { - let sig_len = caller_sig.instantiate_identity().skip_binder().inputs().len() + 1; - let err_type = Ty::new_error(tcx, err); - return tcx.arena.alloc_from_iter((0..sig_len).map(|_| err_type)); + return error_sig_for_delegation(tcx, sig_id, err); } let (parent_args, child_args) = tcx.delegation_user_specified_args(def_id); let (mut folder, args) = create_folder_and_args(tcx, def_id, sig_id, parent_args, child_args); - let caller_sig = EarlyBinder::bind(tcx, caller_sig.skip_binder().fold_with(&mut folder)); + let folded_sig = match caller_sig.skip_binder().try_fold_with(&mut folder) { + Ok(sig) => sig, + Err(()) => { + let err = tcx.dcx().emit_err(crate::diagnostics::DelegationInheritanceFailed { + span: tcx.def_span(def_id), + kind: "signature", + callee_span: tcx.def_span(sig_id), + }); + return error_sig_for_delegation(tcx, sig_id, err); + } + }; + let caller_sig = EarlyBinder::bind(tcx, folded_sig); let sig = caller_sig.instantiate(tcx, args.as_slice()).skip_binder(); let output = std::iter::once(sig.output()); diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index b003a358f9589..d23e9376bfc93 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -1706,6 +1706,16 @@ pub(crate) struct OnlyCurrentTraitsPointerSugg<'a> { pub ptr_ty: Ty<'a>, } +#[derive(Diagnostic)] +#[diag("failed to inherit delegation {$kind}")] +pub(crate) struct DelegationInheritanceFailed { + #[primary_span] + pub span: Span, + pub kind: &'static str, + #[label("callee defined here")] + pub callee_span: Span, +} + #[derive(Diagnostic)] #[diag("{$descr}")] pub(crate) struct UnsupportedDelegation<'a> { diff --git a/tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.rs b/tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.rs new file mode 100644 index 0000000000000..a53038ad2178f --- /dev/null +++ b/tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.rs @@ -0,0 +1,18 @@ +#![feature(fn_delegation)] + +trait C {} + +struct S; + +impl S { + //~^ ERROR type provided when a constant was expected + fn foo_self(self) {} +} + +trait Trait { + reuse S::<1>::foo_self::<_> as foo_self_4; + //~^ ERROR failed to inherit delegation predicates + //~| ERROR the size for values of type `T` cannot be known +} + +fn main() {} diff --git a/tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.stderr b/tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.stderr new file mode 100644 index 0000000000000..b13a63aab323f --- /dev/null +++ b/tests/ui/delegation/generics/const-param-trait-name-collision-ice-163868.stderr @@ -0,0 +1,40 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/const-param-trait-name-collision-ice-163868.rs:7:24 + | +LL | impl S { + | ^ + +error: failed to inherit delegation predicates + --> $DIR/const-param-trait-name-collision-ice-163868.rs:13:19 + | +LL | fn foo_self(self) {} + | -------------------- callee defined here +... +LL | reuse S::<1>::foo_self::<_> as foo_self_4; + | ^^^^^^^^ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/const-param-trait-name-collision-ice-163868.rs:13:19 + | +LL | reuse S::<1>::foo_self::<_> as foo_self_4; + | ^^^^^^^^ + | | + | doesn't have a size known at compile-time + | this type parameter needs to be `Sized` + | +note: required by an implicit `Sized` bound in `S::<{const error}>::foo_self` + --> $DIR/const-param-trait-name-collision-ice-163868.rs:9:17 + | +LL | impl S { +LL | +LL | fn foo_self(self) {} + | ^ required by the implicit `Sized` requirement on this type parameter in `S::<{const error}>::foo_self` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn foo_self(self) {} + | ++++++++ + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0277, E0747. +For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.rs b/tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.rs new file mode 100644 index 0000000000000..0398a184c0cfe --- /dev/null +++ b/tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.rs @@ -0,0 +1,16 @@ +#![feature(fn_delegation)] + +struct S; +//~^ ERROR: type parameter `A` is never used + +impl<'b, 'c, C, const C: usize> S { +//~^ ERROR: the name `C` is already used for a generic parameter in this item's generic parameters +//~| ERROR: type provided when a constant was expected + fn foo_self() {} +} + +reuse S::<(), 123>::foo_self; +//~^ ERROR: failed to inherit delegation predicates +//~| ERROR: the size for values of type `T` cannot be known at compilation time + +fn main() {} diff --git a/tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.stderr b/tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.stderr new file mode 100644 index 0000000000000..b8f423543a14d --- /dev/null +++ b/tests/ui/delegation/generics/const-param-type-name-collision-ice-162776.stderr @@ -0,0 +1,63 @@ +error[E0403]: the name `C` is already used for a generic parameter in this item's generic parameters + --> $DIR/const-param-type-name-collision-ice-162776.rs:6:23 + | +LL | impl<'b, 'c, C, const C: usize> S { + | - ^ already used + | | + | first use of `C` + +error[E0747]: type provided when a constant was expected + --> $DIR/const-param-type-name-collision-ice-162776.rs:6:38 + | +LL | impl<'b, 'c, C, const C: usize> S { + | ^ + | +help: consider changing this type parameter to a const parameter + | +LL - impl<'b, 'c, C, const C: usize> S { +LL + impl<'b, 'c, const C: usize, const C: usize> S { + | + +error[E0392]: type parameter `A` is never used + --> $DIR/const-param-type-name-collision-ice-162776.rs:3:10 + | +LL | struct S; + | ^ unused type parameter + | + = help: consider removing `A`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `A` to be a const parameter, use `const A: /* Type */` instead + +error: failed to inherit delegation predicates + --> $DIR/const-param-type-name-collision-ice-162776.rs:12:21 + | +LL | fn foo_self() {} + | ------------------------------- callee defined here +... +LL | reuse S::<(), 123>::foo_self; + | ^^^^^^^^ + +error[E0277]: the size for values of type `T` cannot be known at compilation time + --> $DIR/const-param-type-name-collision-ice-162776.rs:12:21 + | +LL | reuse S::<(), 123>::foo_self; + | ^^^^^^^^ + | | + | doesn't have a size known at compile-time + | this type parameter needs to be `Sized` + | +note: required by an implicit `Sized` bound in `S::::foo_self` + --> $DIR/const-param-type-name-collision-ice-162776.rs:9:17 + | +LL | impl<'b, 'c, C, const C: usize> S { +... +LL | fn foo_self() {} + | ^ required by the implicit `Sized` requirement on this type parameter in `S::::foo_self` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn foo_self() {} + | ++++++++ + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0277, E0392, E0403, E0747. +For more information about an error, try `rustc --explain E0277`.