diff options
Diffstat (limited to 'tests/ui/associated-consts')
86 files changed, 1958 insertions, 0 deletions
diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.rs b/tests/ui/associated-consts/assoc-const-eq-missing.rs new file mode 100644 index 000000000..5e029a12d --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-missing.rs @@ -0,0 +1,26 @@ +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + + +fn foo1<F: Foo<Z=3>>() {} +//~^ ERROR associated type +fn foo2<F: Foo<Z=usize>>() {} +//~^ ERROR associated type +fn foo3<F: Foo<Z=5>>() {} +//~^ ERROR associated type + +fn main() { + foo1::<Bar>(); + foo2::<Bar>(); + foo3::<Bar>(); +} diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr new file mode 100644 index 000000000..b4bd6456c --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr @@ -0,0 +1,21 @@ +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:15:16 + | +LL | fn foo1<F: Foo<Z=3>>() {} + | ^ associated type `Z` not found + +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:17:16 + | +LL | fn foo2<F: Foo<Z=usize>>() {} + | ^ associated type `Z` not found + +error[E0220]: associated type `Z` not found for `Foo` + --> $DIR/assoc-const-eq-missing.rs:19:16 + | +LL | fn foo3<F: Foo<Z=5>>() {} + | ^ associated type `Z` not found + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0220`. diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs new file mode 100644 index 000000000..c5d78469e --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs @@ -0,0 +1,31 @@ +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub trait FooTy { + type T; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +impl FooTy for Bar { + type T = usize; +} + + +fn foo<F: Foo<N=usize>>() {} +//~^ ERROR expected associated constant bound, found type +fn foo2<F: FooTy<T=3usize>>() {} +//~^ ERROR expected associated type bound, found constant + +fn main() { + foo::<Bar>(); + foo2::<Bar>(); +} diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr new file mode 100644 index 000000000..11198729e --- /dev/null +++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr @@ -0,0 +1,26 @@ +error: expected associated constant bound, found type + --> $DIR/assoc-const-ty-mismatch.rs:23:15 + | +LL | fn foo<F: Foo<N=usize>>() {} + | ^^^^^^^ + | +note: associated constant defined here + --> $DIR/assoc-const-ty-mismatch.rs:5:3 + | +LL | const N: usize; + | ^^^^^^^^^^^^^^ + +error: expected associated type bound, found constant + --> $DIR/assoc-const-ty-mismatch.rs:25:18 + | +LL | fn foo2<F: FooTy<T=3usize>>() {} + | ^^^^^^^^ + | +note: associated type defined here + --> $DIR/assoc-const-ty-mismatch.rs:9:3 + | +LL | type T; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/associated-consts/assoc-const.rs b/tests/ui/associated-consts/assoc-const.rs new file mode 100644 index 000000000..9c7884c80 --- /dev/null +++ b/tests/ui/associated-consts/assoc-const.rs @@ -0,0 +1,22 @@ +// run-pass +#![feature(associated_const_equality)] +#![allow(unused)] + +pub trait Foo { + const N: usize; +} + +pub struct Bar; + +impl Foo for Bar { + const N: usize = 3; +} + +const TEST:usize = 3; + + +fn foo<F: Foo<N=3usize>>() {} + +fn main() { + foo::<Bar>() +} diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.rs b/tests/ui/associated-consts/associated-const-ambiguity-report.rs new file mode 100644 index 000000000..927d2c69e --- /dev/null +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.rs @@ -0,0 +1,21 @@ +trait Foo { + const ID: i32; +} + +trait Bar { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +impl Bar for i32 { + const ID: i32 = 3; +} + +const X: i32 = <i32>::ID; //~ ERROR E0034 + +fn main() { + assert_eq!(1, X); +} diff --git a/tests/ui/associated-consts/associated-const-ambiguity-report.stderr b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr new file mode 100644 index 000000000..5435f2232 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-ambiguity-report.stderr @@ -0,0 +1,28 @@ +error[E0034]: multiple applicable items in scope + --> $DIR/associated-const-ambiguity-report.rs:17:23 + | +LL | const X: i32 = <i32>::ID; + | ^^ multiple `ID` found + | +note: candidate #1 is defined in an impl of the trait `Foo` for the type `i32` + --> $DIR/associated-const-ambiguity-report.rs:10:5 + | +LL | const ID: i32 = 1; + | ^^^^^^^^^^^^^ +note: candidate #2 is defined in an impl of the trait `Bar` for the type `i32` + --> $DIR/associated-const-ambiguity-report.rs:14:5 + | +LL | const ID: i32 = 3; + | ^^^^^^^^^^^^^ +help: disambiguate the associated constant for candidate #1 + | +LL | const X: i32 = <i32 as Foo>::ID; + | ~~~~~~~~~~~~~~ +help: disambiguate the associated constant for candidate #2 + | +LL | const X: i32 = <i32 as Bar>::ID; + | ~~~~~~~~~~~~~~ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0034`. diff --git a/tests/ui/associated-consts/associated-const-array-len.rs b/tests/ui/associated-consts/associated-const-array-len.rs new file mode 100644 index 000000000..17d782427 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-array-len.rs @@ -0,0 +1,10 @@ +trait Foo { + const ID: usize; +} + +const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; +//~^ ERROR the trait bound `i32: Foo` is not satisfied + +fn main() { + assert_eq!(1, X); +} diff --git a/tests/ui/associated-consts/associated-const-array-len.stderr b/tests/ui/associated-consts/associated-const-array-len.stderr new file mode 100644 index 000000000..86c62e7b7 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-array-len.stderr @@ -0,0 +1,9 @@ +error[E0277]: the trait bound `i32: Foo` is not satisfied + --> $DIR/associated-const-array-len.rs:5:16 + | +LL | const X: [i32; <i32 as Foo>::ID] = [0, 1, 2]; + | ^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `i32` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/associated-consts/associated-const-const-eval.rs b/tests/ui/associated-consts/associated-const-const-eval.rs new file mode 100644 index 000000000..5a34bb97c --- /dev/null +++ b/tests/ui/associated-consts/associated-const-const-eval.rs @@ -0,0 +1,20 @@ +// run-pass + +trait Foo { + const NUM: usize; +} + +impl Foo for i32 { + const NUM: usize = 1; +} + +const FOO: usize = <i32 as Foo>::NUM; + +fn main() { + assert_eq!(1, FOO); + + match 1 { + <i32 as Foo>::NUM => {}, + _ => assert!(false) + } +} diff --git a/tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs b/tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs new file mode 100644 index 000000000..611639b84 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-cross-crate-const-eval.rs @@ -0,0 +1,28 @@ +// run-pass +// aux-build:associated-const-cc-lib.rs + + +extern crate associated_const_cc_lib as foolib; + +pub struct LocalFoo; + +impl foolib::Foo for LocalFoo { + const BAR: usize = 1; +} + +const FOO_1: usize = <foolib::FooNoDefault as foolib::Foo>::BAR; +const FOO_2: usize = <LocalFoo as foolib::Foo>::BAR; +const FOO_3: usize = foolib::InherentBar::BAR; + +fn main() { + assert_eq!(0, FOO_1); + assert_eq!(1, FOO_2); + assert_eq!(3, FOO_3); + + match 0 { + <foolib::FooNoDefault as foolib::Foo>::BAR => {}, + <LocalFoo as foolib::Foo>::BAR => assert!(false), + foolib::InherentBar::BAR => assert!(false), + _ => assert!(false) + } +} diff --git a/tests/ui/associated-consts/associated-const-cross-crate-defaults.rs b/tests/ui/associated-consts/associated-const-cross-crate-defaults.rs new file mode 100644 index 000000000..92d9cffec --- /dev/null +++ b/tests/ui/associated-consts/associated-const-cross-crate-defaults.rs @@ -0,0 +1,22 @@ +// run-pass +// aux-build:associated-const-cc-lib.rs + + +extern crate associated_const_cc_lib as foolib; + +pub struct LocalFooUseDefault; + +impl foolib::FooDefault for LocalFooUseDefault {} + +pub struct LocalFooOverwriteDefault; + +impl foolib::FooDefault for LocalFooOverwriteDefault { + const BAR: usize = 4; +} + +fn main() { + assert_eq!(1, <foolib::FooUseDefault as foolib::FooDefault>::BAR); + assert_eq!(2, <foolib::FooOverwriteDefault as foolib::FooDefault>::BAR); + assert_eq!(1, <LocalFooUseDefault as foolib::FooDefault>::BAR); + assert_eq!(4, <LocalFooOverwriteDefault as foolib::FooDefault>::BAR); +} diff --git a/tests/ui/associated-consts/associated-const-cross-crate.rs b/tests/ui/associated-consts/associated-const-cross-crate.rs new file mode 100644 index 000000000..ecdc112e0 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-cross-crate.rs @@ -0,0 +1,17 @@ +// run-pass +// aux-build:associated-const-cc-lib.rs + + +extern crate associated_const_cc_lib as foolib; + +pub struct LocalFoo; + +impl foolib::Foo for LocalFoo { + const BAR: usize = 1; +} + +fn main() { + assert_eq!(0, <foolib::FooNoDefault as foolib::Foo>::BAR); + assert_eq!(1, <LocalFoo as foolib::Foo>::BAR); + assert_eq!(3, foolib::InherentBar::BAR); +} diff --git a/tests/ui/associated-consts/associated-const-dead-code.rs b/tests/ui/associated-consts/associated-const-dead-code.rs new file mode 100644 index 000000000..f7b676418 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-dead-code.rs @@ -0,0 +1,12 @@ +#![deny(dead_code)] + +struct MyFoo; + +impl MyFoo { + const BAR: u32 = 1; + //~^ ERROR associated constant `BAR` is never used +} + +fn main() { + let _: MyFoo = MyFoo; +} diff --git a/tests/ui/associated-consts/associated-const-dead-code.stderr b/tests/ui/associated-consts/associated-const-dead-code.stderr new file mode 100644 index 000000000..cc701cc4b --- /dev/null +++ b/tests/ui/associated-consts/associated-const-dead-code.stderr @@ -0,0 +1,14 @@ +error: associated constant `BAR` is never used + --> $DIR/associated-const-dead-code.rs:6:11 + | +LL | const BAR: u32 = 1; + | ^^^ + | +note: the lint level is defined here + --> $DIR/associated-const-dead-code.rs:1:9 + | +LL | #![deny(dead_code)] + | ^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/associated-const-generic-obligations.rs b/tests/ui/associated-consts/associated-const-generic-obligations.rs new file mode 100644 index 000000000..498e315b5 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-generic-obligations.rs @@ -0,0 +1,18 @@ +trait Foo { + type Out: Sized; +} + +impl Foo for String { + type Out = String; +} + +trait Bar: Foo { + const FROM: Self::Out; +} + +impl<T: Foo> Bar for T { + const FROM: &'static str = "foo"; + //~^ ERROR implemented const `FROM` has an incompatible type for trait [E0326] +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-generic-obligations.stderr b/tests/ui/associated-consts/associated-const-generic-obligations.stderr new file mode 100644 index 000000000..f45fa0ad5 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-generic-obligations.stderr @@ -0,0 +1,17 @@ +error[E0326]: implemented const `FROM` has an incompatible type for trait + --> $DIR/associated-const-generic-obligations.rs:14:17 + | +LL | const FROM: &'static str = "foo"; + | ^^^^^^^^^^^^ expected associated type, found `&str` + | +note: type in trait + --> $DIR/associated-const-generic-obligations.rs:10:17 + | +LL | const FROM: Self::Out; + | ^^^^^^^^^ + = note: expected associated type `<T as Foo>::Out` + found reference `&'static str` + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs new file mode 100644 index 000000000..63bac9613 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.rs @@ -0,0 +1,11 @@ +trait Foo { + const NAME: &'static str; +} + + +impl<'a> Foo for &'a () { + const NAME: &'a str = "unit"; + //~^ ERROR const not compatible with trait +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr new file mode 100644 index 000000000..742b81535 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr @@ -0,0 +1,18 @@ +error[E0308]: const not compatible with trait + --> $DIR/associated-const-impl-wrong-lifetime.rs:7:5 + | +LL | const NAME: &'a str = "unit"; + | ^^^^^^^^^^^^^^^^^^^ lifetime mismatch + | + = note: expected reference `&'static str` + found reference `&'a str` +note: the lifetime `'a` as defined here... + --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6 + | +LL | impl<'a> Foo for &'a () { + | ^^ + = 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-consts/associated-const-impl-wrong-type.rs b/tests/ui/associated-consts/associated-const-impl-wrong-type.rs new file mode 100644 index 000000000..1aad749c1 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-type.rs @@ -0,0 +1,12 @@ +trait Foo { + const BAR: u32; +} + +struct SignedBar; + +impl Foo for SignedBar { + const BAR: i32 = -1; + //~^ ERROR implemented const `BAR` has an incompatible type for trait [E0326] +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr new file mode 100644 index 000000000..f3616035f --- /dev/null +++ b/tests/ui/associated-consts/associated-const-impl-wrong-type.stderr @@ -0,0 +1,15 @@ +error[E0326]: implemented const `BAR` has an incompatible type for trait + --> $DIR/associated-const-impl-wrong-type.rs:8:16 + | +LL | const BAR: i32 = -1; + | ^^^ expected `u32`, found `i32` + | +note: type in trait + --> $DIR/associated-const-impl-wrong-type.rs:2:16 + | +LL | const BAR: u32; + | ^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0326`. diff --git a/tests/ui/associated-consts/associated-const-in-global-const.rs b/tests/ui/associated-consts/associated-const-in-global-const.rs new file mode 100644 index 000000000..18d7a1215 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-in-global-const.rs @@ -0,0 +1,13 @@ +// run-pass + +struct Foo; + +impl Foo { + const BAR: f32 = 1.5; +} + +const FOOBAR: f32 = <Foo>::BAR; + +fn main() { + assert_eq!(1.5f32, FOOBAR); +} diff --git a/tests/ui/associated-consts/associated-const-in-trait.rs b/tests/ui/associated-consts/associated-const-in-trait.rs new file mode 100644 index 000000000..cf5d5d859 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-in-trait.rs @@ -0,0 +1,12 @@ +// #29924 + +trait Trait { + const N: usize; +} + +impl dyn Trait { + //~^ ERROR the trait `Trait` cannot be made into an object [E0038] + const fn n() -> usize { Self::N } +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-in-trait.stderr b/tests/ui/associated-consts/associated-const-in-trait.stderr new file mode 100644 index 000000000..60bbe385c --- /dev/null +++ b/tests/ui/associated-consts/associated-const-in-trait.stderr @@ -0,0 +1,18 @@ +error[E0038]: the trait `Trait` cannot be made into an object + --> $DIR/associated-const-in-trait.rs:7:6 + | +LL | impl dyn Trait { + | ^^^^^^^^^ `Trait` cannot be made into an object + | +note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety> + --> $DIR/associated-const-in-trait.rs:4:11 + | +LL | trait Trait { + | ----- this trait cannot be made into an object... +LL | const N: usize; + | ^ ...because it contains this associated `const` + = help: consider moving `N` to another trait + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0038`. diff --git a/tests/ui/associated-consts/associated-const-inherent-impl.rs b/tests/ui/associated-consts/associated-const-inherent-impl.rs new file mode 100644 index 000000000..c6d956dff --- /dev/null +++ b/tests/ui/associated-consts/associated-const-inherent-impl.rs @@ -0,0 +1,11 @@ +// run-pass + +struct Foo; + +impl Foo { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, Foo::ID); +} diff --git a/tests/ui/associated-consts/associated-const-marks-live-code.rs b/tests/ui/associated-consts/associated-const-marks-live-code.rs new file mode 100644 index 000000000..68eb4e25d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-marks-live-code.rs @@ -0,0 +1,15 @@ +// run-pass + +#![deny(dead_code)] + +const GLOBAL_BAR: u32 = 1; + +struct Foo; + +impl Foo { + const BAR: u32 = GLOBAL_BAR; +} + +pub fn main() { + let _: u32 = Foo::BAR; +} diff --git a/tests/ui/associated-consts/associated-const-match-patterns.rs b/tests/ui/associated-consts/associated-const-match-patterns.rs new file mode 100644 index 000000000..62c1cb983 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-match-patterns.rs @@ -0,0 +1,68 @@ +// run-pass +// aux-build:empty-struct.rs + + +extern crate empty_struct; +use empty_struct::XEmpty2 as XFoo; + +struct Foo; + +#[derive(PartialEq, Eq)] +enum Bar { + Var1, + Var2, +} + +// Use inherent and trait impls to test UFCS syntax. +impl Foo { + const MYBAR: Bar = Bar::Var2; +} + +trait HasBar { + const THEBAR: Bar; +} + +impl HasBar for Foo { + const THEBAR: Bar = Bar::Var1; +} + +impl HasBar for XFoo { + const THEBAR: Bar = Bar::Var1; +} + +fn main() { + // Inherent impl + assert!(match Bar::Var2 { + Foo::MYBAR => true, + _ => false, + }); + assert!(match Bar::Var2 { + <Foo>::MYBAR => true, + _ => false, + }); + // Trait impl + assert!(match Bar::Var1 { + Foo::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + <Foo>::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + <Foo as HasBar>::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + XFoo::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + <XFoo>::THEBAR => true, + _ => false, + }); + assert!(match Bar::Var1 { + <XFoo as HasBar>::THEBAR => true, + _ => false, + }); +} diff --git a/tests/ui/associated-consts/associated-const-no-item.rs b/tests/ui/associated-consts/associated-const-no-item.rs new file mode 100644 index 000000000..024d14e21 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-no-item.rs @@ -0,0 +1,10 @@ +trait Foo { + const ID: i32; +} + +const X: i32 = <i32>::ID; +//~^ ERROR no associated item named `ID` found + +fn main() { + assert_eq!(1, X); +} diff --git a/tests/ui/associated-consts/associated-const-no-item.stderr b/tests/ui/associated-consts/associated-const-no-item.stderr new file mode 100644 index 000000000..fe27da5ac --- /dev/null +++ b/tests/ui/associated-consts/associated-const-no-item.stderr @@ -0,0 +1,16 @@ +error[E0599]: no associated item named `ID` found for type `i32` in the current scope + --> $DIR/associated-const-no-item.rs:5:23 + | +LL | const X: i32 = <i32>::ID; + | ^^ associated item not found in `i32` + | + = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `ID`, perhaps you need to implement it + --> $DIR/associated-const-no-item.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0599`. diff --git a/tests/ui/associated-consts/associated-const-outer-ty-refs.rs b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs new file mode 100644 index 000000000..f32ca0ccc --- /dev/null +++ b/tests/ui/associated-consts/associated-const-outer-ty-refs.rs @@ -0,0 +1,10 @@ +// run-pass +trait Lattice { + const BOTTOM: Self; +} + +impl<T> Lattice for Option<T> { + const BOTTOM: Option<T> = None; +} + +fn main(){} diff --git a/tests/ui/associated-consts/associated-const-overwrite-default.rs b/tests/ui/associated-consts/associated-const-overwrite-default.rs new file mode 100644 index 000000000..445135aef --- /dev/null +++ b/tests/ui/associated-consts/associated-const-overwrite-default.rs @@ -0,0 +1,13 @@ +// run-pass + +trait Foo { + const ID: i32 = 2; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, <i32 as Foo>::ID); +} diff --git a/tests/ui/associated-consts/associated-const-private-impl.rs b/tests/ui/associated-consts/associated-const-private-impl.rs new file mode 100644 index 000000000..3ee3134ac --- /dev/null +++ b/tests/ui/associated-consts/associated-const-private-impl.rs @@ -0,0 +1,15 @@ +mod bar1 { + pub use self::bar2::Foo; + mod bar2 { + pub struct Foo; + + impl Foo { + const ID: i32 = 1; + } + } +} + +fn main() { + assert_eq!(1, bar1::Foo::ID); + //~^ERROR associated constant `ID` is private +} diff --git a/tests/ui/associated-consts/associated-const-private-impl.stderr b/tests/ui/associated-consts/associated-const-private-impl.stderr new file mode 100644 index 000000000..a3fa3002e --- /dev/null +++ b/tests/ui/associated-consts/associated-const-private-impl.stderr @@ -0,0 +1,12 @@ +error[E0624]: associated constant `ID` is private + --> $DIR/associated-const-private-impl.rs:13:30 + | +LL | const ID: i32 = 1; + | ------------- private associated constant defined here +... +LL | assert_eq!(1, bar1::Foo::ID); + | ^^ private associated constant + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0624`. diff --git a/tests/ui/associated-consts/associated-const-public-impl.rs b/tests/ui/associated-consts/associated-const-public-impl.rs new file mode 100644 index 000000000..787bee0ff --- /dev/null +++ b/tests/ui/associated-consts/associated-const-public-impl.rs @@ -0,0 +1,16 @@ +// run-pass + +mod bar1 { + pub use self::bar2::Foo; + mod bar2 { + pub struct Foo; + + impl Foo { + pub const ID: i32 = 1; + } + } +} + +fn main() { + assert_eq!(1, bar1::Foo::ID); +} diff --git a/tests/ui/associated-consts/associated-const-range-match-patterns.rs b/tests/ui/associated-consts/associated-const-range-match-patterns.rs new file mode 100644 index 000000000..5276869a7 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-range-match-patterns.rs @@ -0,0 +1,40 @@ +// run-pass +#![allow(dead_code, unreachable_patterns)] +#![allow(ellipsis_inclusive_range_patterns)] + +struct Foo; + +trait HasNum { + const NUM: isize; +} +impl HasNum for Foo { + const NUM: isize = 1; +} + +fn main() { + assert!(match 2 { + Foo::NUM ... 3 => true, + _ => false, + }); + assert!(match 0 { + -1 ... <Foo as HasNum>::NUM => true, + _ => false, + }); + assert!(match 1 { + <Foo as HasNum>::NUM ... <Foo>::NUM => true, + _ => false, + }); + + assert!(match 2 { + Foo::NUM ..= 3 => true, + _ => false, + }); + assert!(match 0 { + -1 ..= <Foo as HasNum>::NUM => true, + _ => false, + }); + assert!(match 1 { + <Foo as HasNum>::NUM ..= <Foo>::NUM => true, + _ => false, + }); +} diff --git a/tests/ui/associated-consts/associated-const-resolution-order.rs b/tests/ui/associated-consts/associated-const-resolution-order.rs new file mode 100644 index 000000000..d2ccd30a6 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-resolution-order.rs @@ -0,0 +1,25 @@ +// run-pass + +struct MyType; + +impl MyType { + const IMPL_IS_INHERENT: bool = true; +} + +trait MyTrait { + const IMPL_IS_INHERENT: bool; + const IMPL_IS_ON_TRAIT: bool; +} + +impl MyTrait for MyType { + const IMPL_IS_INHERENT: bool = false; + const IMPL_IS_ON_TRAIT: bool = true; +} + +fn main() { + // Check that the inherent impl is used before the trait, but that the trait + // can still be accessed. + assert!(<MyType>::IMPL_IS_INHERENT); + assert!(!<MyType as MyTrait>::IMPL_IS_INHERENT); + assert!(<MyType>::IMPL_IS_ON_TRAIT); +} diff --git a/tests/ui/associated-consts/associated-const-self-type.rs b/tests/ui/associated-consts/associated-const-self-type.rs new file mode 100644 index 000000000..36e1e4ecc --- /dev/null +++ b/tests/ui/associated-consts/associated-const-self-type.rs @@ -0,0 +1,13 @@ +// run-pass + +trait MyInt { + const ONE: Self; +} + +impl MyInt for i32 { + const ONE: i32 = 1; +} + +fn main() { + assert_eq!(1, <i32>::ONE); +} diff --git a/tests/ui/associated-consts/associated-const-trait-bound.rs b/tests/ui/associated-consts/associated-const-trait-bound.rs new file mode 100644 index 000000000..403cdbd7f --- /dev/null +++ b/tests/ui/associated-consts/associated-const-trait-bound.rs @@ -0,0 +1,21 @@ +// build-pass (FIXME(62277): could be check-pass?) + +trait ConstDefault { + const DEFAULT: Self; +} + +trait Foo: Sized {} + +trait FooExt: Foo { + type T: ConstDefault; +} + +trait Bar<F: FooExt> { + const T: F::T; +} + +impl<F: FooExt> Bar<F> for () { + const T: F::T = <F::T as ConstDefault>::DEFAULT; +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arms.rs b/tests/ui/associated-consts/associated-const-type-parameter-arms.rs new file mode 100644 index 000000000..3f260d84e --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arms.rs @@ -0,0 +1,29 @@ +pub enum EFoo { A, B, C, D } + +pub trait Foo { + const X: EFoo; +} + +struct Abc; + +impl Foo for Abc { + const X: EFoo = EFoo::B; +} + +struct Def; +impl Foo for Def { + const X: EFoo = EFoo::D; +} + +pub fn test<A: Foo, B: Foo>(arg: EFoo) { + match arg { + A::X => println!("A::X"), + //~^ error: associated consts cannot be referenced in patterns [E0158] + B::X => println!("B::X"), + //~^ error: associated consts cannot be referenced in patterns [E0158] + _ => (), + } +} + +fn main() { +} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr new file mode 100644 index 000000000..1ccf9febd --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arms.stderr @@ -0,0 +1,15 @@ +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/associated-const-type-parameter-arms.rs:20:9 + | +LL | A::X => println!("A::X"), + | ^^^^ + +error[E0158]: associated consts cannot be referenced in patterns + --> $DIR/associated-const-type-parameter-arms.rs:22:9 + | +LL | B::X => println!("B::X"), + | ^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0158`. diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs new file mode 100644 index 000000000..8fe79b97d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.rs @@ -0,0 +1,21 @@ +pub trait Foo { + const Y: usize; +} + +struct Abc; +impl Foo for Abc { + const Y: usize = 8; +} + +struct Def; +impl Foo for Def { + const Y: usize = 33; +} + +pub fn test<A: Foo, B: Foo>() { + let _array = [4; <A as Foo>::Y]; + //~^ ERROR constant expression depends on a generic parameter +} + +fn main() { +} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr new file mode 100644 index 000000000..0bc019b2d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays-2.stderr @@ -0,0 +1,10 @@ +error: constant expression depends on a generic parameter + --> $DIR/associated-const-type-parameter-arrays-2.rs:16:22 + | +LL | let _array = [4; <A as Foo>::Y]; + | ^^^^^^^^^^^^^ + | + = note: this may fail depending on what value the parameter takes + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays.rs b/tests/ui/associated-consts/associated-const-type-parameter-arrays.rs new file mode 100644 index 000000000..5152d7840 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays.rs @@ -0,0 +1,20 @@ +pub trait Foo { + const Y: usize; +} + +struct Abc; +impl Foo for Abc { + const Y: usize = 8; +} + +struct Def; +impl Foo for Def { + const Y: usize = 33; +} + +pub fn test<A: Foo, B: Foo>() { + let _array: [u32; <A as Foo>::Y]; + //~^ ERROR generic parameters may not be used +} + +fn main() {} diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr new file mode 100644 index 000000000..46a54a12d --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr @@ -0,0 +1,11 @@ +error: generic parameters may not be used in const operations + --> $DIR/associated-const-type-parameter-arrays.rs:16:24 + | +LL | let _array: [u32; <A as Foo>::Y]; + | ^ cannot perform const operation using `A` + | + = note: type parameters may not be used in const expressions + = help: use `#![feature(generic_const_exprs)]` to allow generic const expressions + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/associated-const-type-parameters.rs b/tests/ui/associated-consts/associated-const-type-parameters.rs new file mode 100644 index 000000000..e7ead1045 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-type-parameters.rs @@ -0,0 +1,44 @@ +// run-pass + +trait Foo { + const X: i32; + fn get_x() -> i32 { + Self::X + } +} + +struct Abc; +impl Foo for Abc { + const X: i32 = 11; +} + +struct Def; +impl Foo for Def { + const X: i32 = 97; +} + +struct Proxy<T>(#[allow(unused_tuple_struct_fields)] T); + +impl<T: Foo> Foo for Proxy<T> { + const X: i32 = T::X; +} + +fn sub<A: Foo, B: Foo>() -> i32 { + A::X - B::X +} + +trait Bar: Foo { + const Y: i32 = Self::X; +} + +fn main() { + assert_eq!(11, Abc::X); + assert_eq!(97, Def::X); + assert_eq!(11, Abc::get_x()); + assert_eq!(97, Def::get_x()); + assert_eq!(-86, sub::<Abc, Def>()); + assert_eq!(86, sub::<Def, Abc>()); + assert_eq!(-86, sub::<Proxy<Abc>, Def>()); + assert_eq!(-86, sub::<Abc, Proxy<Def>>()); + assert_eq!(86, sub::<Proxy<Def>, Proxy<Abc>>()); +} diff --git a/tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs b/tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs new file mode 100644 index 000000000..ca44c9f45 --- /dev/null +++ b/tests/ui/associated-consts/associated-const-ufcs-infer-trait.rs @@ -0,0 +1,13 @@ +// run-pass + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, <i32>::ID); +} diff --git a/tests/ui/associated-consts/associated-const-use-default.rs b/tests/ui/associated-consts/associated-const-use-default.rs new file mode 100644 index 000000000..adf36b1ff --- /dev/null +++ b/tests/ui/associated-consts/associated-const-use-default.rs @@ -0,0 +1,11 @@ +// run-pass + +trait Foo { + const ID: i32 = 1; +} + +impl Foo for i32 {} + +fn main() { + assert_eq!(1, <i32 as Foo>::ID); +} diff --git a/tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs b/tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs new file mode 100644 index 000000000..8f01bae4f --- /dev/null +++ b/tests/ui/associated-consts/associated-const-use-impl-of-same-trait.rs @@ -0,0 +1,25 @@ +// run-pass + +// The main purpose of this test is to ensure that different impls of the same +// trait can refer to each other without setting off the static recursion check +// (as long as there's no actual recursion). + +trait Foo { + const BAR: u32; +} + +struct IsFoo1; + +impl Foo for IsFoo1 { + const BAR: u32 = 1; +} + +struct IsFoo2; + +impl Foo for IsFoo2 { + const BAR: u32 = <IsFoo1 as Foo>::BAR; +} + +fn main() { + assert_eq!(<IsFoo1>::BAR, <IsFoo2 as Foo>::BAR); +} diff --git a/tests/ui/associated-consts/associated-const.rs b/tests/ui/associated-consts/associated-const.rs new file mode 100644 index 000000000..e4b1c29f3 --- /dev/null +++ b/tests/ui/associated-consts/associated-const.rs @@ -0,0 +1,13 @@ +// run-pass + +trait Foo { + const ID: i32; +} + +impl Foo for i32 { + const ID: i32 = 1; +} + +fn main() { + assert_eq!(1, <i32 as Foo>::ID); +} diff --git a/tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs b/tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs new file mode 100644 index 000000000..4fcefe32c --- /dev/null +++ b/tests/ui/associated-consts/auxiliary/associated-const-cc-lib.rs @@ -0,0 +1,34 @@ +#![crate_type="lib"] + +// These items are for testing that associated consts work cross-crate. +pub trait Foo { + const BAR: usize; +} + +pub struct FooNoDefault; + +impl Foo for FooNoDefault { + const BAR: usize = 0; +} + +// These test that defaults and default resolution work cross-crate. +pub trait FooDefault { + const BAR: usize = 1; +} + +pub struct FooOverwriteDefault; + +impl FooDefault for FooOverwriteDefault { + const BAR: usize = 2; +} + +pub struct FooUseDefault; + +impl FooDefault for FooUseDefault {} + +// Test inherent impls. +pub struct InherentBar; + +impl InherentBar { + pub const BAR: usize = 3; +} diff --git a/tests/ui/associated-consts/auxiliary/empty-struct.rs b/tests/ui/associated-consts/auxiliary/empty-struct.rs new file mode 100644 index 000000000..93275e714 --- /dev/null +++ b/tests/ui/associated-consts/auxiliary/empty-struct.rs @@ -0,0 +1,9 @@ +pub struct XEmpty1 {} +pub struct XEmpty2; +pub struct XEmpty7(); + +pub enum XE { + XEmpty3 {}, + XEmpty4, + XEmpty6(), +} diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.rs b/tests/ui/associated-consts/defaults-cyclic-fail.rs new file mode 100644 index 000000000..a1c6840a0 --- /dev/null +++ b/tests/ui/associated-consts/defaults-cyclic-fail.rs @@ -0,0 +1,17 @@ +// build-fail + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + //~^ cycle detected when const-evaluating + checking `Tr::A` + + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used +impl Tr for () {} + +fn main() { + // This triggers the cycle error + assert_eq!(<() as Tr>::A, 0); +} diff --git a/tests/ui/associated-consts/defaults-cyclic-fail.stderr b/tests/ui/associated-consts/defaults-cyclic-fail.stderr new file mode 100644 index 000000000..a1483911b --- /dev/null +++ b/tests/ui/associated-consts/defaults-cyclic-fail.stderr @@ -0,0 +1,21 @@ +error[E0391]: cycle detected when const-evaluating + checking `Tr::A` + --> $DIR/defaults-cyclic-fail.rs:5:19 + | +LL | const A: u8 = Self::B; + | ^^^^^^^ + | +note: ...which requires const-evaluating + checking `Tr::B`... + --> $DIR/defaults-cyclic-fail.rs:8:19 + | +LL | const B: u8 = Self::A; + | ^^^^^^^ + = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle +note: cycle used when const-evaluating + checking `main::promoted[1]` + --> $DIR/defaults-cyclic-fail.rs:16:16 + | +LL | assert_eq!(<() as Tr>::A, 0); + | ^^^^^^^^^^^^^ + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/defaults-cyclic-pass.rs b/tests/ui/associated-consts/defaults-cyclic-pass.rs new file mode 100644 index 000000000..82105f25f --- /dev/null +++ b/tests/ui/associated-consts/defaults-cyclic-pass.rs @@ -0,0 +1,36 @@ +// run-pass + +// Cyclic assoc. const defaults don't error unless *used* +trait Tr { + const A: u8 = Self::B; + const B: u8 = Self::A; +} + +// This impl is *allowed* unless its assoc. consts are used, matching the +// behavior without defaults. +impl Tr for () {} + +// Overriding either constant breaks the cycle +impl Tr for u8 { + const A: u8 = 42; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 100; + const B: u8 = 123; +} + +fn main() { + assert_eq!(<u8 as Tr>::A, 42); + assert_eq!(<u8 as Tr>::B, 42); + + assert_eq!(<u16 as Tr>::A, 0); + assert_eq!(<u16 as Tr>::B, 0); + + assert_eq!(<u32 as Tr>::A, 100); + assert_eq!(<u32 as Tr>::B, 123); +} diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.rs b/tests/ui/associated-consts/defaults-not-assumed-fail.rs new file mode 100644 index 000000000..495dfb338 --- /dev/null +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.rs @@ -0,0 +1,44 @@ +// build-fail + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; + //~^ ERROR evaluation of `<() as Tr>::B` failed +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + assert_eq!(<() as Tr>::B, 0); // causes the error above + //~^ constant + + assert_eq!(<u8 as Tr>::A, 254); + assert_eq!(<u8 as Tr>::B, 255); + + assert_eq!(<u16 as Tr>::A, 255); + assert_eq!(<u16 as Tr>::B, 0); + + assert_eq!(<u32 as Tr>::A, 254); + assert_eq!(<u32 as Tr>::B, 0); +} diff --git a/tests/ui/associated-consts/defaults-not-assumed-fail.stderr b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr new file mode 100644 index 000000000..fb7159e40 --- /dev/null +++ b/tests/ui/associated-consts/defaults-not-assumed-fail.stderr @@ -0,0 +1,39 @@ +error[E0080]: evaluation of `<() as Tr>::B` failed + --> $DIR/defaults-not-assumed-fail.rs:8:19 + | +LL | const B: u8 = Self::A + 1; + | ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:16 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^ + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +note: erroneous constant used + --> $DIR/defaults-not-assumed-fail.rs:33:5 + | +LL | assert_eq!(<() as Tr>::B, 0); // causes the error above + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/associated-consts/defaults-not-assumed-pass.rs b/tests/ui/associated-consts/defaults-not-assumed-pass.rs new file mode 100644 index 000000000..c08e05c8a --- /dev/null +++ b/tests/ui/associated-consts/defaults-not-assumed-pass.rs @@ -0,0 +1,42 @@ +// run-pass + +trait Tr { + const A: u8 = 255; + + // This should not be a constant evaluation error (overflow). The value of + // `Self::A` must not be assumed to hold inside the trait. + const B: u8 = Self::A + 1; +} + +// An impl that doesn't override any constant will NOT cause a const eval error +// just because it's defined, but only if the bad constant is used anywhere. +// This matches the behavior without defaults. +impl Tr for () {} + +// An impl that overrides either constant with a suitable value will be fine. +impl Tr for u8 { + const A: u8 = 254; +} + +impl Tr for u16 { + const B: u8 = 0; +} + +impl Tr for u32 { + const A: u8 = 254; + const B: u8 = 0; +} + +fn main() { + assert_eq!(<() as Tr>::A, 255); + //assert_eq!(<() as Tr>::B, 0); // using this is an error + + assert_eq!(<u8 as Tr>::A, 254); + assert_eq!(<u8 as Tr>::B, 255); + + assert_eq!(<u16 as Tr>::A, 255); + assert_eq!(<u16 as Tr>::B, 0); + + assert_eq!(<u32 as Tr>::A, 254); + assert_eq!(<u32 as Tr>::B, 0); +} diff --git a/tests/ui/associated-consts/issue-102335-const.rs b/tests/ui/associated-consts/issue-102335-const.rs new file mode 100644 index 000000000..f60cb92da --- /dev/null +++ b/tests/ui/associated-consts/issue-102335-const.rs @@ -0,0 +1,12 @@ +#![feature(associated_const_equality)] + +trait T { + type A: S<C<X = 0i32> = 34>; + //~^ ERROR associated type bindings are not allowed here +} + +trait S { + const C: i32; +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-102335-const.stderr b/tests/ui/associated-consts/issue-102335-const.stderr new file mode 100644 index 000000000..531d15c59 --- /dev/null +++ b/tests/ui/associated-consts/issue-102335-const.stderr @@ -0,0 +1,9 @@ +error[E0229]: associated type bindings are not allowed here + --> $DIR/issue-102335-const.rs:4:17 + | +LL | type A: S<C<X = 0i32> = 34>; + | ^^^^^^^^ associated type not allowed here + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0229`. diff --git a/tests/ui/associated-consts/issue-105330.rs b/tests/ui/associated-consts/issue-105330.rs new file mode 100644 index 000000000..86e45f10b --- /dev/null +++ b/tests/ui/associated-consts/issue-105330.rs @@ -0,0 +1,21 @@ +pub trait TraitWAssocConst { + const A: usize; +} +pub struct Demo {} + +impl TraitWAssocConst for impl Demo { //~ ERROR E0404 + //~^ ERROR E0562 + pubconst A: str = 32; //~ ERROR expected one of +} + +fn foo<A: TraitWAssocConst<A=32>>() { //~ ERROR E0658 + foo::<Demo>()(); //~ ERROR E0271 + //~^ ERROR E0618 + //~| ERROR E0277 +} + +fn main<A: TraitWAssocConst<A=32>>() { //~ ERROR E0131 + //~^ ERROR E0658 + foo::<Demo>(); //~ ERROR E0277 + //~^ ERROR E0271 +} diff --git a/tests/ui/associated-consts/issue-105330.stderr b/tests/ui/associated-consts/issue-105330.stderr new file mode 100644 index 000000000..30c380152 --- /dev/null +++ b/tests/ui/associated-consts/issue-105330.stderr @@ -0,0 +1,113 @@ +error: expected one of `!` or `::`, found `A` + --> $DIR/issue-105330.rs:8:14 + | +LL | impl TraitWAssocConst for impl Demo { + | - while parsing this item list starting here +LL | +LL | pubconst A: str = 32; + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error[E0404]: expected trait, found struct `Demo` + --> $DIR/issue-105330.rs:6:32 + | +LL | impl TraitWAssocConst for impl Demo { + | ^^^^ not a trait + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo<A: TraitWAssocConst<A=32>>() { + | ^^^^ + | + = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-105330.rs:17:29 + | +LL | fn main<A: TraitWAssocConst<A=32>>() { + | ^^^^ + | + = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in type + --> $DIR/issue-105330.rs:6:27 + | +LL | impl TraitWAssocConst for impl Demo { + | ^^^^^^^^^ + +error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied + --> $DIR/issue-105330.rs:12:11 + | +LL | foo::<Demo>()(); + | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo` + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:11 + | +LL | fn foo<A: TraitWAssocConst<A=32>>() { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32` + --> $DIR/issue-105330.rs:12:11 + | +LL | foo::<Demo>()(); + | ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A` + | + = note: expected constant `32` + found constant `<Demo as TraitWAssocConst>::A` +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo<A: TraitWAssocConst<A=32>>() { + | ^^^^ required by this bound in `foo` + +error[E0618]: expected function, found `()` + --> $DIR/issue-105330.rs:12:5 + | +LL | fn foo<A: TraitWAssocConst<A=32>>() { + | ----------------------------------- `foo::<Demo>` defined here returns `()` +LL | foo::<Demo>()(); + | ^^^^^^^^^^^^^-- + | | + | call expression requires function + +error[E0277]: the trait bound `Demo: TraitWAssocConst` is not satisfied + --> $DIR/issue-105330.rs:19:11 + | +LL | foo::<Demo>(); + | ^^^^ the trait `TraitWAssocConst` is not implemented for `Demo` + | +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:11 + | +LL | fn foo<A: TraitWAssocConst<A=32>>() { + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` + +error[E0271]: type mismatch resolving `<Demo as TraitWAssocConst>::A == 32` + --> $DIR/issue-105330.rs:19:11 + | +LL | foo::<Demo>(); + | ^^^^ expected `32`, found `<Demo as TraitWAssocConst>::A` + | + = note: expected constant `32` + found constant `<Demo as TraitWAssocConst>::A` +note: required by a bound in `foo` + --> $DIR/issue-105330.rs:11:28 + | +LL | fn foo<A: TraitWAssocConst<A=32>>() { + | ^^^^ required by this bound in `foo` + +error[E0131]: `main` function is not allowed to have generic parameters + --> $DIR/issue-105330.rs:17:8 + | +LL | fn main<A: TraitWAssocConst<A=32>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `main` cannot have generic parameters + +error: aborting due to 11 previous errors + +Some errors have detailed explanations: E0131, E0271, E0277, E0404, E0562, E0618, E0658. +For more information about an error, try `rustc --explain E0131`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs new file mode 100644 index 000000000..0315938a7 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.rs @@ -0,0 +1,15 @@ +// Check for recursion involving references to impl-associated const. + +trait Foo { + const BAR: u32; +} + +const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + +struct GlobalImplRef; + +impl GlobalImplRef { + const BAR: u32 = IMPL_REF_BAR; //~ ERROR E0391 +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr new file mode 100644 index 000000000..be5781761 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr @@ -0,0 +1,32 @@ +error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:22 + | +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `IMPL_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:27 + | +LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR; + | ^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 + | +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5 + | +LL | const BAR: u32 = IMPL_REF_BAR; + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs new file mode 100644 index 000000000..4e89f6862 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.rs @@ -0,0 +1,17 @@ +// Check for recursion involving references to trait-associated const default. + +trait Foo { + const BAR: u32; +} + +trait FooDefault { + const BAR: u32 = DEFAULT_REF_BAR; //~ ERROR E0391 +} + +const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR; + +struct GlobalDefaultRef; + +impl FooDefault for GlobalDefaultRef {} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr new file mode 100644 index 000000000..8347b260b --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr @@ -0,0 +1,32 @@ +error[E0391]: cycle detected when elaborating drops for `FooDefault::BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:22 + | +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1 + | +LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:30 + | +LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `FooDefault::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 + | +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `FooDefault::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5 + | +LL | const BAR: u32 = DEFAULT_REF_BAR; + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `FooDefault::BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs new file mode 100644 index 000000000..68b653ff3 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.rs @@ -0,0 +1,15 @@ +// Check for recursion involving references to trait-associated const. + +trait Foo { + const BAR: u32; +} + +const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR; + +struct GlobalTraitRef; + +impl Foo for GlobalTraitRef { + const BAR: u32 = TRAIT_REF_BAR; //~ ERROR E0391 +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr new file mode 100644 index 000000000..3955a3120 --- /dev/null +++ b/tests/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr @@ -0,0 +1,32 @@ +error[E0391]: cycle detected when elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR` + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:22 + | +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^ + | +note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1 + | +LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR; + | ^^^^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:28 + | +LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR; + | ^^^^^^^^^^^^^^^^^^^^^ +note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 + | +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^^ +note: ...which requires caching mir of `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR` for CTFE... + --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5 + | +LL | const BAR: u32 = TRAIT_REF_BAR; + | ^^^^^^^^^^^^^^ + = note: ...which again requires elaborating drops for `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`, completing the cycle + = note: cycle used when running analysis passes on this crate + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0391`. diff --git a/tests/ui/associated-consts/issue-47814.rs b/tests/ui/associated-consts/issue-47814.rs new file mode 100644 index 000000000..a28b1c001 --- /dev/null +++ b/tests/ui/associated-consts/issue-47814.rs @@ -0,0 +1,14 @@ +struct ArpIPv4<'a> { + s: &'a u8 +} + +impl<'a> ArpIPv4<'a> { + const LENGTH: usize = 20; + + pub fn to_buffer() -> [u8; Self::LENGTH] { + //~^ ERROR: generic `Self` types are currently not permitted in anonymous constants + unimplemented!() + } +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-47814.stderr b/tests/ui/associated-consts/issue-47814.stderr new file mode 100644 index 000000000..2e4ddb811 --- /dev/null +++ b/tests/ui/associated-consts/issue-47814.stderr @@ -0,0 +1,14 @@ +error: generic `Self` types are currently not permitted in anonymous constants + --> $DIR/issue-47814.rs:8:32 + | +LL | pub fn to_buffer() -> [u8; Self::LENGTH] { + | ^^^^ + | +note: not a concrete type + --> $DIR/issue-47814.rs:5:10 + | +LL | impl<'a> ArpIPv4<'a> { + | ^^^^^^^^^^^ + +error: aborting due to previous error + diff --git a/tests/ui/associated-consts/issue-58022.rs b/tests/ui/associated-consts/issue-58022.rs new file mode 100644 index 000000000..2a8a1eaa6 --- /dev/null +++ b/tests/ui/associated-consts/issue-58022.rs @@ -0,0 +1,19 @@ +pub trait Foo: Sized { + const SIZE: usize; + + fn new(slice: &[u8; Foo::SIZE]) -> Self; + //~^ ERROR: E0790 +} + +pub struct Bar<T: ?Sized>(T); + +impl Bar<[u8]> { + const SIZE: usize = 32; + + fn new(slice: &[u8; Self::SIZE]) -> Self { + Foo(Box::new(*slice)) + //~^ ERROR: expected function, tuple struct or tuple variant, found trait `Foo` + } +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr new file mode 100644 index 000000000..56d85c066 --- /dev/null +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -0,0 +1,19 @@ +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-58022.rs:4:25 + | +LL | const SIZE: usize; + | ------------------ `Foo::SIZE` defined here +LL | +LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; + | ^^^^^^^^^ cannot refer to the associated constant of trait + +error[E0423]: expected function, tuple struct or tuple variant, found trait `Foo` + --> $DIR/issue-58022.rs:14:9 + | +LL | Foo(Box::new(*slice)) + | ^^^ not a function, tuple struct or tuple variant + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0423, E0790. +For more information about an error, try `rustc --explain E0423`. diff --git a/tests/ui/associated-consts/issue-63496.rs b/tests/ui/associated-consts/issue-63496.rs new file mode 100644 index 000000000..67ef4e74c --- /dev/null +++ b/tests/ui/associated-consts/issue-63496.rs @@ -0,0 +1,9 @@ +trait A { + const C: usize; + + fn f() -> ([u8; A::C], [u8; A::C]); + //~^ ERROR: E0790 + //~| ERROR: E0790 +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-63496.stderr b/tests/ui/associated-consts/issue-63496.stderr new file mode 100644 index 000000000..f2a4e01ad --- /dev/null +++ b/tests/ui/associated-consts/issue-63496.stderr @@ -0,0 +1,21 @@ +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-63496.rs:4:21 + | +LL | const C: usize; + | --------------- `A::C` defined here +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ cannot refer to the associated constant of trait + +error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type + --> $DIR/issue-63496.rs:4:33 + | +LL | const C: usize; + | --------------- `A::C` defined here +LL | +LL | fn f() -> ([u8; A::C], [u8; A::C]); + | ^^^^ cannot refer to the associated constant of trait + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0790`. diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr new file mode 100644 index 000000000..0c3581900 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.noopt.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:27:22 + | +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:35 + | +LL | const NEG_REV: i32 = T::NEG + (-i32::MIN); + | ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:32:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:36 + | +LL | const ADD_REV: i32 = T::ADD + (i32::MAX+1); + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:37:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:35 + | +LL | const DIV_REV: i32 = T::DIV + (1/0); + | ^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:42:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:35 + | +LL | const OOB_REV: i32 = T::OOB + [1][1]; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr new file mode 100644 index 000000000..0c3581900 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:27:22 + | +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:35 + | +LL | const NEG_REV: i32 = T::NEG + (-i32::MIN); + | ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:32:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:36 + | +LL | const ADD_REV: i32 = T::ADD + (i32::MAX+1); + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:37:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:35 + | +LL | const DIV_REV: i32 = T::DIV + (1/0); + | ^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:42:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:35 + | +LL | const OOB_REV: i32 = T::OOB + [1][1]; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr new file mode 100644 index 000000000..0c3581900 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.opt_with_overflow_checks.stderr @@ -0,0 +1,54 @@ +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:27:22 + | +LL | const NEG: i32 = -i32::MIN + T::NEG; + | ^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + | + = note: `#[deny(arithmetic_overflow)]` on by default + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:29:35 + | +LL | const NEG_REV: i32 = T::NEG + (-i32::MIN); + | ^^^^^^^^^^^ attempt to negate `i32::MIN`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:32:22 + | +LL | const ADD: i32 = (i32::MAX+1) + T::ADD; + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this arithmetic operation will overflow + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:34:36 + | +LL | const ADD_REV: i32 = T::ADD + (i32::MAX+1); + | ^^^^^^^^^^^^ attempt to compute `i32::MAX + 1_i32`, which would overflow + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:37:22 + | +LL | const DIV: i32 = (1/0) + T::DIV; + | ^^^^^ attempt to divide `1_i32` by zero + | + = note: `#[deny(unconditional_panic)]` on by default + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:39:35 + | +LL | const DIV_REV: i32 = T::DIV + (1/0); + | ^^^^^ attempt to divide `1_i32` by zero + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:42:22 + | +LL | const OOB: i32 = [1][1] + T::OOB; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: this operation will panic at runtime + --> $DIR/issue-69020-assoc-const-arith-overflow.rs:44:35 + | +LL | const OOB_REV: i32 = T::OOB + [1][1]; + | ^^^^^^ index out of bounds: the length is 1 but the index is 1 + +error: aborting due to 8 previous errors + diff --git a/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs new file mode 100644 index 000000000..d4af6e864 --- /dev/null +++ b/tests/ui/associated-consts/issue-69020-assoc-const-arith-overflow.rs @@ -0,0 +1,46 @@ +// revisions: noopt opt opt_with_overflow_checks +//[noopt]compile-flags: -C opt-level=0 +//[opt]compile-flags: -O +//[opt_with_overflow_checks]compile-flags: -C overflow-checks=on -O + +#![crate_type="lib"] + +pub trait Foo { + const NEG: i32; + const NEG_REV: i32; + + const ADD: i32; + const ADD_REV: i32; + + const DIV: i32; + const DIV_REV: i32; + + const OOB: i32; + const OOB_REV: i32; +} + +// These constants cannot be evaluated already (they depend on `T::N`), so they can just be linted +// like normal run-time code. But codegen works a bit different in const context, so this test +// makes sure that we still catch overflow. Also make sure we emit the same lints if we reverse the +// operands (so that the generic operand comes first). +impl<T: Foo> Foo for Vec<T> { + const NEG: i32 = -i32::MIN + T::NEG; + //~^ ERROR arithmetic operation will overflow + const NEG_REV: i32 = T::NEG + (-i32::MIN); + //~^ ERROR arithmetic operation will overflow + + const ADD: i32 = (i32::MAX+1) + T::ADD; + //~^ ERROR arithmetic operation will overflow + const ADD_REV: i32 = T::ADD + (i32::MAX+1); + //~^ ERROR arithmetic operation will overflow + + const DIV: i32 = (1/0) + T::DIV; + //~^ ERROR operation will panic + const DIV_REV: i32 = T::DIV + (1/0); + //~^ ERROR operation will panic + + const OOB: i32 = [1][1] + T::OOB; + //~^ ERROR operation will panic + const OOB_REV: i32 = T::OOB + [1][1]; + //~^ ERROR operation will panic +} diff --git a/tests/ui/associated-consts/issue-88599-ref-self.rs b/tests/ui/associated-consts/issue-88599-ref-self.rs new file mode 100644 index 000000000..f1144db44 --- /dev/null +++ b/tests/ui/associated-consts/issue-88599-ref-self.rs @@ -0,0 +1,24 @@ +// check-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +pub trait First { + const CONST: usize; +} +pub trait Second {} + +impl<'a> First for dyn Second +where + &'a Self: First, +{ + const CONST: usize = <&Self>::CONST; +} + +trait Third: First +where + [u8; Self::CONST]: +{ + const VAL: [u8; Self::CONST] = [0; Self::CONST]; +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-93775.rs b/tests/ui/associated-consts/issue-93775.rs new file mode 100644 index 000000000..7a007b732 --- /dev/null +++ b/tests/ui/associated-consts/issue-93775.rs @@ -0,0 +1,29 @@ +// build-pass +// ignore-tidy-linelength + +// Regression for #93775, needs build-pass to test it. + +#![recursion_limit = "1000"] + +use std::marker::PhantomData; + +struct Z; +struct S<T>(PhantomData<T>); + +type Nested = S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<S<Z>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>; + +trait AsNum { + const NUM: u32; +} + +impl AsNum for Z { + const NUM: u32 = 0; +} + +impl<T: AsNum> AsNum for S<T> { + const NUM: u32 = T::NUM + 1; +} + +fn main() { + let _ = Nested::NUM; +} diff --git a/tests/ui/associated-consts/issue-93835.rs b/tests/ui/associated-consts/issue-93835.rs new file mode 100644 index 000000000..b2a437fcb --- /dev/null +++ b/tests/ui/associated-consts/issue-93835.rs @@ -0,0 +1,12 @@ +#![feature(type_ascription)] + +fn e() { + type_ascribe!(p, a<p:p<e=6>>); + //~^ ERROR cannot find type `a` in this scope + //~| ERROR cannot find value + //~| ERROR associated const equality + //~| ERROR cannot find trait `p` in this scope + //~| ERROR associated type bounds +} + +fn main() {} diff --git a/tests/ui/associated-consts/issue-93835.stderr b/tests/ui/associated-consts/issue-93835.stderr new file mode 100644 index 000000000..be0573a13 --- /dev/null +++ b/tests/ui/associated-consts/issue-93835.stderr @@ -0,0 +1,40 @@ +error[E0425]: cannot find value `p` in this scope + --> $DIR/issue-93835.rs:4:19 + | +LL | type_ascribe!(p, a<p:p<e=6>>); + | ^ not found in this scope + +error[E0412]: cannot find type `a` in this scope + --> $DIR/issue-93835.rs:4:22 + | +LL | type_ascribe!(p, a<p:p<e=6>>); + | ^ not found in this scope + +error[E0405]: cannot find trait `p` in this scope + --> $DIR/issue-93835.rs:4:26 + | +LL | type_ascribe!(p, a<p:p<e=6>>); + | ^ not found in this scope + +error[E0658]: associated const equality is incomplete + --> $DIR/issue-93835.rs:4:28 + | +LL | type_ascribe!(p, a<p:p<e=6>>); + | ^^^ + | + = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information + = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable + +error[E0658]: associated type bounds are unstable + --> $DIR/issue-93835.rs:4:24 + | +LL | type_ascribe!(p, a<p:p<e=6>>); + | ^^^^^^^^ + | + = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information + = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable + +error: aborting due to 5 previous errors + +Some errors have detailed explanations: E0405, E0412, E0425, E0658. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/associated-consts/mismatched_impl_ty_1.rs b/tests/ui/associated-consts/mismatched_impl_ty_1.rs new file mode 100644 index 000000000..4dc6c2e47 --- /dev/null +++ b/tests/ui/associated-consts/mismatched_impl_ty_1.rs @@ -0,0 +1,18 @@ +// run-pass +#![feature(generic_const_exprs)] +#![allow(incomplete_features)] + +trait MyTrait { + type ArrayType; + const SIZE: usize; + const ARRAY: Self::ArrayType; +} +impl MyTrait for () { + type ArrayType = [u8; Self::SIZE]; + const SIZE: usize = 4; + const ARRAY: [u8; Self::SIZE] = [1, 2, 3, 4]; +} + +fn main() { + let _ = <() as MyTrait>::ARRAY; +} diff --git a/tests/ui/associated-consts/mismatched_impl_ty_2.rs b/tests/ui/associated-consts/mismatched_impl_ty_2.rs new file mode 100644 index 000000000..539becfdc --- /dev/null +++ b/tests/ui/associated-consts/mismatched_impl_ty_2.rs @@ -0,0 +1,11 @@ +// run-pass +trait Trait { + const ASSOC: fn(&'static u32); +} +impl Trait for () { + const ASSOC: for<'a> fn(&'a u32) = |_| (); +} + +fn main() { + let _ = <() as Trait>::ASSOC; +} diff --git a/tests/ui/associated-consts/mismatched_impl_ty_3.rs b/tests/ui/associated-consts/mismatched_impl_ty_3.rs new file mode 100644 index 000000000..17bcc8fe5 --- /dev/null +++ b/tests/ui/associated-consts/mismatched_impl_ty_3.rs @@ -0,0 +1,11 @@ +// run-pass +trait Trait { + const ASSOC: for<'a, 'b> fn(&'a u32, &'b u32); +} +impl Trait for () { + const ASSOC: for<'a> fn(&'a u32, &'a u32) = |_, _| (); +} + +fn main() { + let _ = <() as Trait>::ASSOC; +} diff --git a/tests/ui/associated-consts/shadowed-const.rs b/tests/ui/associated-consts/shadowed-const.rs new file mode 100644 index 000000000..cfdb391d3 --- /dev/null +++ b/tests/ui/associated-consts/shadowed-const.rs @@ -0,0 +1,23 @@ +// Checking that none of these ICE, which was introduced in +// https://github.com/rust-lang/rust/issues/93553 +trait Foo { + type Bar; +} + +trait Baz: Foo { + const Bar: Self::Bar; +} + +trait Baz2: Foo { + const Bar: u32; + + fn foo() -> Self::Bar; +} + +trait Baz3 { + const BAR: usize; + const QUX: Self::BAR; + //~^ ERROR found associated const +} + +fn main() {} diff --git a/tests/ui/associated-consts/shadowed-const.stderr b/tests/ui/associated-consts/shadowed-const.stderr new file mode 100644 index 000000000..fe21d2aec --- /dev/null +++ b/tests/ui/associated-consts/shadowed-const.stderr @@ -0,0 +1,8 @@ +error: found associated const `BAR` when type was expected + --> $DIR/shadowed-const.rs:19:14 + | +LL | const QUX: Self::BAR; + | ^^^^^^^^^ + +error: aborting due to previous error + |