diff options
author | Michael Goulet <michael@errs.io> | 2023-05-08 09:30:21 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-05-08 09:30:21 -0700 |
commit | 29ac429c9bd5f6aa5af8d2c04f3ef8732cd8bd15 (patch) | |
tree | fb9a55891b26a4ce71e471cadc3a964959724ecf /tests | |
parent | fcb275f85e0e64bf3bb488cbd518bb085040c0cf (diff) | |
parent | cd6dec33c2b484fbcb672cb1f80b68b602c1a6f1 (diff) | |
download | rust-29ac429c9bd5f6aa5af8d2c04f3ef8732cd8bd15.tar.gz |
Rollup merge of #109410 - fmease:iat-alias-kind-inherent, r=compiler-errors
Introduce `AliasKind::Inherent` for inherent associated types
Allows us to check (possibly generic) inherent associated types for well-formedness.
Type inference now also works properly.
Follow-up to #105961. Supersedes #108430.
Fixes #106722.
Fixes #108957.
Fixes #109768.
Fixes #109789.
Fixes #109790.
~Not to be merged before #108860 (`AliasKind::Weak`).~
CC `@jackh726`
r? `@compiler-errors`
`@rustbot` label T-types F-inherent_associated_types
Diffstat (limited to 'tests')
42 files changed, 762 insertions, 67 deletions
diff --git a/tests/rustdoc/inherent-projections.rs b/tests/rustdoc/inherent-projections.rs new file mode 100644 index 00000000000..9bda0acaf83 --- /dev/null +++ b/tests/rustdoc/inherent-projections.rs @@ -0,0 +1,44 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// @has 'inherent_projections/fn.create.html' +// @has - '//pre[@class="rust item-decl"]' "create() -> Owner::Metadata" +// @has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Owner.html#associatedtype.Metadata' +pub fn create() -> Owner::Metadata {} + +pub struct Owner; + +impl Owner { + pub type Metadata = (); +} + +// Make sure we handle bound vars correctly. +// @has 'inherent_projections/type.User.html' '//pre[@class="rust item-decl"]' "for<'a> fn(_: Carrier<'a>::Focus)" +pub type User = for<'a> fn(Carrier<'a>::Focus); + +pub struct Carrier<'a>(&'a ()); + +impl<'a> Carrier<'a> { + pub type Focus = &'a mut i32; +} + +//////////////////////////////////////// + +// FIXME(inherent_associated_types): Below we link to `Proj` but we should link to `Proj-1`. +// The current test checks for the buggy behavior for demonstration purposes. + +// @has 'inherent_projections/type.Test.html' +// @has - '//pre[@class="rust item-decl"]' "Parametrized<i32>" +// @has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj' +// @!has - '//pre[@class="rust item-decl"]//a[@class="associatedtype"]/@href' 'struct.Parametrized.html#associatedtype.Proj-1' +pub type Test = Parametrized<i32>::Proj; + +pub struct Parametrized<T>(T); + +impl Parametrized<bool> { + pub type Proj = (); +} + +impl Parametrized<i32> { + pub type Proj = String; +} diff --git a/tests/rustdoc/intra-doc/inherent-associated-types.rs b/tests/rustdoc/intra-doc/inherent-associated-types.rs new file mode 100644 index 00000000000..2b28d2ae60b --- /dev/null +++ b/tests/rustdoc/intra-doc/inherent-associated-types.rs @@ -0,0 +1,45 @@ +#![feature(inherent_associated_types)] + +#![allow(incomplete_features)] +#![deny(rustdoc::broken_intra_doc_links)] + +// @has inherent_associated_types/index.html + +// @has - '//a/@href' 'enum.Simple.html#associatedtype.Type' +//! [`Simple::Type`] + +pub enum Simple {} + +impl Simple { + pub type Type = (); +} + +//////////////////////////////////////// + +// @has 'inherent_associated_types/type.Test0.html' '//a/@href' \ +// 'struct.Parametrized.html#associatedtype.Proj' +/// [`Parametrized<bool>::Proj`] +pub type Test0 = (); + +// FIXME(inherent_associated_types): The intra-doc link below should point to `Proj-1` not `Proj`. +// The current test checks for the buggy behavior for demonstration purposes. +// The same bug happens for inherent associated functions and constants (see #85960, #93398). +// +// Further, at some point we should reject the intra-doc link `Parametrized::Proj`. +// It currently links to `Parametrized<bool>::Proj`. + +// @has 'inherent_associated_types/type.Test1.html' +// @has - '//a/@href' 'struct.Parametrized.html#associatedtype.Proj' +// @!has - '//a/@href' 'struct.Parametrized.html#associatedtype.Proj-1' +/// [`Parametrized<i32>::Proj`] +pub type Test1 = (); + +pub struct Parametrized<T>(T); + +impl Parametrized<bool> { + pub type Proj = (); +} + +impl Parametrized<i32> { + pub type Proj = String; +} diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.rs b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.rs new file mode 100644 index 00000000000..f41574403d8 --- /dev/null +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.rs @@ -0,0 +1,10 @@ +// known-bug: #108491 + +// FIXME(inherent_associated_types): This should pass. + +struct Foo { + bar: Self::Bar, +} +impl Foo { + pub type Bar = usize; +} diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr new file mode 100644 index 00000000000..f313c494671 --- /dev/null +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-adt.stderr @@ -0,0 +1,49 @@ +error[E0601]: `main` function not found in crate `cycle_iat_inside_of_adt` + --> $DIR/cycle-iat-inside-of-adt.rs:10:2 + | +LL | } + | ^ consider adding a `main` function to `$DIR/cycle-iat-inside-of-adt.rs` + +error[E0391]: cycle detected when computing predicates of `Foo` + --> $DIR/cycle-iat-inside-of-adt.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^ + | +note: ...which requires computing predicates of `Foo`... + --> $DIR/cycle-iat-inside-of-adt.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^ +note: ...which requires computing inferred outlives predicates of `Foo`... + --> $DIR/cycle-iat-inside-of-adt.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^ + = note: ...which requires computing the inferred outlives predicates for items in this crate... +note: ...which requires computing type of `Foo::bar`... + --> $DIR/cycle-iat-inside-of-adt.rs:6:5 + | +LL | bar: Self::Bar, + | ^^^^^^^^^^^^^^ +note: ...which requires computing normalized predicates of `Foo`... + --> $DIR/cycle-iat-inside-of-adt.rs:5:1 + | +LL | struct Foo { + | ^^^^^^^^^^ + = note: ...which again requires computing predicates of `Foo`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cycle-iat-inside-of-adt.rs:5:1 + | +LL | / struct Foo { +LL | | bar: Self::Bar, +LL | | } +LL | | impl Foo { +LL | | pub type Bar = usize; +LL | | } + | |_^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0391, E0601. +For more information about an error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.rs b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.rs new file mode 100644 index 00000000000..0c2a38b1173 --- /dev/null +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.rs @@ -0,0 +1,16 @@ +// known-bug: unknown + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// FIXME(inherent_associated_types): This shouldn't lead to a cycle error. + +fn user<T>() where S<T>::P: std::fmt::Debug {} + +struct S<T>; + +impl<T: Copy> S<T> { + type P = (); +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr new file mode 100644 index 00000000000..aaa9a39ea0f --- /dev/null +++ b/tests/ui/associated-inherent-types/bugs/cycle-iat-inside-of-where-predicate.stderr @@ -0,0 +1,37 @@ +error[E0391]: cycle detected when computing predicates of `user` + --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 + | +LL | fn user<T>() where S<T>::P: std::fmt::Debug {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: ...which requires computing predicates of `user`... + --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 + | +LL | fn user<T>() where S<T>::P: std::fmt::Debug {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing explicit predicates of `user`... + --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 + | +LL | fn user<T>() where S<T>::P: std::fmt::Debug {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires computing normalized predicates of `user`... + --> $DIR/cycle-iat-inside-of-where-predicate.rs:8:1 + | +LL | fn user<T>() where S<T>::P: std::fmt::Debug {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires computing predicates of `user`, completing the cycle +note: cycle used when collecting item types in top-level module + --> $DIR/cycle-iat-inside-of-where-predicate.rs:3:1 + | +LL | / #![feature(inherent_associated_types)] +LL | | #![allow(incomplete_features)] +LL | | +LL | | // FIXME(inherent_associated_types): This shouldn't lead to a cycle error. +... | +LL | | +LL | | fn main() {} + | |____________^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-inherent-types/bugs/ice-substitution.rs b/tests/ui/associated-inherent-types/bugs/ice-substitution.rs deleted file mode 100644 index 53ac79e0561..00000000000 --- a/tests/ui/associated-inherent-types/bugs/ice-substitution.rs +++ /dev/null @@ -1,23 +0,0 @@ -// known-bug: unknown -// failure-status: 101 -// normalize-stderr-test "note: .*\n\n" -> "" -// normalize-stderr-test "thread 'rustc' panicked.*\n" -> "" -// rustc-env:RUST_BACKTRACE=0 - -// FIXME: I presume a type variable that couldn't be solved by `resolve_vars_if_possible` -// escapes the InferCtxt snapshot. - -#![feature(inherent_associated_types)] -#![allow(incomplete_features)] - -struct Cont<T>(T); - -impl<T: Copy> Cont<T> { - type Out = Vec<T>; -} - -pub fn weird<T: Copy>(x: T) { - let _: Cont<_>::Out = vec![true]; -} - -fn main() {} diff --git a/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr b/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr deleted file mode 100644 index 1648cfb266b..00000000000 --- a/tests/ui/associated-inherent-types/bugs/ice-substitution.stderr +++ /dev/null @@ -1,6 +0,0 @@ -error: the compiler unexpectedly panicked. this is a bug. - -query stack during panic: -#0 [typeck] type-checking `weird` -#1 [used_trait_imports] finding used_trait_imports `weird` -end of query stack diff --git a/tests/ui/associated-inherent-types/bugs/inference-fail.rs b/tests/ui/associated-inherent-types/bugs/inference-fail.rs deleted file mode 100644 index a920b412b1a..00000000000 --- a/tests/ui/associated-inherent-types/bugs/inference-fail.rs +++ /dev/null @@ -1,15 +0,0 @@ -// known-bug: unknown - -#![feature(inherent_associated_types)] -#![allow(incomplete_features)] - -struct S<T>(T); - -impl S<()> { - type P = i128; -} - -fn main() { - // We fail to infer `_ == ()` here. - let _: S<_>::P; -} diff --git a/tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs b/tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs deleted file mode 100644 index 632dbf3854b..00000000000 --- a/tests/ui/associated-inherent-types/bugs/lack-of-regionck.rs +++ /dev/null @@ -1,19 +0,0 @@ -// known-bug: unknown -// check-pass - -// We currently don't region-check inherent associated type projections at all. - -#![feature(inherent_associated_types)] -#![allow(incomplete_features, dead_code)] - -struct S<T>(T); - -impl S<&'static ()> { - type T = (); -} - -fn usr<'a>() { - let _: S::<&'a ()>::T; // this should *fail* but it doesn't! -} - -fn main() {} diff --git a/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs new file mode 100644 index 00000000000..c7f66e645bb --- /dev/null +++ b/tests/ui/associated-inherent-types/bugs/wf-check-skipped.rs @@ -0,0 +1,15 @@ +// known-bug: #100041 +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// FIXME(inherent_associated_types): This should fail. + +struct Foo; + +impl Foo { + type Bar<T> = (); +} + +fn main() -> Foo::Bar::<Vec<[u32]>> {} diff --git a/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs b/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs index f846bfa4168..83be4f43b5e 100644 --- a/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs +++ b/tests/ui/associated-inherent-types/dispatch-on-self-type-0.rs @@ -31,7 +31,7 @@ fn main() { let _: Select<u8>::Projection = (); let _: Choose<NonCopy>::Result = (); - let _: Choose<bool>::Result = vec![true]; + let _: Choose<&str>::Result = vec!["…"]; // regression test for issue #108957 } // Test if we use the correct `ParamEnv` when proving obligations. diff --git a/tests/ui/associated-inherent-types/former-subst-ice.rs b/tests/ui/associated-inherent-types/former-subst-ice.rs new file mode 100644 index 00000000000..48390b9430b --- /dev/null +++ b/tests/ui/associated-inherent-types/former-subst-ice.rs @@ -0,0 +1,16 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Cont<T>(T); + +impl<T: Copy> Cont<T> { + type Out = Vec<T>; +} + +pub fn weird<T: Copy>(x: T) { + let _: Cont<_>::Out = vec![true]; +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr new file mode 100644 index 00000000000..464b59c249f --- /dev/null +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/generic-associated-types-bad.rs:16:10 + | +LL | const _: Ty::Pr<String> = String::new(); + | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `Ty::Pr` + --> $DIR/generic-associated-types-bad.rs:10:16 + | +LL | type Pr<T: Copy> = T; + | ^^^^ required by this bound in `Ty::Pr` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr new file mode 100644 index 00000000000..4f371b24e80 --- /dev/null +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `Vec<()>: Copy` is not satisfied + --> $DIR/generic-associated-types-bad.rs:20:12 + | +LL | let _: Ty::Pr<Vec<()>>; + | ^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `Vec<()>` + | +note: required by a bound in `Ty::Pr` + --> $DIR/generic-associated-types-bad.rs:10:16 + | +LL | type Pr<T: Copy> = T; + | ^^^^ required by this bound in `Ty::Pr` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr new file mode 100644 index 00000000000..74ec39424ed --- /dev/null +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.region.stderr @@ -0,0 +1,11 @@ +error: lifetime may not live long enough + --> $DIR/generic-associated-types-bad.rs:25:12 + | +LL | fn user<'a>() { + | -- lifetime `'a` defined here +LL | #[cfg(region)] +LL | let _: Ty::Static<&'a str> = ""; + | ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.rs b/tests/ui/associated-inherent-types/generic-associated-types-bad.rs new file mode 100644 index 00000000000..e66392a0a94 --- /dev/null +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.rs @@ -0,0 +1,26 @@ +// revisions: item local region + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +#[derive(Clone, Copy)] +pub enum Ty {} + +impl Ty { + type Pr<T: Copy> = T; + + type Static<Q: 'static> = Q; +} + +#[cfg(item)] +const _: Ty::Pr<String> = String::new(); //[item]~ the trait bound `String: Copy` is not satisfied + +fn main() { + #[cfg(local)] + let _: Ty::Pr<Vec<()>>; //[local]~ ERROR the trait bound `Vec<()>: Copy` is not satisfied +} + +fn user<'a>() { + #[cfg(region)] + let _: Ty::Static<&'a str> = ""; //[region]~ ERROR lifetime may not live long enough +} diff --git a/tests/ui/associated-inherent-types/inference-fail.rs b/tests/ui/associated-inherent-types/inference-fail.rs new file mode 100644 index 00000000000..939a4ff60f2 --- /dev/null +++ b/tests/ui/associated-inherent-types/inference-fail.rs @@ -0,0 +1,11 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S<T>(T); + +impl<T> S<T> { type P = (); } + +fn main() { + // There is no way to infer this type. + let _: S<_>::P = (); //~ ERROR type annotations needed +} diff --git a/tests/ui/associated-inherent-types/bugs/inference-fail.stderr b/tests/ui/associated-inherent-types/inference-fail.stderr index 425691bd6c4..f29144e4aa7 100644 --- a/tests/ui/associated-inherent-types/bugs/inference-fail.stderr +++ b/tests/ui/associated-inherent-types/inference-fail.stderr @@ -1,8 +1,8 @@ error[E0282]: type annotations needed - --> $DIR/inference-fail.rs:14:14 + --> $DIR/inference-fail.rs:10:12 | -LL | let _: S<_>::P; - | ^ cannot infer type +LL | let _: S<_>::P = (); + | ^^^^^^^ cannot infer type for type parameter `T` error: aborting due to previous error diff --git a/tests/ui/associated-inherent-types/inference.rs b/tests/ui/associated-inherent-types/inference.rs new file mode 100644 index 00000000000..38179214fa1 --- /dev/null +++ b/tests/ui/associated-inherent-types/inference.rs @@ -0,0 +1,39 @@ +// Testing inference capabilities. +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +use std::convert::identity; + +struct Container<T>(T); + +impl Container<u32> { + type Sink = (); +} + +impl<Any> Container<Any> { + type Thing = Any; +} + +impl<T> Container<(T, ())> { + type Output = ((), Wrapped<T>); +} + +fn main() { + // Inferred via the Self type of the impl. + let _: Container<_>::Sink; + + // Inferred via the RHS: + + let _: Container<_>::Thing = 0; + + let _: Container<Wrapped<_>>::Thing = Wrapped(false); + + let _: Container<_>::Output = (drop(1), Wrapped("...")); + + let binding: Container<_>::Thing = Default::default(); // unsolved at this point + identity::<String>(binding); // constrained and solved here +} + +struct Wrapped<T>(T); diff --git a/tests/ui/associated-inherent-types/issue-109768.rs b/tests/ui/associated-inherent-types/issue-109768.rs new file mode 100644 index 00000000000..a3ae2e2ab44 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-109768.rs @@ -0,0 +1,12 @@ +// incremental + +struct Wrapper<T>(T); + +struct Local<T, U>(T, U); + +impl<T> Local { //~ ERROR missing generics for struct `Local` + type AssocType3 = T; //~ ERROR inherent associated types are unstable + + const WRAPPED_ASSOC_3: Wrapper<Self::AssocType3> = Wrapper(); +} +//~^ ERROR `main` function not found diff --git a/tests/ui/associated-inherent-types/issue-109768.stderr b/tests/ui/associated-inherent-types/issue-109768.stderr new file mode 100644 index 00000000000..97706d4062a --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-109768.stderr @@ -0,0 +1,35 @@ +error[E0601]: `main` function not found in crate `issue_109768` + --> $DIR/issue-109768.rs:11:2 + | +LL | } + | ^ consider adding a `main` function to `$DIR/issue-109768.rs` + +error[E0107]: missing generics for struct `Local` + --> $DIR/issue-109768.rs:7:9 + | +LL | impl<T> Local { + | ^^^^^ expected 2 generic arguments + | +note: struct defined here, with 2 generic parameters: `T`, `U` + --> $DIR/issue-109768.rs:5:8 + | +LL | struct Local<T, U>(T, U); + | ^^^^^ - - +help: add missing generic arguments + | +LL | impl<T> Local<T, U> { + | ++++++ + +error[E0658]: inherent associated types are unstable + --> $DIR/issue-109768.rs:8:5 + | +LL | type AssocType3 = T; + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #8995 <https://github.com/rust-lang/rust/issues/8995> for more information + = help: add `#![feature(inherent_associated_types)]` to the crate attributes to enable + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0601, E0658. +For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/associated-inherent-types/issue-109789.rs b/tests/ui/associated-inherent-types/issue-109789.rs new file mode 100644 index 00000000000..0b5ba7d1fb5 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-109789.rs @@ -0,0 +1,22 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo<T>(T); + +impl Foo<fn(&'static ())> { + type Assoc = u32; +} + +trait Other {} +impl Other for u32 {} + +// FIXME(inherent_associated_types): Avoid emitting two diagnostics (they only differ in span). +// FIXME(inherent_associated_types): Enhancement: Spruce up the diagnostic by saying something like +// "implementation is not general enough" as is done for traits via +// `try_report_trait_placeholder_mismatch`. + +fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {} +//~^ ERROR mismatched types +//~| ERROR mismatched types + +fn main() {} diff --git a/tests/ui/associated-inherent-types/issue-109789.stderr b/tests/ui/associated-inherent-types/issue-109789.stderr new file mode 100644 index 00000000000..7af338274a1 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-109789.stderr @@ -0,0 +1,21 @@ +error[E0308]: mismatched types + --> $DIR/issue-109789.rs:18:1 + | +LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Foo<fn(&'static ())>` + found struct `Foo<for<'a> fn(&'a ())>` + +error[E0308]: mismatched types + --> $DIR/issue-109789.rs:18:11 + | +LL | fn bar(_: Foo<for<'a> fn(&'a ())>::Assoc) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other + | + = note: expected struct `Foo<fn(&'static ())>` + found struct `Foo<for<'a> fn(&'a ())>` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-inherent-types/issue-109790.rs b/tests/ui/associated-inherent-types/issue-109790.rs new file mode 100644 index 00000000000..b2be19a28f4 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-109790.rs @@ -0,0 +1,17 @@ +// check-pass + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo<T>(T); + +impl<'a> Foo<fn(&'a ())> { + type Assoc = &'a (); +} + +trait Other {} +impl Other for u32 {} + +fn bar(_: for<'a> fn(Foo<fn(&'a ())>::Assoc)) {} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/late-bound-regions.rs b/tests/ui/associated-inherent-types/late-bound-regions.rs new file mode 100644 index 00000000000..488a2cda649 --- /dev/null +++ b/tests/ui/associated-inherent-types/late-bound-regions.rs @@ -0,0 +1,25 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// Test if we correctly normalize `S<'a>::P` with respect to late-bound regions. + +type Function = for<'a> fn(&'a i32) -> S<'a>::P; + +struct S<'a>(&'a ()); + +trait Inter { + type P; +} + +impl<'a> S<'a> { + type P = &'a i32; +} + +fn ret_ref_local<'e>() -> &'e i32 { + let f: Function = |x| x; + + let local = 0; + f(&local) //~ ERROR cannot return value referencing local variable `local` +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/late-bound-regions.stderr b/tests/ui/associated-inherent-types/late-bound-regions.stderr new file mode 100644 index 00000000000..4706fcca91d --- /dev/null +++ b/tests/ui/associated-inherent-types/late-bound-regions.stderr @@ -0,0 +1,12 @@ +error[E0515]: cannot return value referencing local variable `local` + --> $DIR/late-bound-regions.rs:22:5 + | +LL | f(&local) + | ^^------^ + | | | + | | `local` is borrowed here + | returns a value referencing data owned by the current function + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0515`. diff --git a/tests/ui/associated-inherent-types/normalization-overflow.rs b/tests/ui/associated-inherent-types/normalization-overflow.rs new file mode 100644 index 00000000000..4228238aa7b --- /dev/null +++ b/tests/ui/associated-inherent-types/normalization-overflow.rs @@ -0,0 +1,12 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// FIXME(fmease): I'd prefer to report a cycle error here instead of an overflow one. + +struct T; + +impl T { + type This = Self::This; //~ ERROR overflow evaluating associated type `T::This` +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/normalization-overflow.stderr b/tests/ui/associated-inherent-types/normalization-overflow.stderr new file mode 100644 index 00000000000..16bb64281e3 --- /dev/null +++ b/tests/ui/associated-inherent-types/normalization-overflow.stderr @@ -0,0 +1,8 @@ +error: overflow evaluating associated type `T::This` + --> $DIR/normalization-overflow.rs:9:17 + | +LL | type This = Self::This; + | ^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-inherent-types/private-in-public.rs b/tests/ui/associated-inherent-types/private-in-public.rs new file mode 100644 index 00000000000..a4b372537c7 --- /dev/null +++ b/tests/ui/associated-inherent-types/private-in-public.rs @@ -0,0 +1,26 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] +#![crate_type = "lib"] + +#![deny(private_in_public)] + +pub type PubAlias0 = PubTy::PrivAssocTy; +//~^ ERROR private associated type `PubTy::PrivAssocTy` in public interface (error E0446) +//~| WARNING this was previously accepted +pub type PubAlias1 = PrivTy::PubAssocTy; +//~^ ERROR private type `PrivTy` in public interface (error E0446) +//~| WARNING this was previously accepted +pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>; +//~^ ERROR private type `PrivTy` in public interface (error E0446) +//~| WARNING this was previously accepted + +pub struct PubTy; +impl PubTy { + type PrivAssocTy = (); + pub type PubAssocTy<T> = T; +} + +struct PrivTy; +impl PrivTy { + pub type PubAssocTy = (); +} diff --git a/tests/ui/associated-inherent-types/private-in-public.stderr b/tests/ui/associated-inherent-types/private-in-public.stderr new file mode 100644 index 00000000000..f0a64e96179 --- /dev/null +++ b/tests/ui/associated-inherent-types/private-in-public.stderr @@ -0,0 +1,34 @@ +error: private associated type `PubTy::PrivAssocTy` in public interface (error E0446) + --> $DIR/private-in-public.rs:7:1 + | +LL | pub type PubAlias0 = PubTy::PrivAssocTy; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> +note: the lint level is defined here + --> $DIR/private-in-public.rs:5:9 + | +LL | #![deny(private_in_public)] + | ^^^^^^^^^^^^^^^^^ + +error: private type `PrivTy` in public interface (error E0446) + --> $DIR/private-in-public.rs:10:1 + | +LL | pub type PubAlias1 = PrivTy::PubAssocTy; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> + +error: private type `PrivTy` in public interface (error E0446) + --> $DIR/private-in-public.rs:13:1 + | +LL | pub type PubAlias2 = PubTy::PubAssocTy<PrivTy>; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #34537 <https://github.com/rust-lang/rust/issues/34537> + +error: aborting due to 3 previous errors + diff --git a/tests/ui/associated-inherent-types/regionck-0.rs b/tests/ui/associated-inherent-types/regionck-0.rs new file mode 100644 index 00000000000..7c94539ace1 --- /dev/null +++ b/tests/ui/associated-inherent-types/regionck-0.rs @@ -0,0 +1,14 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S<T>(T); + +impl S<&'static ()> { + type T = (); +} + +fn user<'a>() { + let _: S::<&'a ()>::T; //~ ERROR lifetime may not live long enough +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/regionck-0.stderr b/tests/ui/associated-inherent-types/regionck-0.stderr new file mode 100644 index 00000000000..3a438ee630e --- /dev/null +++ b/tests/ui/associated-inherent-types/regionck-0.stderr @@ -0,0 +1,10 @@ +error: lifetime may not live long enough + --> $DIR/regionck-0.rs:11:12 + | +LL | fn user<'a>() { + | -- lifetime `'a` defined here +LL | let _: S::<&'a ()>::T; + | ^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` + +error: aborting due to previous error + diff --git a/tests/ui/associated-inherent-types/regionck-1.rs b/tests/ui/associated-inherent-types/regionck-1.rs new file mode 100644 index 00000000000..ec663cd0f77 --- /dev/null +++ b/tests/ui/associated-inherent-types/regionck-1.rs @@ -0,0 +1,13 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct U; + +impl U { + // Don't imply any bounds here. + + type NoTyOutliv<'a, T> = &'a T; //~ ERROR the parameter type `T` may not live long enough + type NoReOutliv<'a, 'b> = &'a &'b (); //~ ERROR reference has a longer lifetime than the data it references +} + +fn main() {} diff --git a/tests/ui/associated-inherent-types/regionck-1.stderr b/tests/ui/associated-inherent-types/regionck-1.stderr new file mode 100644 index 00000000000..b17d89ca306 --- /dev/null +++ b/tests/ui/associated-inherent-types/regionck-1.stderr @@ -0,0 +1,29 @@ +error[E0309]: the parameter type `T` may not live long enough + --> $DIR/regionck-1.rs:9:30 + | +LL | type NoTyOutliv<'a, T> = &'a T; + | ^^^^^- help: consider adding a where clause: `where T: 'a` + | | + | ...so that the reference type `&'a T` does not outlive the data it points at + +error[E0491]: in type `&'a &'b ()`, reference has a longer lifetime than the data it references + --> $DIR/regionck-1.rs:10:31 + | +LL | type NoReOutliv<'a, 'b> = &'a &'b (); + | ^^^^^^^^^^ + | +note: the pointer is valid for the lifetime `'a` as defined here + --> $DIR/regionck-1.rs:10:21 + | +LL | type NoReOutliv<'a, 'b> = &'a &'b (); + | ^^ +note: but the referenced data is only valid for the lifetime `'b` as defined here + --> $DIR/regionck-1.rs:10:25 + | +LL | type NoReOutliv<'a, 'b> = &'a &'b (); + | ^^ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0309, E0491. +For more information about an error, try `rustc --explain E0309`. diff --git a/tests/ui/associated-inherent-types/regionck-2.rs b/tests/ui/associated-inherent-types/regionck-2.rs new file mode 100644 index 00000000000..7a0b8b08300 --- /dev/null +++ b/tests/ui/associated-inherent-types/regionck-2.rs @@ -0,0 +1,14 @@ +// Regression test for issue #109299. + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Lexer<'d>(&'d ()); + +impl Lexer<'static> { + type Cursor = (); +} + +fn test(_: Lexer::Cursor) {} //~ ERROR mismatched types + +fn main() {} diff --git a/tests/ui/associated-inherent-types/regionck-2.stderr b/tests/ui/associated-inherent-types/regionck-2.stderr new file mode 100644 index 00000000000..b0a4ed35d56 --- /dev/null +++ b/tests/ui/associated-inherent-types/regionck-2.stderr @@ -0,0 +1,18 @@ +error[E0308]: mismatched types + --> $DIR/regionck-2.rs:12:12 + | +LL | fn test(_: Lexer::Cursor) {} + | ^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected struct `Lexer<'static>` + found struct `Lexer<'_>` +note: the anonymous lifetime defined here... + --> $DIR/regionck-2.rs:12:12 + | +LL | fn test(_: Lexer::Cursor) {} + | ^^^^^ + = note: ...does not necessarily outlive the static lifetime + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs new file mode 100644 index 00000000000..b32b4288ac9 --- /dev/null +++ b/tests/ui/associated-inherent-types/type-alias-bounds-are-enforced.rs @@ -0,0 +1,26 @@ +// check-pass +// compile-flags: --crate-type=lib + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +// Bounds on the self type play a major role in the resolution of inherent associated types (*). +// As a result of that, if a type alias contains any then its bounds have to be respected and the +// lint `type_alias_bounds` should not fire. +// +// FIXME(inherent_associated_types): In the current implementation that is. We might move the +// selection phase of IATs from hir_typeck to trait_selection resulting in us not requiring the +// ParamEnv that early allowing us to ignore bounds on type aliases again. +// Triage this before stabilization. + +#![deny(type_alias_bounds)] + +pub type Alias<T: Bound> = (Source<T>::Assoc,); + + +pub struct Source<T>(T); +pub trait Bound {} + +impl<T: Bound> Source<T> { + pub type Assoc = (); +} diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.rs b/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.rs new file mode 100644 index 00000000000..d081c4d5b78 --- /dev/null +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.rs @@ -0,0 +1,12 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S<T>(T); + +impl<T: Copy> S<T> { + type T = T; +} + +fn main() { + let _: S<_>::T = String::new(); //~ ERROR the trait bound `String: Copy` is not satisfied +} diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr b/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr new file mode 100644 index 00000000000..ecf30f4cdec --- /dev/null +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-inferred-type.stderr @@ -0,0 +1,17 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/unsatisfied-bounds-inferred-type.rs:11:12 + | +LL | let _: S<_>::T = String::new(); + | ^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `S<T>::T` + --> $DIR/unsatisfied-bounds-inferred-type.rs:6:9 + | +LL | impl<T: Copy> S<T> { + | ^^^^ required by this bound in `S<T>::T` +LL | type T = T; + | - required by a bound in this associated type + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.rs b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.rs new file mode 100644 index 00000000000..97bd2c42160 --- /dev/null +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.rs @@ -0,0 +1,14 @@ +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct S<T>(T); + +impl<T> S<T> { + type X = () + where + T: Copy; +} + +fn main() { + let _: S::<String>::X; //~ ERROR the trait bound `String: Copy` is not satisfied +} diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr new file mode 100644 index 00000000000..d4968cd05dc --- /dev/null +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr @@ -0,0 +1,18 @@ +error[E0277]: the trait bound `String: Copy` is not satisfied + --> $DIR/unsatisfied-bounds-where-clause-on-assoc-ty.rs:13:12 + | +LL | let _: S::<String>::X; + | ^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String` + | +note: required by a bound in `S<T>::X` + --> $DIR/unsatisfied-bounds-where-clause-on-assoc-ty.rs:9:12 + | +LL | type X = () + | - required by a bound in this associated type +LL | where +LL | T: Copy; + | ^^^^ required by this bound in `S<T>::X` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. |