Add regression tests for issues
This commit is contained in:
parent
fead45815c
commit
485111c48e
14 changed files with 206 additions and 38 deletions
|
@ -6,7 +6,8 @@ trait Tr {
|
|||
const B: u8 = Self::A;
|
||||
}
|
||||
|
||||
// This impl is *allowed* unless its assoc. consts are used
|
||||
// This impl is *allowed* unless its assoc. consts are used, matching the
|
||||
// behavior without defaults.
|
||||
impl Tr for () {}
|
||||
|
||||
// Overriding either constant breaks the cycle
|
||||
|
|
|
@ -2,21 +2,16 @@
|
|||
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
// Having a cycle in assoc. type defaults is okay, as long as there's no impl
|
||||
// that retains it.
|
||||
trait Tr {
|
||||
type Item = u8;
|
||||
type Container = Vec<Self::Item>;
|
||||
type A = Self::B;
|
||||
type B = Self::A;
|
||||
}
|
||||
|
||||
impl Tr for () {}
|
||||
|
||||
impl Tr for u16 {
|
||||
type Item = u16;
|
||||
// An impl has to break the cycle to be accepted.
|
||||
impl Tr for u8 {
|
||||
type A = u8;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _container: <() as Tr>::Container = Vec::<u8>::new();
|
||||
let _item: <() as Tr>::Item = 0u8;
|
||||
|
||||
let _container: <u16 as Tr>::Container = Vec::<u16>::new();
|
||||
let _item: <u16 as Tr>::Item = 0u16;
|
||||
}
|
||||
fn main() {}
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
trait Tr {
|
||||
type Item = u8;
|
||||
type Container = Vec<Self::Item>;
|
||||
}
|
||||
|
||||
impl Tr for () {}
|
||||
|
||||
impl Tr for u16 {
|
||||
type Item = u16;
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let _container: <() as Tr>::Container = Vec::<u8>::new();
|
||||
let _item: <() as Tr>::Item = 0u8;
|
||||
|
||||
let _container: <u16 as Tr>::Container = Vec::<u16>::new();
|
||||
let _item: <u16 as Tr>::Item = 0u16;
|
||||
}
|
|
@ -3,6 +3,9 @@
|
|||
//! The old implementation of defaults did not check whether the provided
|
||||
//! default actually fulfills all bounds on the assoc. type, leading to
|
||||
//! unsoundness, demonstrated here as a use-after-free.
|
||||
//!
|
||||
//! Note that the underlying cause of this is still not yet fixed.
|
||||
//! See: https://github.com/rust-lang/rust/issues/33017
|
||||
|
||||
// compile-fail
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-1.rs:20:18
|
||||
--> $DIR/defaults-unsound-62211-1.rs:23:18
|
||||
|
|
||||
LL | type Output: Copy
|
||||
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: std::marker::Copy` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-1.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: cannot add-assign `&'static str` to `Self`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:24:7
|
||||
--> $DIR/defaults-unsound-62211-1.rs:27:7
|
||||
|
|
||||
LL | + AddAssign<&'static str>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
|
||||
|
@ -20,26 +20,26 @@ LL | + AddAssign<&'static str>
|
|||
= help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
|
||||
= help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-1.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-1.rs:22:7
|
||||
--> $DIR/defaults-unsound-62211-1.rs:25:7
|
||||
|
|
||||
LL | + Deref<Target = str>
|
||||
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: std::ops::Deref` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-1.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `Self` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:27:7
|
||||
--> $DIR/defaults-unsound-62211-1.rs:30:7
|
||||
|
|
||||
LL | + Display = Self;
|
||||
| ^^^^^^^ `Self` cannot be formatted with the default formatter
|
||||
|
@ -48,13 +48,13 @@ LL | + Display = Self;
|
|||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
= help: consider adding a `where Self: std::fmt::Display` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-1.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `T` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-1.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
|
||||
|
@ -64,7 +64,7 @@ LL | impl<T> UncheckedCopy for T {}
|
|||
= help: consider adding a `where T: std::fmt::Display` bound
|
||||
|
||||
error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-1.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-1.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
|
||||
|
@ -72,7 +72,7 @@ LL | impl<T> UncheckedCopy for T {}
|
|||
= help: consider adding a `where T: std::ops::Deref` bound
|
||||
|
||||
error[E0277]: cannot add-assign `&'static str` to `T`
|
||||
--> $DIR/defaults-unsound-62211-1.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-1.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ no implementation for `T += &'static str`
|
||||
|
@ -81,7 +81,7 @@ LL | impl<T> UncheckedCopy for T {}
|
|||
= help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-1.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-1.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
|
@ -3,6 +3,9 @@
|
|||
//! The old implementation of defaults did not check whether the provided
|
||||
//! default actually fulfills all bounds on the assoc. type, leading to
|
||||
//! unsoundness and ICEs, the latter being demonstrated here.
|
||||
//!
|
||||
//! Note that the underlying cause of this is still not yet fixed.
|
||||
//! See: https://github.com/rust-lang/rust/issues/33017
|
||||
|
||||
// compile-fail
|
||||
|
||||
|
|
|
@ -1,18 +1,18 @@
|
|||
error[E0277]: the trait bound `Self: std::marker::Copy` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-2.rs:20:18
|
||||
--> $DIR/defaults-unsound-62211-2.rs:23:18
|
||||
|
|
||||
LL | type Output: Copy
|
||||
| ^^^^ the trait `std::marker::Copy` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: std::marker::Copy` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-2.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: cannot add-assign `&'static str` to `Self`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:24:7
|
||||
--> $DIR/defaults-unsound-62211-2.rs:27:7
|
||||
|
|
||||
LL | + AddAssign<&'static str>
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `Self += &'static str`
|
||||
|
@ -20,26 +20,26 @@ LL | + AddAssign<&'static str>
|
|||
= help: the trait `std::ops::AddAssign<&'static str>` is not implemented for `Self`
|
||||
= help: consider adding a `where Self: std::ops::AddAssign<&'static str>` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-2.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `Self: std::ops::Deref` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-2.rs:22:7
|
||||
--> $DIR/defaults-unsound-62211-2.rs:25:7
|
||||
|
|
||||
LL | + Deref<Target = str>
|
||||
| ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `Self`
|
||||
|
|
||||
= help: consider adding a `where Self: std::ops::Deref` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-2.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `Self` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:27:7
|
||||
--> $DIR/defaults-unsound-62211-2.rs:30:7
|
||||
|
|
||||
LL | + Display = Self;
|
||||
| ^^^^^^^ `Self` cannot be formatted with the default formatter
|
||||
|
@ -48,13 +48,13 @@ LL | + Display = Self;
|
|||
= note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
|
||||
= help: consider adding a `where Self: std::fmt::Display` bound
|
||||
note: required by `UncheckedCopy`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:17:1
|
||||
--> $DIR/defaults-unsound-62211-2.rs:20:1
|
||||
|
|
||||
LL | trait UncheckedCopy: Sized {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: `T` doesn't implement `std::fmt::Display`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-2.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
|
||||
|
@ -64,7 +64,7 @@ LL | impl<T> UncheckedCopy for T {}
|
|||
= help: consider adding a `where T: std::fmt::Display` bound
|
||||
|
||||
error[E0277]: the trait bound `T: std::ops::Deref` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-2.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-2.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ the trait `std::ops::Deref` is not implemented for `T`
|
||||
|
@ -72,7 +72,7 @@ LL | impl<T> UncheckedCopy for T {}
|
|||
= help: consider adding a `where T: std::ops::Deref` bound
|
||||
|
||||
error[E0277]: cannot add-assign `&'static str` to `T`
|
||||
--> $DIR/defaults-unsound-62211-2.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-2.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ no implementation for `T += &'static str`
|
||||
|
@ -81,7 +81,7 @@ LL | impl<T> UncheckedCopy for T {}
|
|||
= help: consider adding a `where T: std::ops::AddAssign<&'static str>` bound
|
||||
|
||||
error[E0277]: the trait bound `T: std::marker::Copy` is not satisfied
|
||||
--> $DIR/defaults-unsound-62211-2.rs:40:9
|
||||
--> $DIR/defaults-unsound-62211-2.rs:43:9
|
||||
|
|
||||
LL | impl<T> UncheckedCopy for T {}
|
||||
| ^^^^^^^^^^^^^ the trait `std::marker::Copy` is not implemented for `T`
|
||||
|
|
29
src/test/ui/associated-types/issue-32350.rs
Normal file
29
src/test/ui/associated-types/issue-32350.rs
Normal file
|
@ -0,0 +1,29 @@
|
|||
// check-pass
|
||||
|
||||
// This is another instance of the "normalizations don't work" issue with
|
||||
// defaulted associated types.
|
||||
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
pub trait Emitter<'a> {
|
||||
type Ctxt: 'a;
|
||||
type CtxtBrw: 'a = &'a Self::Ctxt;
|
||||
|
||||
fn get_cx(&'a self) -> Self::CtxtBrw;
|
||||
}
|
||||
|
||||
struct MyCtxt;
|
||||
|
||||
struct MyEmitter {
|
||||
ctxt: MyCtxt
|
||||
}
|
||||
|
||||
impl <'a> Emitter<'a> for MyEmitter {
|
||||
type Ctxt = MyCtxt;
|
||||
|
||||
fn get_cx(&'a self) -> &'a MyCtxt {
|
||||
&self.ctxt
|
||||
}
|
||||
}
|
||||
|
||||
fn main() {}
|
23
src/test/ui/associated-types/issue-41868.rs
Normal file
23
src/test/ui/associated-types/issue-41868.rs
Normal file
|
@ -0,0 +1,23 @@
|
|||
// check-pass
|
||||
|
||||
// Defaulted assoc. types should normalize properly in impls that don't
|
||||
// override them.
|
||||
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub trait CanDecode: Sized {
|
||||
type Output = Self;
|
||||
fn read(rdr: &mut Foo) -> Option<Self::Output>;
|
||||
}
|
||||
|
||||
impl CanDecode for u8 {
|
||||
fn read(rdr: &mut Foo) -> Option<Self::Output> { Some(42) }
|
||||
}
|
||||
|
||||
impl CanDecode for u16 {
|
||||
fn read(rdr: &mut Foo) -> Option<u16> { Some(17) }
|
||||
}
|
||||
|
||||
fn main() {}
|
15
src/test/ui/associated-types/issue-43924.rs
Normal file
15
src/test/ui/associated-types/issue-43924.rs
Normal file
|
@ -0,0 +1,15 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
|
||||
// This used to cause an ICE because assoc. type defaults weren't properly
|
||||
// type-checked.
|
||||
|
||||
trait Foo<T: Default + ToString> {
|
||||
type Out: Default + ToString + ?Sized = dyn ToString; //~ error: not satisfied
|
||||
}
|
||||
|
||||
impl Foo<u32> for () {} //~ error: not satisfied
|
||||
impl Foo<u64> for () {} //~ error: not satisfied
|
||||
|
||||
fn main() {
|
||||
assert_eq!(<() as Foo<u32>>::Out::default().to_string(), "false");
|
||||
}
|
27
src/test/ui/associated-types/issue-43924.stderr
Normal file
27
src/test/ui/associated-types/issue-43924.stderr
Normal file
|
@ -0,0 +1,27 @@
|
|||
error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
|
||||
--> $DIR/issue-43924.rs:7:15
|
||||
|
|
||||
LL | type Out: Default + ToString + ?Sized = dyn ToString;
|
||||
| ^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
|
||||
|
|
||||
note: required by `Foo`
|
||||
--> $DIR/issue-43924.rs:6:1
|
||||
|
|
||||
LL | trait Foo<T: Default + ToString> {
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
|
||||
--> $DIR/issue-43924.rs:10:6
|
||||
|
|
||||
LL | impl Foo<u32> for () {}
|
||||
| ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
|
||||
|
||||
error[E0277]: the trait bound `(dyn std::string::ToString + 'static): std::default::Default` is not satisfied
|
||||
--> $DIR/issue-43924.rs:11:6
|
||||
|
|
||||
LL | impl Foo<u64> for () {}
|
||||
| ^^^^^^^^ the trait `std::default::Default` is not implemented for `(dyn std::string::ToString + 'static)`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0277`.
|
16
src/test/ui/associated-types/issue-47385.rs
Normal file
16
src/test/ui/associated-types/issue-47385.rs
Normal file
|
@ -0,0 +1,16 @@
|
|||
// check-pass
|
||||
|
||||
#![feature(associated_type_defaults)]
|
||||
|
||||
pub struct Foo;
|
||||
|
||||
pub trait Bar: From<<Self as Bar>::Input> {
|
||||
type Input = Self;
|
||||
}
|
||||
|
||||
impl Bar for Foo {
|
||||
// Will compile with explicit type:
|
||||
// type Input = Self;
|
||||
}
|
||||
|
||||
fn main() {}
|
11
src/test/ui/associated-types/issue-63593.rs
Normal file
11
src/test/ui/associated-types/issue-63593.rs
Normal file
|
@ -0,0 +1,11 @@
|
|||
#![feature(associated_type_defaults)]
|
||||
|
||||
// Tests that `Self` is not assumed to implement `Sized` when used as an
|
||||
// associated type default.
|
||||
|
||||
trait Inner<S> {}
|
||||
|
||||
trait MyTrait {
|
||||
type This = Self; //~ error: size for values of type `Self` cannot be known
|
||||
fn something<I: Inner<Self::This>>(i: I);
|
||||
}
|
23
src/test/ui/associated-types/issue-63593.stderr
Normal file
23
src/test/ui/associated-types/issue-63593.stderr
Normal file
|
@ -0,0 +1,23 @@
|
|||
error[E0601]: `main` function not found in crate `issue_63593`
|
||||
|
|
||||
= note: consider adding a `main` function to `$DIR/issue-63593.rs`
|
||||
|
||||
error[E0277]: the size for values of type `Self` cannot be known at compilation time
|
||||
--> $DIR/issue-63593.rs:9:5
|
||||
|
|
||||
LL | type This = Self;
|
||||
| ^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
|
||||
|
|
||||
= help: the trait `std::marker::Sized` is not implemented for `Self`
|
||||
= note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
|
||||
= help: consider adding a `where Self: std::marker::Sized` bound
|
||||
note: required by `MyTrait`
|
||||
--> $DIR/issue-63593.rs:8:1
|
||||
|
|
||||
LL | trait MyTrait {
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0277, E0601.
|
||||
For more information about an error, try `rustc --explain E0277`.
|
Loading…
Add table
Add a link
Reference in a new issue