-
Notifications
You must be signed in to change notification settings - Fork 1.8k
fix: Port a bunch of stuff from rustc and fix a bunch of type mismatches/diagnostics #20664
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
@@ -0,0 +1,1298 @@ | |||
//! Post-inference closure analysis: captures and closure kind. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file was just moved from crates/hir-ty/src/infer/closure.rs
, to clean things up and also to not mix new solver and Chalk imports.
Some(x) | ||
} else { | ||
None | ||
salsa::attach(db, || { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This file needed salsa::attach()
in few places.
It'd be really nice if we could share |
let x = match 1 { | ||
1 => t as *mut i32, | ||
//^^^^^^^^^^^^^ adjustments: Pointer(MutToConstPointer) | ||
//^ adjustments: Deref(None), Borrow(RawPtr(Mut)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A theme that repeats here and in other tests is variance. Look at the comment I added to variances_of()
for the detail, but in rough lines, bivariance causes problems with the new solver, and our tests had it all over the place. I fixed most of them before becoming upset and defaulting to Invariant
in variance.rs; I still think there is value in fixing the test so I left them as is.
On an unrelated note, the change in adjustments from MutToConstPointer
to Deref
, Borrow
is intentional - I believe rustc does the same.
73..94 'spam!(...am!())': {unknown} | ||
100..119 'for _ ...!() {}': fn into_iter<isize>(isize) -> <isize as IntoIterator>::IntoIter | ||
100..119 'for _ ...!() {}': {unknown} | ||
100..119 'for _ ...!() {}': <isize as IntoIterator>::IntoIter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This test has again associated type normalization and {unknown}
accuracy in fluff; we're used to that with the new solver, I'm not sure under what condition that happens.
!0..13 '"helloworld!"': &'static str | ||
65..121 '{ ...")); }': () | ||
75..76 'x': &'static str | ||
75..76 'x': &'? str |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is another theme repeating in the tests: we lost almost all of our lifetimes. Due to the significance of this I checked this, and this is kinda intentional: rustc has a region check pass (well, not exactly a pass) (https://rustc-dev-guide.rust-lang.org/type-inference.html#region-constraints) and without it our regions won't be resolved. We could add that pass later, or we could instead wait until we properly support lifetimes.
} | ||
|
||
// FIXME(next-solver): The never type fallback implemented in r-a no longer works properly because of | ||
// `Coerce` predicates. We should reimplement fallback like rustc. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To expand a bit on this: the never type fallback relies on being able to conclude from the diverging-ness of one infer var to another. It does this, simply, by resolving the root variable. Unfortunately, now this isn't enough: coercion between variables, also an element that needs to be taken into account in the fallback, can be delayed and stored in the form of Coerce
predicates in the fulfillment context. Worse, unlike root vars, Coerce
predicates form a graph and not even necessarily a DAG: therefore, some more sophisticated tracking is needed. Instead of complicating this PR even more, I opted to regress never types a bit and leave that as a future work.
38..39 'y': {unknown} | ||
41..43 '&y': &'? {unknown} | ||
42..43 'y': {unknown} | ||
20..21 'y': &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? &'? {unknown} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have no idea what caused the blowup here, but it doesn't seem so bad: the test just tests we don't crash or something AFAIK.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What a relief that we don't have infinite recursion here 😌 (Maybe it encountered some recursion limit here?)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably the solver (or something else) hitting its overflow check.
616c9d3
to
badc11f
Compare
// FIXME: We need to have an `upvars_mentioned()` query: | ||
// At this point we haven't done capture analysis, which means | ||
// that the ClosureArgs just contains an inference variable instead | ||
// of tuple of captured types. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess at this point InferenceContext.result.closure_info
would have been filled up for given closure_def_id_a
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically yes, closure analysis at the end of inference is equivalent to this query and should resolve the infer var. I didn't do this because I didn't want to overload this PR, but it should be pretty easy.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Leaving this as a follow-up sounds reasonable to me, as this is already about 10K loc PR 😆
let is_capturing_closure = |_ty: Ty<'db>| { | ||
// FIXME: | ||
// if let TyKind::Closure(closure_def_id, _args) = ty.kind() { | ||
// self.db.upvars_mentioned(closure_def_id.expect_local()).is_some() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And might this be like the above one? (I might be wrong 😅 )
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like you are not 😅
} | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finally we got some human-readable debug impl here 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That wasn't intended in fact, I just did that for my own convenience and left it here, but well, instead of everyone doing the same for their convenience then reverting it let's save their time 😅
// | ||
// cc trait-system-refactor-initiative#110 | ||
if self.infcx.next_trait_solver() && !alias.has_escaping_bound_vars() && !self.in_alias { | ||
if !alias.has_escaping_bound_vars() && !self.in_alias { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like Jack forgot to remove this 😄
…iagnostics This started from porting coercion, but ended with porting much more.
badc11f
to
7d18608
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks great overall! I couldn’t spot no more then just few questionable lines, which is impressive given how large this change is. Fantastic work. It’s hard to imagine how much effort went into pulling this off in just a few days!
I think it's totally fine to merge this now but would you like to wait for reviews from other rust-analyzer or types team members?
I think we don't need another full review, but given the size of the PR I'll wait for at least one more approval: CC @Veykril @lnicola @davidbarsky @flodiebold. I don't expect type team members to review (or have the capacity to review) this. |
I'm merging this based on the above @ShoyuVanilla review and @jackh726's vibe approval on Zulip. |
changelog fixup #20329 |
This started from porting coercion, but ended with porting much more.
As I shared on Zulip, type mismatches go to zero, and diagnostics go to 1.
This is a giant PR. However, all stuff under
hir-ty/src/next_solver
is basically copied straight from rustc, so could use a skim review (although something is probably warranted). To my detriment I discovered, after porting plenty of code, that some of the modules were already there - so I had to cut them. I chose to preserve the ones that were more loyal to the origin, even if it means porting more code.Some themes of the PR:
ObligationCtxt
(parallel to rustc) and starts to use it. This is an opening to a future where, like rustc and correctly (and unlike what we do currently), we don't stash all obligations on theInferenceTable
, rather we evaluate them separately and only put them there if needed.Obligation
overPredicate
. Existing APIs usingPredicate
remain, but new code usesObligation
(and existing APIs will also be migrated eventually). The reason is foresight.Obligation
is basically meant to be a rootPredicate
, and the most important thing about it is its ability to carry origin information (ObligationCause
, currently empty), which will be used when we start reporting trait solving errors. Better prepare for that day.