about summary refs log tree commit diff
diff options
context:
space:
mode:
authorAmanda Stjerna <amanda.stjerna@it.uu.se>2025-04-17 10:36:37 +0200
committerAmanda Stjerna <amanda.stjerna@it.uu.se>2025-04-22 12:07:53 +0200
commite9d374c6573a413f598c9b52f938a8abd5e041cf (patch)
treec53f2acb268911c63749aa0c903ce9f5972e7998
parentc4b38a596767c9c6275c937cf3a2d4b9612b4875 (diff)
downloadrust-e9d374c6573a413f598c9b52f938a8abd5e041cf.tar.gz
rust-e9d374c6573a413f598c9b52f938a8abd5e041cf.zip
Add tests for two untested cases of placeholder relations
During work on #130227, I discovered several situations not covered by any
previously existing UI test. This commit introudces tests to cover that.
-rw-r--r--tests/ui/borrowck/static-trait-bound-lost.rs54
-rw-r--r--tests/ui/nll/relate_tys/placeholder-outlives-existential.rs31
-rw-r--r--tests/ui/nll/relate_tys/placeholder-outlives-existential.stderr25
3 files changed, 110 insertions, 0 deletions
diff --git a/tests/ui/borrowck/static-trait-bound-lost.rs b/tests/ui/borrowck/static-trait-bound-lost.rs
new file mode 100644
index 00000000000..0288acea0f6
--- /dev/null
+++ b/tests/ui/borrowck/static-trait-bound-lost.rs
@@ -0,0 +1,54 @@
+// This test is a reduced version of a bug introduced during work on type-tests for Polonius.
+// The underlying problem is that the 'static bound is lost for a type parameter that is
+// threaded deeply enough, causing an error.
+// The bug was first observed in exr-1.4.1/src/image/read/mod.rs:124:5 during perf test.
+
+//@ check-pass
+
+use std::marker::PhantomData;
+
+struct ReadAllLayers<ReadChannels> {
+    px: PhantomData<ReadChannels>,
+}
+
+trait ReadLayers<'s> {}
+
+impl<'s, C> ReadLayers<'s> for ReadAllLayers<C> where C: ReadChannels<'s> {}
+
+fn make_builder<A, Set, Pixels>(
+    _: Set,
+) -> ReadAllLayers<CollectPixels<A, Pixels, Set>>
+where
+    Set: Fn(&mut Pixels),
+{
+    todo!()
+}
+
+struct CollectPixels<Pixel, PixelStorage, SetPixel> {
+    px: PhantomData<(SetPixel, Pixel, PixelStorage)>,
+}
+
+impl<'s, PixelStorage, SetPixel: 's> ReadChannels<'s>
+    for CollectPixels<usize, PixelStorage, SetPixel>
+where
+    SetPixel: Fn(&mut PixelStorage),
+{
+}
+
+trait ReadChannels<'s> {}
+
+fn from_file<L>(_: L)
+where
+    for<'s> L: ReadLayers<'s>,
+{
+}
+
+pub fn read_all_rgba_layers_from_file<Set: 'static, Pixels: 'static>(
+    set_pixel: Set,
+) where
+    Set: Fn(&mut Pixels),
+{
+    from_file(make_builder(set_pixel)); // Error triggered.
+}
+
+pub fn main() {}
diff --git a/tests/ui/nll/relate_tys/placeholder-outlives-existential.rs b/tests/ui/nll/relate_tys/placeholder-outlives-existential.rs
new file mode 100644
index 00000000000..3f22e9a313a
--- /dev/null
+++ b/tests/ui/nll/relate_tys/placeholder-outlives-existential.rs
@@ -0,0 +1,31 @@
+// Test that we correctly handle some cases of placeholder leaks.
+//
+//@ compile-flags:-Zno-leak-check
+
+
+struct Co<'a>(&'a ());
+struct Inv<'a>(*mut &'a ());
+struct Contra<'a>(fn(&'a ()));
+
+// `exists<'e> forall<'p> 'p: 'e` -> ERROR
+fn p_outlives_e(
+    x: for<'e> fn(for<'p> fn(fn(fn(Contra<'e>, Co<'p>)))),
+) -> fn(fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
+    x //~ ERROR mismatched types [E0308]
+}
+
+// `exists<'e> forall<'p> 'e: 'p` -> Ok, 'e: 'static
+fn e_outlives_p_static(
+    x: for<'e> fn(Inv<'e>, for<'p> fn(fn(fn(Contra<'p>, Co<'e>)))),
+) -> fn(Inv<'static>, fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
+    x
+}
+
+// `exists<'e> forall<'p> 'e: 'p` -> Ok, 'e: 'static -> ERROR
+fn e_outlives_p_static_err<'not_static>(
+    x: for<'e> fn(Inv<'e>, for<'p> fn(fn(fn(Contra<'p>, Co<'e>)))),
+) -> fn(Inv<'not_static>, fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>)))) {
+    x //~ ERROR lifetime may not live long enough
+}
+
+fn main() {}
diff --git a/tests/ui/nll/relate_tys/placeholder-outlives-existential.stderr b/tests/ui/nll/relate_tys/placeholder-outlives-existential.stderr
new file mode 100644
index 00000000000..80ab5c8d6e9
--- /dev/null
+++ b/tests/ui/nll/relate_tys/placeholder-outlives-existential.stderr
@@ -0,0 +1,25 @@
+error[E0308]: mismatched types
+  --> $DIR/placeholder-outlives-existential.rs:14:5
+   |
+LL |     x
+   |     ^ one type is more general than the other
+   |
+   = note: expected fn pointer `fn(fn(fn(for<'unify> fn(Contra<'unify>, Co<'unify>))))`
+              found fn pointer `for<'e> fn(for<'e, 'p> fn(for<'e, 'p> fn(for<'e, 'p> fn(Contra<'e>, Co<'p>))))`
+
+error: lifetime may not live long enough
+  --> $DIR/placeholder-outlives-existential.rs:28:5
+   |
+LL | fn e_outlives_p_static_err<'not_static>(
+   |                            ----------- lifetime `'not_static` defined here
+...
+LL |     x
+   |     ^ returning this value requires that `'not_static` must outlive `'static`
+   |
+   = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant
+   = note: the struct `Inv<'a>` is invariant over the parameter `'a`
+   = help: see <https://doc.rust-lang.org/nomicon/subtyping.html> for more information about variance
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.