Rollup merge of #141390 - compiler-errors:poly-select-new-solver, r=lcnr

Don't allow `poly_select` in new solver

I added a `poly_select` call in #140519, but this causes an ICE since the new solver doesn't properly handle the "instantiate binder -> recanonicalize" step in the proof tree visitor.

While we could fix the select visitor to look at the next step in proof tree, it's not really necessary. Instead, let's enforce that all callees call the non-higher-ranked `select` function in the new solver.

Fixes https://github.com/rust-lang/rust/issues/141322

r? lcnr
This commit is contained in:
Matthias Krüger
2025-05-22 16:04:16 +02:00
committed by GitHub
6 changed files with 69 additions and 10 deletions

View File

@@ -1501,11 +1501,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
return None;
};
let Ok(Some(ImplSource::UserDefined(impl_data))) = SelectionContext::new(self)
.poly_select(&obligation.with(
self.tcx,
let trait_ref = self.enter_forall_and_leak_universe(
predicate.kind().rebind(proj.projection_term.trait_ref(self.tcx)),
))
);
let Ok(Some(ImplSource::UserDefined(impl_data))) =
SelectionContext::new(self).select(&obligation.with(self.tcx, trait_ref))
else {
return None;
};

View File

@@ -5,7 +5,7 @@ use rustc_infer::traits::solve::inspect::ProbeKind;
use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal};
use rustc_infer::traits::{
BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause,
PolyTraitObligation, Selection, SelectionError, SelectionResult,
Selection, SelectionError, SelectionResult, TraitObligation,
};
use rustc_macros::extension;
use rustc_middle::{bug, span_bug};
@@ -17,7 +17,7 @@ use crate::solve::inspect::{self, ProofTreeInferCtxtExt};
impl<'tcx> InferCtxt<'tcx> {
fn select_in_new_trait_solver(
&self,
obligation: &PolyTraitObligation<'tcx>,
obligation: &TraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
assert!(self.next_trait_solver());

View File

@@ -265,9 +265,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &PolyTraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
if self.infcx.next_trait_solver() {
return self.infcx.select_in_new_trait_solver(obligation);
}
assert!(!self.infcx.next_trait_solver());
let candidate = match self.select_from_obligation(obligation) {
Err(SelectionError::Overflow(OverflowError::Canonical)) => {
@@ -299,6 +297,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
&mut self,
obligation: &TraitObligation<'tcx>,
) -> SelectionResult<'tcx, Selection<'tcx>> {
if self.infcx.next_trait_solver() {
return self.infcx.select_in_new_trait_solver(obligation);
}
self.poly_select(&Obligation {
cause: obligation.cause.clone(),
param_env: obligation.param_env,

View File

@@ -0,0 +1,12 @@
error[E0308]: mismatched types
--> $DIR/hr-projection-mismatch.rs:20:5
|
LL | wrap::<_, Thing>();
| ^^^^^^^^^^^^^^^^ one type is more general than the other
|
= note: expected reference `&'a _`
found reference `&_`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0308`.

View File

@@ -0,0 +1,20 @@
error[E0271]: type mismatch resolving `<Thing as Trait<'a>>::Assoc == &i32`
--> $DIR/hr-projection-mismatch.rs:20:15
|
LL | wrap::<_, Thing>();
| ^^^^^ type mismatch resolving `<Thing as Trait<'a>>::Assoc == &i32`
|
note: types differ
--> $DIR/hr-projection-mismatch.rs:14:18
|
LL | type Assoc = &'a i32;
| ^^^^^^^
note: required by a bound in `wrap`
--> $DIR/hr-projection-mismatch.rs:17:33
|
LL | fn wrap<T, U: for<'a> Trait<'a, Assoc = T>>() {}
| ^^^^^^^^^ required by this bound in `wrap`
error: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0271`.

View File

@@ -0,0 +1,25 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
// Regression test for <https://github.com/rust-lang/rust/issues/141322>.
trait Trait<'a> {
type Assoc;
}
struct Thing;
impl<'a> Trait<'a> for Thing {
type Assoc = &'a i32;
}
fn wrap<T, U: for<'a> Trait<'a, Assoc = T>>() {}
fn foo() {
wrap::<_, Thing>();
//[next]~^ ERROR type mismatch resolving `<Thing as Trait<'a>>::Assoc == &i32
//[current]~^^ ERROR mismatched types
}
fn main() {}