Auto merge of #136988 - compiler-errors:impossible_predicates, r=lcnr

Use the new solver in the `impossible_predicates`

The old solver is unsound for many reasons. One of which was weaponized by `@lcnr` in #140212, where the old solver was incompletely considering a dyn vtable method to be impossible and replacing its vtable entry with a null value. This null function could be called post-mono.

The new solver is expected to be less incomplete due to its correct handling of higher-ranked aliases in relate. This PR switches the `impossible_predicates` query to use the new solver, which patches this UB.

r? lcnr
This commit is contained in:
bors 2025-05-15 15:31:24 +00:00
commit c4e05e53d1
2 changed files with 43 additions and 9 deletions

View file

@ -690,8 +690,11 @@ fn replace_param_and_infer_args_with_placeholder<'tcx>(
/// used during analysis.
pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause<'tcx>>) -> bool {
debug!("impossible_predicates(predicates={:?})", predicates);
let (infcx, param_env) =
tcx.infer_ctxt().build_with_typing_env(ty::TypingEnv::fully_monomorphized());
let (infcx, param_env) = tcx
.infer_ctxt()
.with_next_trait_solver(true)
.build_with_typing_env(ty::TypingEnv::fully_monomorphized());
let ocx = ObligationCtxt::new(&infcx);
let predicates = ocx.normalize(&ObligationCause::dummy(), param_env, predicates);
for predicate in predicates {
@ -704,13 +707,6 @@ pub fn impossible_predicates<'tcx>(tcx: TyCtxt<'tcx>, predicates: Vec<ty::Clause
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
}

View file

@ -0,0 +1,38 @@
//@ run-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
trait Id {
type This<'a>;
}
impl<T> Id for T {
type This<'a> = T;
}
trait Trait<T> {}
impl<T: Id> Trait<for<'a> fn(T::This<'a>)> for T {}
trait Method<T: Id> {
fn call_me(&self)
where
T: Trait<for<'a> fn(T::This<'a>)>;
}
impl<T, U> Method<U> for T {
fn call_me(&self) {
println!("method was reachable");
}
}
fn generic<T: Id>(x: &dyn Method<T>) {
// Proving `T: Trait<for<'a> fn(T::This<'a>)>` holds.
x.call_me();
}
fn main() {
// Proving `u32: Trait<fn(u32)>` fails due to incompleteness.
// We don't add the method to the vtable of `dyn Method`, so
// calling it causes UB.
generic::<u32>(&());
}