diff options
| author | bors <bors@rust-lang.org> | 2019-10-06 16:32:46 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2019-10-06 16:32:46 +0000 |
| commit | 421bd77f42c2fe8a2596dbcc1580ec97fb89009f (patch) | |
| tree | 7c0dc2e29403ff3bc579d3d422a4495d067ca751 /src/test | |
| parent | 9203ee7b56b9963e6b95a58fb43985a3d9a637f6 (diff) | |
| parent | 47f89e7485ed7a76d8bfcbedcad07fd6b74fa927 (diff) | |
| download | rust-421bd77f42c2fe8a2596dbcc1580ec97fb89009f.tar.gz rust-421bd77f42c2fe8a2596dbcc1580ec97fb89009f.zip | |
Auto merge of #64564 - jonas-schievink:cowardly-default, r=nikomatsakis
Deny specializing items not in the parent impl Part of https://github.com/rust-lang/rust/issues/29661 (https://github.com/rust-lang/rfcs/pull/2532). At least sort of? This was discussed in https://github.com/rust-lang/rust/pull/61812#discussion_r300504114 and is needed for that PR to make progress (fixing an unsoundness). One annoyance with doing this is that it sometimes requires users to copy-paste a provided trait method into an impl just to mark it `default` (ie. there is no syntax to forward this impl method to the provided trait method). cc @Centril and @arielb1
Diffstat (limited to 'src/test')
5 files changed, 144 insertions, 3 deletions
diff --git a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs index 5cf975b5752..1e5555355c3 100644 --- a/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs +++ b/src/test/ui/specialization/auxiliary/cross_crates_defaults.rs @@ -22,7 +22,9 @@ pub trait Bar { fn bar(&self) -> i32 { 0 } } -impl<T> Bar for T {} // use the provided method +impl<T> Bar for T { + default fn bar(&self) -> i32 { 0 } +} impl Bar for i32 { fn bar(&self) -> i32 { 1 } diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs index 36cb939bc48..9546a5dd5f5 100644 --- a/src/test/ui/specialization/issue-36804.rs +++ b/src/test/ui/specialization/issue-36804.rs @@ -13,6 +13,10 @@ where fn next(&mut self) -> Option<T> { unimplemented!() } + + default fn count(self) -> usize where Self: Sized { + self.fold(0, |cnt, _| cnt + 1) + } } impl<'a, I, T: 'a> Iterator for Cloned<I> diff --git a/src/test/ui/specialization/non-defaulted-item-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs new file mode 100644 index 00000000000..403f718d7dd --- /dev/null +++ b/src/test/ui/specialization/non-defaulted-item-fail.rs @@ -0,0 +1,53 @@ +#![feature(specialization, associated_type_defaults)] + +// Test that attempting to override a non-default method or one not in the +// parent impl causes an error. + +trait Foo { + type Ty = (); + const CONST: u8 = 123; + fn foo(&self) -> bool { true } +} + +// Specialization tree for Foo: +// +// Box<T> Vec<T> +// / \ / \ +// Box<i32> Box<i64> Vec<()> Vec<bool> + +impl<T> Foo for Box<T> { + type Ty = bool; + const CONST: u8 = 0; + fn foo(&self) -> bool { false } +} + +// Allowed +impl Foo for Box<i32> {} + +// Can't override a non-`default` fn +impl Foo for Box<i64> { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + fn foo(&self) -> bool { true } +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + + +// Doesn't mention the item = provided body/value is used and the method is final. +impl<T> Foo for Vec<T> {} + +// Allowed +impl Foo for Vec<()> {} + +impl Foo for Vec<bool> { + type Ty = Vec<()>; +//~^ error: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + const CONST: u8 = 42; +//~^ error: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + fn foo(&self) -> bool { true } +//~^ error: `foo` specializes an item from a parent `impl`, but that item is not marked `default` +} + +fn main() {} diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr new file mode 100644 index 00000000000..e6c5fc1441b --- /dev/null +++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr @@ -0,0 +1,81 @@ +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:29:5 + | +LL | / impl<T> Foo for Box<T> { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:31:5 + | +LL | / impl<T> Foo for Box<T> { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:33:5 + | +LL | / impl<T> Foo for Box<T> { +LL | | type Ty = bool; +LL | | const CONST: u8 = 0; +LL | | fn foo(&self) -> bool { false } +LL | | } + | |_- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:45:5 + | +LL | impl<T> Foo for Vec<T> {} + | ------------------------- parent `impl` is here +... +LL | type Ty = Vec<()>; + | ^^^^^^^^^^^^^^^^^^ cannot specialize default item `Ty` + | + = note: to specialize, `Ty` in the parent `impl` must be marked `default` + +error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:47:5 + | +LL | impl<T> Foo for Vec<T> {} + | ------------------------- parent `impl` is here +... +LL | const CONST: u8 = 42; + | ^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `CONST` + | + = note: to specialize, `CONST` in the parent `impl` must be marked `default` + +error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default` + --> $DIR/non-defaulted-item-fail.rs:49:5 + | +LL | impl<T> Foo for Vec<T> {} + | ------------------------- parent `impl` is here +... +LL | fn foo(&self) -> bool { true } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo` + | + = note: to specialize, `foo` in the parent `impl` must be marked `default` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0520`. diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs index 5d65a0457e7..9ae3d1e9f39 100644 --- a/src/test/ui/specialization/specialization-default-methods.rs +++ b/src/test/ui/specialization/specialization-default-methods.rs @@ -55,8 +55,9 @@ trait Bar { // / \ // Vec<i32> $Vec<i64> -// use the provided method -impl<T> Bar for T {} +impl<T> Bar for T { + default fn bar(&self) -> i32 { 0 } +} impl Bar for i32 { fn bar(&self) -> i32 { 1 } |
