-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Add Output = expected type trait obligation for known binary operators #96482
Add Output = expected type trait obligation for known binary operators #96482
Conversation
@bors try @rust-timer queue |
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
⌛ Trying commit 6fe3b1debd3b44413c657a0b1dba37d553d7a526 with merge 2142253261d42f925cbaf34fe261e47feea3b67b... |
(ah I missed some tests, will fix those later today) |
retrying perf run, pushes will cause it to cancel @bors try @rust-timer queue |
Awaiting bors try build completion. @rustbot label: +S-waiting-on-perf |
⌛ Trying commit e9ecae53d06562c178dfb3a81d298f5c167639b9 with merge f07f0f43ceab58a4ed0051bac441d2d07d6571e2... |
obligations.push(traits::Obligation::new( | ||
cause.clone(), | ||
self.param_env, | ||
ty::Binder::dummy(ty::PredicateKind::Projection(ProjectionPredicate { |
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.
My only worry is that registering this projection obligation will cause inference to break in certain places, since it asserts type equality as opposed to coercibility.
@@ -511,6 +516,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||
}; | |||
obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); |
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 might be possible to stash the type from the expectation in the BinOp
cause-code then edit the code that suggests "add std::ops::Mul
" to add the associated type there, in case inference is broken by the current change (or if the perf hit is too massive). I'll try to think about if either is a really valid worry, though.
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.
in case inference is broken by the current change
I guess not necessarily, since we're only applying this when we have Expectation::ExpectHasType
, not the other ones which are there to guide coercion... (I think)
@@ -511,6 +516,31 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||
}; | |||
obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds)); | |||
|
|||
// If we're producing obligations for an operator trait, and it has an `Output` | |||
// associated type, then we add an `Output=expected` obligation. | |||
if let (true, Expectation::ExpectHasType(output_ty)) = (is_op, expected) { |
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.
nits: let
chains can make this more readable, and Expectation::only_has_type
might be useful instead of matching on the variant itself.
This comment has been minimized.
This comment has been minimized.
☀️ Try build successful - checks-actions |
Queued f07f0f43ceab58a4ed0051bac441d2d07d6571e2 with parent ff18038, future comparison URL. |
Finished benchmarking commit (f07f0f43ceab58a4ed0051bac441d2d07d6571e2): comparison url. Summary: This benchmark run did not return any relevant results. If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. Benchmarking this pull request likely means that it is perf-sensitive, so we're automatically marking it as not fit for rolling up. While you can manually mark this PR as fit for rollup, we strongly recommend not doing so since this PR may lead to changes in compiler perf. @bors rollup=never |
I'm not too happy with the increase in verbosity, but the perf impact isn't massive and we might be able to work things out so that we don't regress as much in the output.
This is a problem, though :( I think this suggestion might be a more straightforward approach to get the same effect we're looking for. |
Yeah I think my original strategy won't work if it's changing type-checking results. I tried what @compiler-errors suggested of carrying additional data in the obligation cause, and passing that through to the suggestion code. Take a look and let me know if the implementation seems reasonable. It fixes the specific issue in missing-bounds.rs while not breaking anything else. The hackiest part is the code that generates and appends the string |
☔ The latest upstream changes (presumably #97135) made this pull request unmergeable. Please resolve the merge conflicts. |
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.
r=me after rebase (ping me to approve)
if !errors.is_empty() { | ||
for error in errors { | ||
if let Some(trait_pred) = | ||
error.obligation.predicate.to_opt_poly_trait_pred() | ||
{ |
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 to avoid the Vec
allocation, right? Good idea.
@@ -504,6 +525,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | |||
rhs_span: opt_input_expr.map(|expr| expr.span), | |||
is_lit: opt_input_expr | |||
.map_or(false, |expr| matches!(expr.kind, hir::ExprKind::Lit(_))), | |||
output_pred: None, |
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.
Not necessary for this PR: I wonder if we can provide the predicate somehow here 🤔
Apologies for the delay in reviewing. If you can squash the commits, that would also be useful. |
Ping :) |
Ah apologies for the delay in the response to the review! Too busy graduating. I will get to this by the weekend. |
@willcrichton no hurries! Congratulations! |
ping from triage:
FYI: when a PR is ready for review, send a message containing |
c40c425
to
b61f8ba
Compare
Sorry again for the delays. I just rebased, and found a new regression. Whatever code is producing the suggestion is creating an incorrect syntax combining the associated type bound with an existing trait parameter. See: https://github.com/rust-lang/rust/pull/96482/files#diff-b4e22a434e69c155966cdab3f3b6ae44922478447624ba038055ca32f1b3a50f I will try to debug this soon. |
☔ The latest upstream changes (presumably #99165) made this pull request unmergeable. Please resolve the merge conflicts. |
LL | fn add_ten<N: std::ops::Add<i32><Output=N>>(n: N) -> N { | ||
| ++++++++++++++++++++++++++++++ |
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.
If you can't figure this one out, let's clean up for merge and open a follow up ticket.
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 figured out the issue. I added a fix, although it duplicates some code as you can see in the commit and the FIXME. If you want me to figure out a way to factor out the duplicated code I can do that, otherwise the PR is ready I think.
…ise trait obligations for binops.
ba5f969
to
2f15dfa
Compare
@bors r+ |
☀️ Test successful - checks-actions |
Finished benchmarking commit (d695a49): comparison url. Instruction countThis benchmark run did not return any relevant results for this metric. Max RSS (memory usage)Results
CyclesResults
If you disagree with this performance assessment, please file an issue in rust-lang/rustc-perf. @rustbot label: -perf-regression Footnotes |
This PR is a follow-on to #94034 that addresses #96442. That is, after replacing the trait-suggestion logic in
op.rs
with a more generic path that analyzes a general set ofObligation
s, then we lost some specificity in the suggestions where the bounds on the associated typeOutput=
would not get suggested.This PR fixes this issue by changing
FnCtxt::construct_obligation_for_trait
to include a newProjectionPredicate
obligation for binary operators that obliges thatOutput
is the same as the expected type of the expression. Additionally, to get the expected type of the expression, this PR threads theExpectation<'tcx>
structure throughout several functions.See src/test/ui/generic-associated-types/missing-bounds.stderr for an example of how this works.
One side effect of this change is it causes type-check failures with binops to include additional information. Specifically, many now say
It's up for discussion whether this added context is worth it to the user.
r? @estebank