about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2025-01-14 01:50:53 +0000
committerMichael Goulet <michael@errs.io>2025-01-14 01:51:16 +0000
commit377dbc96a6d5b7d22b75d4bd98fd00d9e1bb194e (patch)
treec918f98edd11b94c6bbb3c2bffab219bea89cc53
parent2ae9916816a448fcaab3b2da461de754eda0055a (diff)
downloadrust-377dbc96a6d5b7d22b75d4bd98fd00d9e1bb194e.tar.gz
rust-377dbc96a6d5b7d22b75d4bd98fd00d9e1bb194e.zip
Leak check in impossible_predicates to avoid monomorphizing impossible instances
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs15
-rw-r--r--tests/ui/traits/trait-upcasting/impossible-method-modulo-binders-2.rs39
-rw-r--r--tests/ui/traits/trait-upcasting/impossible-method-modulo-binders.rs40
3 files changed, 91 insertions, 3 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index 1dcd0d0dfb8..da16a742099 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -714,9 +714,18 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
     }
     let errors = ocx.select_all_or_error();
 
-    let result = !errors.is_empty();
-    debug!("impossible_predicates = {:?}", result);
-    result
+    if !errors.is_empty() {
+        return true;
+    }
+
+    // Leak check for any higher-ranked trait mismatches.
+    // We only need to do this in the old solver, since the new solver already
+    // leak-checks.
+    if !infcx.next_trait_solver() && infcx.leak_check(ty::UniverseIndex::ROOT, None).is_err() {
+        return true;
+    }
+
+    false
 }
 
 fn instantiate_and_check_impossible_predicates<'tcx>(
diff --git a/tests/ui/traits/trait-upcasting/impossible-method-modulo-binders-2.rs b/tests/ui/traits/trait-upcasting/impossible-method-modulo-binders-2.rs
new file mode 100644
index 00000000000..bc433605531
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/impossible-method-modulo-binders-2.rs
@@ -0,0 +1,39 @@
+//@ build-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+#![allow(coherence_leak_check)]
+
+type A = fn(&'static ());
+type B = fn(&());
+
+trait Bound<P: WithAssoc>: From<GetAssoc<P>> {
+}
+impl Bound<B> for String {}
+
+trait Trt<T> {
+    fn __(&self, x: T) where T: Bound<A> {
+        T::from(());
+    }
+}
+
+impl<T, S> Trt<T> for S {}
+
+type GetAssoc<T> = <T as WithAssoc>::Ty;
+
+trait WithAssoc {
+    type Ty;
+}
+
+impl WithAssoc for B {
+    type Ty = String;
+}
+
+impl WithAssoc for A {
+    type Ty = ();
+}
+
+fn main() {
+    let x: &'static dyn Trt<String> = &();
+}
diff --git a/tests/ui/traits/trait-upcasting/impossible-method-modulo-binders.rs b/tests/ui/traits/trait-upcasting/impossible-method-modulo-binders.rs
new file mode 100644
index 00000000000..63ad1c0a060
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/impossible-method-modulo-binders.rs
@@ -0,0 +1,40 @@
+//@ build-pass
+//@ revisions: current next
+//@ ignore-compare-mode-next-solver (explicit revisions)
+//@[next] compile-flags: -Znext-solver
+
+trait Foo {}
+impl Foo for fn(&'static ()) {}
+
+trait Bar {
+    type Assoc: Default;
+}
+impl<T: Foo> Bar for T {
+    type Assoc = usize;
+}
+impl Bar for fn(&()) {
+    type Assoc = ();
+}
+
+fn needs_foo<T: Foo>() -> usize {
+    needs_bar::<T>()
+}
+
+fn needs_bar<T: Bar>() -> <T as Bar>::Assoc {
+    Default::default()
+}
+
+trait Evil<T> {
+    fn bad(&self)
+    where
+        T: Foo,
+    {
+        needs_foo::<T>();
+    }
+}
+
+impl Evil<fn(&())> for () {}
+
+fn main() {
+    let x: &dyn Evil<fn(&())> = &();
+}