about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthew Jasper <mjjasper1@gmail.com>2019-12-26 23:41:32 +0000
committerMatthew Jasper <mjjasper1@gmail.com>2020-02-14 20:12:46 +0000
commit7f41cf4cef551d887de539842d11945b6bfaa8b6 (patch)
tree2f5cda4c006088e01d4563cf9e69b63fbcfbc1c4
parent033bd8c7af79d362b4e861543b63991e7300948f (diff)
downloadrust-7f41cf4cef551d887de539842d11945b6bfaa8b6.tar.gz
rust-7f41cf4cef551d887de539842d11945b6bfaa8b6.zip
Check associated opaque types don't use unconstrained lifetimes
-rw-r--r--src/librustc_typeck/impl_wf_check.rs18
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-const.rs12
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs26
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr9
-rw-r--r--src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs6
5 files changed, 57 insertions, 14 deletions
diff --git a/src/librustc_typeck/impl_wf_check.rs b/src/librustc_typeck/impl_wf_check.rs
index e9c18b59da9..0b4b8a49054 100644
--- a/src/librustc_typeck/impl_wf_check.rs
+++ b/src/librustc_typeck/impl_wf_check.rs
@@ -120,11 +120,23 @@ fn enforce_impl_params_are_constrained(
     let lifetimes_in_associated_types: FxHashSet<_> = impl_item_refs
         .iter()
         .map(|item_ref| tcx.hir().local_def_id(item_ref.id.hir_id))
-        .filter(|&def_id| {
+        .flat_map(|def_id| {
             let item = tcx.associated_item(def_id);
-            item.kind == ty::AssocKind::Type && item.defaultness.has_value()
+            match item.kind {
+                ty::AssocKind::Type => {
+                    if item.defaultness.has_value() {
+                        cgp::parameters_for(&tcx.type_of(def_id), true)
+                    } else {
+                        Vec::new()
+                    }
+                }
+                ty::AssocKind::OpaqueTy => {
+                    let predicates = tcx.predicates_of(def_id).instantiate_identity(tcx);
+                    cgp::parameters_for(&predicates, true)
+                }
+                ty::AssocKind::Method | ty::AssocKind::Const => Vec::new(),
+            }
         })
-        .flat_map(|def_id| cgp::parameters_for(&tcx.type_of(def_id), true))
         .collect();
 
     for param in &impl_generics.params {
diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs
index 5db677d82e2..2907c21c620 100644
--- a/src/test/ui/type-alias-impl-trait/assoc-type-const.rs
+++ b/src/test/ui/type-alias-impl-trait/assoc-type-const.rs
@@ -6,7 +6,7 @@
 #![feature(const_generics)]
 //~^ WARN the feature `const_generics` is incomplete and may cause the compiler to crash
 
-trait UnwrapItemsExt<const C: usize> {
+trait UnwrapItemsExt<'a, const C: usize> {
     type Iter;
     fn unwrap_items(self) -> Self::Iter;
 }
@@ -18,18 +18,16 @@ trait MyTrait<'a, const C: usize> {
     const MY_CONST: usize;
 }
 
-impl<'a, const C: usize> MyTrait<'a, {C}> for MyStruct<{C}> {
+impl<'a, const C: usize> MyTrait<'a, { C }> for MyStruct<{ C }> {
     type MyItem = u8;
     const MY_CONST: usize = C;
 }
 
-impl<'a, I, const C: usize> UnwrapItemsExt<{C}> for I
-where
-{
-    type Iter = impl MyTrait<'a, {C}>;
+impl<'a, I, const C: usize> UnwrapItemsExt<'a, { C }> for I {
+    type Iter = impl MyTrait<'a, { C }>;
 
     fn unwrap_items(self) -> Self::Iter {
-        MyStruct::<{C}> {}
+        MyStruct::<{ C }> {}
     }
 }
 
diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs
new file mode 100644
index 00000000000..3f34b00ec77
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.rs
@@ -0,0 +1,26 @@
+// Tests that we don't allow unconstrained lifetime parameters in impls when
+// the lifetime is used in an associated opaque type.
+
+#![feature(type_alias_impl_trait)]
+
+trait UnwrapItemsExt {
+    type Iter;
+    fn unwrap_items(self) -> Self::Iter;
+}
+
+struct MyStruct {}
+
+trait MyTrait<'a> {}
+
+impl<'a> MyTrait<'a> for MyStruct {}
+
+impl<'a, I> UnwrapItemsExt for I {
+    //~^ ERROR the lifetime parameter `'a` is not constrained
+    type Iter = impl MyTrait<'a>;
+
+    fn unwrap_items(self) -> Self::Iter {
+        MyStruct {}
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
new file mode 100644
index 00000000000..e594dc577b1
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime-unconstrained.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/assoc-type-lifetime-unconstrained.rs:17:6
+   |
+LL | impl<'a, I> UnwrapItemsExt for I {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs
index cff1d24494e..39f785d8cc5 100644
--- a/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs
+++ b/src/test/ui/type-alias-impl-trait/assoc-type-lifetime.rs
@@ -4,7 +4,7 @@
 
 #![feature(type_alias_impl_trait)]
 
-trait UnwrapItemsExt {
+trait UnwrapItemsExt<'a> {
     type Iter;
     fn unwrap_items(self) -> Self::Iter;
 }
@@ -15,9 +15,7 @@ trait MyTrait<'a> {}
 
 impl<'a> MyTrait<'a> for MyStruct {}
 
-impl<'a, I> UnwrapItemsExt for I
-where
-{
+impl<'a, I> UnwrapItemsExt<'a> for I {
     type Iter = impl MyTrait<'a>;
 
     fn unwrap_items(self) -> Self::Iter {