-Znext-solver use the trait object's own bounds instead of goal when considering builtin object bounds#152859
-Znext-solver use the trait object's own bounds instead of goal when considering builtin object bounds#152859ShoyuVanilla wants to merge 2 commits intorust-lang:mainfrom
-Znext-solver use the trait object's own bounds instead of goal when considering builtin object bounds#152859Conversation
4a25656 to
0f257f0
Compare
|
hmm, thinking about this, given pub trait Trait<T> {
type Assoc;
}
pub trait Foo {
type FooAssoc;
}
pub struct Wrap<U: Foo>(<dyn Trait<i32, Assoc = i64> as Trait<U::FooAssoc>>::Assoc)
where
dyn Trait<i32, Assoc = i64>: Trait<U::FooAssoc>;we're checking This builtin impl should be impl Trait<i32> for dyn Trait<i32, Assoc = i64>
where
i32: Sized,
// we eagerly replace `<Self as Trait<i32>>::Assoc` with `i64` when
// emitting the impl to avoid non-productive cycles.
<Self as Trait<i32>>::Assoc: Sized,
{
type Assoc = i64;
}The builtin impl only applies here if I think the bug is here We should compute the where-clauses of the builtin impl using only the object type, not the goal we actually have to prove. This builtin impl won't be applicable for |
…iltin object bounds
0f257f0 to
4d3a012
Compare
-Znext-solver Remove a problematic assertion from probing object bound candidates-Znext-solver se the trait object's own bounds instead of goal when considering builtin object bounds
|
That looks correct. I was being too narrow in my reasoning about the cause 😅 |
This comment has been minimized.
This comment has been minimized.
| @@ -83,14 +83,21 @@ where | |||
| assumption: I::Clause, | |||
| ) -> Result<Candidate<I>, NoSolution> { | |||
| Self::probe_and_match_goal_against_assumption(ecx, source, goal, assumption, |ecx| { | |||
| ecx.try_evaluate_added_goals()?; | |||
There was a problem hiding this comment.
rust/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs
Lines 192 to 194 in 1eb36c6
We equate the goal with the assumption before entering this closure in the above lines.
However, that eq relationship does not actually hold in the problematic cases from the linked issues.
Because this additional goal is introduced through that equality, the ICE still occurs even if we use the trait ref from the trait object (instead of the goal's trait ref) when calling predicates_for_object_candidate.
Those predicates are evaluated here, in projection_may_match:
I think short-circuiting candidates for which the equality cannot hold, before entering the remaining probing, would be harmless and prevent the ICE.
In fact, adding just that early check is enough to fix the ICE in the linked issues.
But I think using trait object's own bounds instead of goal's is correct, so changed the follwing lines as well.
| @@ -425,7 +425,7 @@ where | |||
| } | |||
| } | |||
| ty::Dynamic(tt, ..) => { | |||
| let principal = tt.principal().map(|p| p.def_id()); | |||
| let principal = tt.principal_def_id(); | |||
There was a problem hiding this comment.
This change is irrelevant of the issue but seems trivial 😅
-Znext-solver se the trait object's own bounds instead of goal when considering builtin object bounds-Znext-solver use the trait object's own bounds instead of goal when considering builtin object bounds
|
Hmm, the CI failure looks sus. Am I doing somewhat very incorrect thingy? |
How? do you still have the code which ICEd when using the trait object arguments lying around? |
The very same code from the beginning pub trait Trait<T> {
type Assoc;
}
pub trait Foo {
type FooAssoc;
}
pub struct Wrap<U: Foo>(<dyn Trait<i32, Assoc = i64> as Trait<U::FooAssoc>>::Assoc)
where
dyn Trait<i32, Assoc = i64>: Trait<U::FooAssoc>;
fn main() {}but maybe I've done what you said in a very wrong way, as the CI failed with very suspicious segfault: https://github.com/rust-lang/rust/actions/runs/22516543500/job/65235925254 |
|
but why:tm: if you use the trait object itself to build the where-clauses, when do you encounter |
|
It is encountered before replacing things. rust/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs Lines 79 to 95 in ddd36bd The replacement happens in rust/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs Lines 925 to 940 in 1eb36c6 We are currently(without this PR) adding such goals in |
|
but that's fine, is it not? the builtin impl should not apply here 🤔 we want to use the where-clause after all |
|
Yeah, such unprovable nested goal itself is fine and correct. rust/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs Lines 961 to 967 in ddd36bd But we still ICE because of L966 here, as projection_may_match filters out the correct(if we use the trait object itself) projection, because of that unprovable nested goal.
So, my intention of that line was to short circuit such unappliable builtin impl before trying replacements |
|
ah, that's yeah... whether the projection matches shouldn't depend on goals from the parent. Eagerly checking whether the nested goals of equating the signature succeeds does fix this issue, but in theory, the Given the way this is setup, all projections should structurally match and we shouldn't have to do any interesting type system stuff there at all. Could you replace the code to check whether the arguments are structurally equal instead of doing proper type system equality? |
Oh, that sounds like a correct way. Would it be sth like the following? fn projection_may_match(
&mut self,
source_projection: ty::Binder<I, ty::ProjectionPredicate<I>>,
target_projection: ty::AliasTerm<I>,
) -> bool {
source_projection.item_def_id() == target_projection.def_id
&& self
.ecx
.probe(|_| ProbeKind::ProjectionCompatibility)
.enter(|ecx| -> Result<_, NoSolution> {
let source_projection = ecx.instantiate_binder_with_infer(source_projection);
- ecx.eq(self.param_env, source_projection.projection_term, target_projection)?;
- ecx.try_evaluate_added_goals()
+ ecx.eq_structurally_relating_aliases(self.param_env, source_projection.projection_term, target_projection)
})
.is_ok()
} |
|
should be |
|
Uh-oh, I encountered the very same problem expressed in this test: Would it make sense to do Or maybe I should devise more radical, correct fix. Maybe replacing projections before matching the goal against the assumption, or calling |
Fixes #152789 and fixes #151329
r? lcnr