summaryrefslogtreecommitdiffstats
path: root/src/test/ui/associated-types/defaults-specialization.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/test/ui/associated-types/defaults-specialization.rs')
-rw-r--r--src/test/ui/associated-types/defaults-specialization.rs96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs
new file mode 100644
index 000000000..553705b2a
--- /dev/null
+++ b/src/test/ui/associated-types/defaults-specialization.rs
@@ -0,0 +1,96 @@
+//! Tests the interaction of associated type defaults and specialization.
+
+#![feature(associated_type_defaults, specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Tr {
+ type Ty = u8;
+
+ fn make() -> Self::Ty {
+ 0u8
+ //~^ error: mismatched types
+ }
+}
+
+struct A<T>(T);
+// In a `default impl`, assoc. types are defaulted as well,
+// so their values can't be assumed.
+default impl<T> Tr for A<T> {
+ fn make() -> u8 { 0 }
+ //~^ ERROR method `make` has an incompatible type for trait
+}
+
+struct A2<T>(T);
+// ...same, but in the method body
+default impl<T> Tr for A2<T> {
+ fn make() -> Self::Ty { 0u8 }
+ //~^ ERROR mismatched types
+}
+
+struct B<T>(T);
+// Explicitly defaulting the type does the same.
+impl<T> Tr for B<T> {
+ default type Ty = bool;
+
+ fn make() -> bool { true }
+ //~^ ERROR method `make` has an incompatible type for trait
+}
+
+struct B2<T>(T);
+// ...same, but in the method body
+impl<T> Tr for B2<T> {
+ default type Ty = bool;
+
+ fn make() -> Self::Ty { true }
+ //~^ ERROR mismatched types
+}
+
+struct C<T>(T);
+// Only the method is defaulted, so this is fine.
+impl<T> Tr for C<T> {
+ type Ty = bool;
+
+ default fn make() -> bool { true }
+}
+
+// Defaulted method *can* assume the type, if the default is kept.
+struct D<T>(T);
+impl<T> Tr for D<T> {
+ default fn make() -> u8 { 0 }
+}
+
+impl Tr for D<bool> {
+ fn make() -> u8 { 255 }
+}
+
+struct E<T>(T);
+impl<T> Tr for E<T> {
+ default type Ty = bool;
+ default fn make() -> Self::Ty { panic!(); }
+}
+
+// This impl specializes and sets `Ty`, it can rely on `Ty=String`.
+impl Tr for E<bool> {
+ type Ty = String;
+
+ fn make() -> String { String::new() }
+}
+
+fn main() {
+ // Test that we can assume the right set of assoc. types from outside the impl
+
+ // This is a `default impl`, which does *not* mean that `A`/`A2` actually implement the trait.
+ // cf. https://github.com/rust-lang/rust/issues/48515
+ //let _: <A<()> as Tr>::Ty = 0u8;
+ //let _: <A2<()> as Tr>::Ty = 0u8;
+
+ let _: <B<()> as Tr>::Ty = 0u8; //~ error: mismatched types
+ let _: <B<()> as Tr>::Ty = true; //~ error: mismatched types
+ let _: <B2<()> as Tr>::Ty = 0u8; //~ error: mismatched types
+ let _: <B2<()> as Tr>::Ty = true; //~ error: mismatched types
+
+ let _: <C<()> as Tr>::Ty = true;
+
+ let _: <D<()> as Tr>::Ty = 0u8;
+ let _: <D<bool> as Tr>::Ty = 0u8;
+}