about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2018-10-30 16:38:50 -0400
committerNiko Matsakis <niko@alum.mit.edu>2019-01-02 17:35:05 -0500
commit652fd2efdfea46f9b31859ff3c8a92e40581f224 (patch)
tree7be5fd18adde029ff6ed0847fdccb41ea96e05ad /src
parentb68fad670bb3612cac26e50751e4fd9150e59977 (diff)
downloadrust-652fd2efdfea46f9b31859ff3c8a92e40581f224.tar.gz
rust-652fd2efdfea46f9b31859ff3c8a92e40581f224.zip
add tests exercising `exists<'a> { forall<'b> { .. } }` pattern
Amazingly, this scenario was not tested for trait matching.
Diffstat (limited to 'src')
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-fn.rs23
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-fn.stderr24
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs35
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs37
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs29
-rw-r--r--src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr15
6 files changed, 163 insertions, 0 deletions
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.rs b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
new file mode 100644
index 00000000000..bba1f4dfb86
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.rs
@@ -0,0 +1,23 @@
+// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+trait Trait<T> {}
+
+fn foo<'a>() -> fn(&'a u32) {
+    panic!()
+}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+    // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)`
+    //   - This requires (among other things) instantiating `'b` universally,
+    //     yielding `fn(&!b u32)`, in a fresh universe U1
+    //   - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`.
+
+    let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
new file mode 100644
index 00000000000..75ba89f58da
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-fn.stderr
@@ -0,0 +1,24 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/hrtb-exists-forall-fn.rs:22:34
+   |
+LL |     let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer
+   |                                  ^^^
+   |
+   = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U1, name: BrNamed(crate0:DefIndex(1:11), 'b) })...
+   = note: ...so that the expression is assignable:
+           expected for<'b> fn(&'b u32)
+              found fn(&u32)
+note: but, the lifetime must be valid for the call at 22:34...
+  --> $DIR/hrtb-exists-forall-fn.rs:22:34
+   |
+LL |     let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer
+   |                                  ^^^^^
+note: ...so type `fn(&u32)` of expression is valid during the expression
+  --> $DIR/hrtb-exists-forall-fn.rs:22:34
+   |
+LL |     let _: for<'b> fn(&'b u32) = foo(); //~ ERROR cannot infer
+   |                                  ^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
new file mode 100644
index 00000000000..8801760056e
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-contravariant.rs
@@ -0,0 +1,35 @@
+// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+//
+// compile-pass
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+    T: Trait<for<'b> fn(&'b u32)>,
+{
+}
+
+impl<'a> Trait<fn(&'a u32)> for () {}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+    // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)` -- this does a
+    //   "bidirectional" subtyping check, so we wind up with:
+    //   - `fn(&?a u32) <: for<'b> fn(&'b u32)` :-
+    //     - `&'!b u32 <: &?a u32`
+    //     - `!'b: ?a` -- solveable if `?a` is inferred to `'empty`
+    //   - `for<'b> fn(&'b u32) <: fn(&?a u32)` :-
+    //     - `&?a u32 u32 <: &?b u32`
+    //     - `?a: ?b` -- solveable if `?b` is also inferred to `'empty`
+    // - So the subtyping check succeeds, somewhat surprisingly.
+    //   This is because we can use `'empty`.
+
+    foo::<()>();
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs
new file mode 100644
index 00000000000..da1bb7cd5fd
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-covariant.rs
@@ -0,0 +1,37 @@
+// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+//
+// compile-pass
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+    T: Trait<for<'b> fn(fn(&'b u32))>,
+{
+}
+
+impl<'a> Trait<fn(fn(&'a u32))> for () {}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(fn(&'a u32))> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(fn(&?a u32))>`
+    // - We unify `fn(fn(&?a u32))` with `for<'b> fn(fn(&'b u32))` -- this does a
+    //   "bidirectional" subtyping check, so we wind up with:
+    //   - `fn(fn(&?a u32)) <: for<'b> fn(fn(&'b u32))` :-
+    //     - `fn(&!b u32) <: fn(&?a u32)`
+    //       - `&?a u32 <: &!b u32`
+    //         - `?a: !'b` -- solveable if `?a` is inferred to `'static`
+    //   - `for<'b> fn(fn(&'b u32)) <: fn(fn(&?a u32))` :-
+    //     - `fn(&?a u32) <: fn(&?b u32)`
+    //       - `&?b u32 <: &?a u32`
+    //         - `?b: ?a` -- solveable if `?b` is inferred to `'static`
+    // - So the subtyping check succeeds, somewhat surprisingly.
+    //   This is because we can use `'static`.
+
+    foo::<()>();
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
new file mode 100644
index 00000000000..db589548d0e
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.rs
@@ -0,0 +1,29 @@
+// Test a `exists<'a> { forall<'b> { 'a = 'b } }` pattern -- which should not compile!
+//
+// In particular, we test this pattern in trait solving, where it is not connected
+// to any part of the source code.
+
+use std::cell::Cell;
+
+trait Trait<T> {}
+
+fn foo<T>()
+where
+    T: Trait<for<'b> fn(Cell<&'b u32>)>,
+{
+}
+
+impl<'a> Trait<fn(Cell<&'a u32>)> for () {}
+
+fn main() {
+    // Here, proving that `(): Trait<for<'b> fn(&'b u32)>` uses the impl:
+    //
+    // - The impl provides the clause `forall<'a> { (): Trait<fn(&'a u32)> }`
+    // - We instantiate `'a` existentially to get `(): Trait<fn(&?a u32)>`
+    // - We unify `fn(&?a u32)` with `for<'b> fn(&'b u32)`
+    //   - This requires (among other things) instantiating `'b` universally,
+    //     yielding `fn(&!b u32)`, in a fresh universe U1
+    //   - So we get `?a = !b` but the universe U0 assigned to `?a` cannot name `!b`.
+
+    foo::<()>(); //~ ERROR cannot infer
+}
diff --git a/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
new file mode 100644
index 00000000000..7a0986ccdd9
--- /dev/null
+++ b/src/test/ui/hrtb/hrtb-exists-forall-trait-invariant.stderr
@@ -0,0 +1,15 @@
+error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
+  --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5
+   |
+LL |     foo::<()>(); //~ ERROR cannot infer
+   |     ^^^^^^^^^
+   |
+   = note: first, the lifetime cannot outlive lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'b) })...
+   = note: ...but the lifetime must also be valid for lifetime RePlaceholder(Placeholder { universe: U3, name: BrNamed(crate0:DefIndex(1:11), 'b) })...
+   = note: ...so that the types are compatible:
+           expected Trait<for<'b> fn(std::cell::Cell<&'b u32>)>
+              found Trait<fn(std::cell::Cell<&u32>)>
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0495`.