about summary refs log tree commit diff
diff options
context:
space:
mode:
authorYuki Okushi <jtitor@2k36.org>2021-04-28 16:59:08 +0900
committerGitHub <noreply@github.com>2021-04-28 16:59:08 +0900
commit35eac429f6c80d41e5a9f3995ca087ac28ab7d71 (patch)
tree0326c135c1ab7fc481e09527ca6959bd1b66cfb2
parent54ad5cb8f493a9233c70d6bffcc2f662ad2231cc (diff)
parent857cb4de20160ed8a4931a87ee1112aeb8c0d97e (diff)
Rollup merge of #84622 - jackh726:gats-trait-object, r=nikomatsakis
Make traits with GATs not object safe

Closes #81823

r? `@nikomatsakis`
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/object_safety.rs8
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/confirmation.rs7
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.rs3
-rw-r--r--src/test/ui/generic-associated-types/gat-in-trait-path.stderr20
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.rs3
-rw-r--r--src/test/ui/generic-associated-types/issue-67510-pass.stderr20
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.rs2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.stderr37
-rw-r--r--src/test/ui/generic-associated-types/issue-78671.rs1
-rw-r--r--src/test/ui/generic-associated-types/issue-78671.stderr20
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.rs3
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.stderr38
-rw-r--r--src/test/ui/generic-associated-types/trait-objects.rs16
-rw-r--r--src/test/ui/generic-associated-types/trait-objects.stderr18
15 files changed, 179 insertions, 25 deletions
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 00dec3b355f..c9b73c68209 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -670,6 +670,9 @@ pub enum ObjectSafetyViolation {
 
     /// Associated const.
     AssocConst(Symbol, Span),
+
+    /// GAT
+    GAT(Symbol, Span),
 }
 
 impl ObjectSafetyViolation {
@@ -715,6 +718,9 @@ impl ObjectSafetyViolation {
                 format!("it contains associated `const` `{}`", name).into()
             }
             ObjectSafetyViolation::AssocConst(..) => "it contains this associated `const`".into(),
+            ObjectSafetyViolation::GAT(name, _) => {
+                format!("it contains the generic associated type `{}`", name).into()
+            }
         }
     }
 
@@ -773,6 +779,7 @@ impl ObjectSafetyViolation {
                 );
             }
             ObjectSafetyViolation::AssocConst(name, _)
+            | ObjectSafetyViolation::GAT(name, _)
             | ObjectSafetyViolation::Method(name, ..) => {
                 err.help(&format!("consider moving `{}` to another trait", name));
             }
@@ -786,6 +793,7 @@ impl ObjectSafetyViolation {
             ObjectSafetyViolation::SupertraitSelf(spans)
             | ObjectSafetyViolation::SizedSelf(spans) => spans.clone(),
             ObjectSafetyViolation::AssocConst(_, span)
+            | ObjectSafetyViolation::GAT(_, span)
             | ObjectSafetyViolation::Method(_, _, span)
                 if *span != DUMMY_SP =>
             {
diff --git a/compiler/rustc_trait_selection/src/traits/object_safety.rs b/compiler/rustc_trait_selection/src/traits/object_safety.rs
index ac5ec24eeee..d5e1bd3f9ea 100644
--- a/compiler/rustc_trait_selection/src/traits/object_safety.rs
+++ b/compiler/rustc_trait_selection/src/traits/object_safety.rs
@@ -132,6 +132,14 @@ fn object_safety_violations_for_trait(
             .map(|item| ObjectSafetyViolation::AssocConst(item.ident.name, item.ident.span)),
     );
 
+    violations.extend(
+        tcx.associated_items(trait_def_id)
+            .in_definition_order()
+            .filter(|item| item.kind == ty::AssocKind::Type)
+            .filter(|item| !tcx.generics_of(item.def_id).params.is_empty())
+            .map(|item| ObjectSafetyViolation::GAT(item.ident.name, item.ident.span)),
+    );
+
     debug!(
         "object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
         trait_def_id, violations
diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
index 31685a012ca..e338a21b603 100644
--- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs
@@ -462,12 +462,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         for assoc_type in assoc_types {
             if !tcx.generics_of(assoc_type).params.is_empty() {
-                // FIXME(generic_associated_types) generate placeholders to
-                // extend the trait substs.
-                tcx.sess.span_fatal(
+                tcx.sess.delay_span_bug(
                     obligation.cause.span,
-                    "generic associated types in trait objects are not supported yet",
+                    "GATs in trait object shouldn't have been considered",
                 );
+                return Err(SelectionError::Unimplemented);
             }
             // This maybe belongs in wf, but that can't (doesn't) handle
             // higher-ranked things.
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.rs b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
index 2dbd1840dec..6527eb47504 100644
--- a/src/test/ui/generic-associated-types/gat-in-trait-path.rs
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(generic_associated_types)]
   //~^ WARNING: the feature `generic_associated_types` is incomplete
 #![feature(associated_type_defaults)]
@@ -22,6 +20,7 @@ impl<T> Foo for Fooer<T> {
 }
 
 fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
+//~^ the trait `Foo` cannot be made into an object
 
 
 fn main() {
diff --git a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
index f3769827f04..49dfce8b4bd 100644
--- a/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
+++ b/src/test/ui/generic-associated-types/gat-in-trait-path.stderr
@@ -1,5 +1,5 @@
 warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/gat-in-trait-path.rs:3:12
+  --> $DIR/gat-in-trait-path.rs:1:12
    |
 LL | #![feature(generic_associated_types)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,5 +7,21 @@ LL | #![feature(generic_associated_types)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
 
-warning: 1 warning emitted
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/gat-in-trait-path.rs:22:13
+   |
+LL | fn f(_arg : Box<dyn for<'a> Foo<A<'a> = &'a ()>>) {}
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+   = help: consider moving `A` to another trait
+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/gat-in-trait-path.rs:6:10
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     type A<'a> where Self: 'a;
+   |          ^ ...because it contains the generic associated type `A`
+
+error: aborting due to previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.rs b/src/test/ui/generic-associated-types/issue-67510-pass.rs
index ff38b3e93eb..6ee865072ae 100644
--- a/src/test/ui/generic-associated-types/issue-67510-pass.rs
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.rs
@@ -1,5 +1,3 @@
-// check-pass
-
 #![feature(generic_associated_types)]
   //~^ WARNING: the feature `generic_associated_types` is incomplete
 
@@ -8,5 +6,6 @@ trait X {
 }
 
 fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
+//~^ ERROR the trait `X` cannot be made into an object
 
 fn main() {}
diff --git a/src/test/ui/generic-associated-types/issue-67510-pass.stderr b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
index 0fbf704df76..65998afa7f9 100644
--- a/src/test/ui/generic-associated-types/issue-67510-pass.stderr
+++ b/src/test/ui/generic-associated-types/issue-67510-pass.stderr
@@ -1,5 +1,5 @@
 warning: the feature `generic_associated_types` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/issue-67510-pass.rs:3:12
+  --> $DIR/issue-67510-pass.rs:1:12
    |
 LL | #![feature(generic_associated_types)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
@@ -7,5 +7,21 @@ LL | #![feature(generic_associated_types)]
    = note: `#[warn(incomplete_features)]` on by default
    = note: see issue #44265 <https://github.com/rust-lang/rust/issues/44265> for more information
 
-warning: 1 warning emitted
+error[E0038]: the trait `X` cannot be made into an object
+  --> $DIR/issue-67510-pass.rs:8:19
+   |
+LL | fn _func1<'a>(_x: Box<dyn X<Y<'a>=&'a ()>>) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^ `X` cannot be made into an object
+   |
+   = help: consider moving `Y` to another trait
+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/issue-67510-pass.rs:5:10
+   |
+LL | trait X {
+   |       - this trait cannot be made into an object...
+LL |     type Y<'a>;
+   |          ^ ...because it contains the generic associated type `Y`
+
+error: aborting due to previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-76535.rs b/src/test/ui/generic-associated-types/issue-76535.rs
index 5e73a882986..9643c82db77 100644
--- a/src/test/ui/generic-associated-types/issue-76535.rs
+++ b/src/test/ui/generic-associated-types/issue-76535.rs
@@ -36,4 +36,6 @@ impl SuperTrait for SuperStruct {
 
 fn main() {
     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+    //~^ ERROR the trait `SuperTrait` cannot be made into an object
+    //~^^ ERROR the trait `SuperTrait` cannot be made into an object
 }
diff --git a/src/test/ui/generic-associated-types/issue-76535.stderr b/src/test/ui/generic-associated-types/issue-76535.stderr
index 17661e0d90a..d31560f12f0 100644
--- a/src/test/ui/generic-associated-types/issue-76535.stderr
+++ b/src/test/ui/generic-associated-types/issue-76535.stderr
@@ -23,6 +23,39 @@ help: use angle brackets to add missing lifetime argument
 LL |     type SubType<'a><'a>: SubTrait;
    |                 ^^^^
 
-error: aborting due to previous error; 1 warning emitted
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:38:14
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+   = help: consider moving `SubType` to another trait
+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/issue-76535.rs:7:10
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+LL |     type SubType<'a>: SubTrait;
+   |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+
+error[E0038]: the trait `SuperTrait` cannot be made into an object
+  --> $DIR/issue-76535.rs:38:57
+   |
+LL |     let sub: Box<dyn SuperTrait<SubType = SubStruct>> = Box::new(SuperStruct::new(0));
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `SuperTrait` cannot be made into an object
+   |
+   = help: consider moving `SubType` to another trait
+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/issue-76535.rs:7:10
+   |
+LL | pub trait SuperTrait {
+   |           ---------- this trait cannot be made into an object...
+LL |     type SubType<'a>: SubTrait;
+   |          ^^^^^^^ ...because it contains the generic associated type `SubType`
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
+   = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
+
+error: aborting due to 3 previous errors; 1 warning emitted
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-78671.rs b/src/test/ui/generic-associated-types/issue-78671.rs
index 1b02aac8bcb..4e47d3c6655 100644
--- a/src/test/ui/generic-associated-types/issue-78671.rs
+++ b/src/test/ui/generic-associated-types/issue-78671.rs
@@ -7,6 +7,7 @@ trait CollectionFamily {
 }
 fn floatify() {
     Box::new(Family) as &dyn CollectionFamily<Member=usize>
+    //~^ the trait `CollectionFamily` cannot be made into an object
 }
 
 struct Family;
diff --git a/src/test/ui/generic-associated-types/issue-78671.stderr b/src/test/ui/generic-associated-types/issue-78671.stderr
index 7a9aced5bea..c9febfb59af 100644
--- a/src/test/ui/generic-associated-types/issue-78671.stderr
+++ b/src/test/ui/generic-associated-types/issue-78671.stderr
@@ -14,6 +14,22 @@ help: use angle brackets to add missing type argument
 LL |     type Member<T><T>;
    |                ^^^
 
-error: aborting due to previous error
+error[E0038]: the trait `CollectionFamily` cannot be made into an object
+  --> $DIR/issue-78671.rs:9:25
+   |
+LL |     Box::new(Family) as &dyn CollectionFamily<Member=usize>
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `CollectionFamily` cannot be made into an object
+   |
+   = help: consider moving `Member` to another trait
+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/issue-78671.rs:5:10
+   |
+LL | trait CollectionFamily {
+   |       ---------------- this trait cannot be made into an object...
+LL |     type Member<T>;
+   |          ^^^^^^ ...because it contains the generic associated type `Member`
+
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/issue-79422.rs b/src/test/ui/generic-associated-types/issue-79422.rs
index aeb33ca5464..b2ba3c24abb 100644
--- a/src/test/ui/generic-associated-types/issue-79422.rs
+++ b/src/test/ui/generic-associated-types/issue-79422.rs
@@ -42,5 +42,6 @@ impl<K, V: Default> MapLike<K, V> for Source {
 fn main() {
     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
-    //~^^ ERROR type mismatch resolving
+    //~^^ the trait `MapLike` cannot be made into an object
+    //~^^ the trait `MapLike` cannot be made into an object
 }
diff --git a/src/test/ui/generic-associated-types/issue-79422.stderr b/src/test/ui/generic-associated-types/issue-79422.stderr
index a119bff03e2..4973ae19729 100644
--- a/src/test/ui/generic-associated-types/issue-79422.stderr
+++ b/src/test/ui/generic-associated-types/issue-79422.stderr
@@ -14,17 +14,39 @@ help: use angle brackets to add missing lifetime argument
 LL |     type VRefCont<'a><'a>: RefCont<'a, V>;
    |                  ^^^^
 
-error[E0271]: type mismatch resolving `<BTreeMap<u8, u8> as MapLike<u8, u8>>::VRefCont<'static> == (dyn RefCont<'_, u8> + 'static)`
+error[E0038]: the trait `MapLike` cannot be made into an object
+  --> $DIR/issue-79422.rs:44:12
+   |
+LL |         as Box<dyn MapLike<u8, u8, VRefCont = dyn RefCont<'_, u8>>>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+   = help: consider moving `VRefCont` to another trait
+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/issue-79422.rs:21:10
+   |
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+LL |     type VRefCont<'a>: RefCont<'a, V>;
+   |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+
+error[E0038]: the trait `MapLike` cannot be made into an object
   --> $DIR/issue-79422.rs:43:13
    |
 LL |     let m = Box::new(std::collections::BTreeMap::<u8, u8>::new())
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected trait object `dyn RefCont`, found reference
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `MapLike` cannot be made into an object
+   |
+   = help: consider moving `VRefCont` to another trait
+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/issue-79422.rs:21:10
    |
-   = note: expected trait object `(dyn RefCont<'_, u8> + 'static)`
-                 found reference `&'static u8`
-   = note: required for the cast to the object type `dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>`
+LL | trait MapLike<K, V> {
+   |       ------- this trait cannot be made into an object...
+LL |     type VRefCont<'a>: RefCont<'a, V>;
+   |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
+   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
+   = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0107, E0271.
-For more information about an error, try `rustc --explain E0107`.
+Some errors have detailed explanations: E0038, E0107.
+For more information about an error, try `rustc --explain E0038`.
diff --git a/src/test/ui/generic-associated-types/trait-objects.rs b/src/test/ui/generic-associated-types/trait-objects.rs
new file mode 100644
index 00000000000..997a550b0ef
--- /dev/null
+++ b/src/test/ui/generic-associated-types/trait-objects.rs
@@ -0,0 +1,16 @@
+#![feature(generic_associated_types)]
+#![allow(incomplete_features)]
+
+trait StreamingIterator {
+    type Item<'a> where Self: 'a;
+    fn size_hint(&self) -> (usize, Option<usize>);
+    // Uncommenting makes `StreamingIterator` not object safe
+//    fn next(&mut self) -> Self::Item<'_>;
+}
+
+fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
+    //~^ the trait `StreamingIterator` cannot be made into an object
+    x.size_hint().0
+}
+
+fn main() {}
diff --git a/src/test/ui/generic-associated-types/trait-objects.stderr b/src/test/ui/generic-associated-types/trait-objects.stderr
new file mode 100644
index 00000000000..a8f1768ba26
--- /dev/null
+++ b/src/test/ui/generic-associated-types/trait-objects.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `StreamingIterator` cannot be made into an object
+  --> $DIR/trait-objects.rs:11:16
+   |
+LL | fn min_size(x: &mut dyn for<'a> StreamingIterator<Item<'a> = &'a i32>) -> usize {
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `StreamingIterator` cannot be made into an object
+   |
+   = help: consider moving `Item` to another trait
+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/trait-objects.rs:5:10
+   |
+LL | trait StreamingIterator {
+   |       ----------------- this trait cannot be made into an object...
+LL |     type Item<'a> where Self: 'a;
+   |          ^^^^ ...because it contains the generic associated type `Item`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.