-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
[WIP] binops: don't eagerly unify the types of LHS and RHS if one of them is a primitive #22993
Conversation
@@ -2683,8 +2683,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>, | |||
unifier: F) where | |||
F: FnOnce(), | |||
{ | |||
debug!(">> typechecking: expr={} expected={}", | |||
expr.repr(fcx.tcx()), expected.repr(fcx.tcx())); | |||
if fcx.inh.node_types.borrow().get(&expr.id).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.
Without this, the RHS ended being type checked (check_expr_*
) twice. And that causes problems when RHS is a generic enum, eg Some(0) == None
didn't type check (RUST_LOG reported unfulfilled _: Sized
obligations on None
), and the error message was that None
needed type annotations: Some(0) == None::<i32>()
.
This was the least invasive solution that I could think of to avoid type cheking the RHS twice. If you have any other idea, let me know.
☔ The latest upstream changes (presumably #22995) made this pull request unmergeable. Please resolve the merge conflicts. |
I'm not sure how I feel about the specific approach that this patch takes. Maybe we can chat a bit on IRC. In particular, I am sort of keen to the approach of:
The advantages I see here:
Note that you can I'd be curious to hear others' opinion on this -- naturally @japaric but perhaps also @eddyb or @Aatch? I think this change is purely local to the how the compiler is structured. |
@nikomatsakis we already handle intrinsic calls in-line, we could do the same thing for calls to built-in operators. |
I like the idea in principle, but when I tried to implement it, type inference went downhill: // bits: u32
bits >> 31 == 0 //~ error: `PartialEq<i32>` is not implemented by `u32` This may be solved by making default type params ( // exponent: i16
exponent -= 127 + 23;
// ~~~~~~~~~ expected `i16` found `i32` To do this correctly, we need to find |
On Wed, Mar 04, 2015 at 02:25:15PM -0800, Eduard Burtescu wrote:
That's not quite what I had in mind. Rather, I figured that trans + |
On Wed, Mar 04, 2015 at 05:06:37PM -0800, Jorge Aparicio wrote:
Ah, interesting. Yes, it does seem like we'd need either:
|
Does this fix #22099? |
@japaric we can fix the type inference issues (at least in libcore) like so: This basically encodes some knowledge about the binary op traits and the way they are implemented for integral types etc into the typeck code. Eventually, I could imagine the |
@mdinger It should. |
Cool. You probably should add it to the header post (closes ...). |
@mdinger I've added a TODO to the header post. (Btw, let me know if you spot any other issue that seems related/duplicated) |
@japaric Will do. Thanks. |
Update: After trying @nikomatsakis patch I got further but I'm getting a bunch of "error: user-defined operators are not allowed in constants" in all binary operations that are in |
@japaric let's discuss on IRC :) I have thoughts... |
Closing this due to #23319 |
Multidispatch now works when the LHS is a primitive, e.g.
1 + 1
,1 + BigFloat
and1 + BigInt
all compile (if the proper trait impls are in scope).Because RHS is no longer constrained to have the same type as the LHS when the LHS is a primitive, type annotations are required in some situations where multiple resolutions are possible:
This PR also fixes some questionable behavior where the RHS was driving type inference, this no longer compiles:
[breaking-change]
closes #19035
closes #22743
r? @nikomatsakis
Another pattern that broke is
1 + (loop {})
, because the RHS fallbacks to()
andi32
doesn't implementAdd<()>
. This used to work becauseloop {}
was coerced toi32
, and that expression resolved to built-in operation. I think I can add extra logic to coerce the bottom type before it fallbacks to avoid breaking this pattern.TODO