diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2025-01-14 19:25:06 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-01-14 19:25:06 +0100 |
| commit | 866e61aae076d38fd8a239449775a423c3384348 (patch) | |
| tree | 159533c8666e5709f3aeb1049115c4fdb94b0762 | |
| parent | ca9a9d2f3553676e642bc570ec58332acf0f0f71 (diff) | |
| parent | 94ffced66747a94554e0e0fa420eb21abdced095 (diff) | |
Rollup merge of #135466 - compiler-errors:leak-check-impossible, r=lcnr
Leak check in `impossible_predicates` to avoid monomorphizing impossible instances Fixes #135462 r? lcnr
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..c03b5145aa7 --- /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 +// Regression test for #135462. +#![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(&())> = &(); +} |
