-
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
Use PredicateObligation
s instead of Predicate
s
#69745
Conversation
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 need to move relevant comments from the original PR, and review the code that is different.
src/librustc_infer/traits/wf.rs
Outdated
.map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred)) | ||
.zip(predicates.spans.into_iter()) | ||
.map(|(pred, span)| { | ||
let cause = self.cause(traits::BindingObligation(def_id, span)); |
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.
Before I forget, cc @nikomatsakis on the ItemObligation
vs BindingObligation
split, and the name of the latter.
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.
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.
Hmm, the name BindingObligation
doesn't say that much to me, and the rustdoc on it is not very precise:
Like ItemObligation, but with extra detail on the source of the obligation.
I presume that it's meant to track the precise bound that caused this obligation? In which case I think the name is "decent", but I'd probably just call it WhereClause
or something. I don't think the suffix "Obligation" is adding much 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.
Adding some links to relevant comments in the original PR.
src/librustc_infer/traits/wf.rs
Outdated
.map(|pred| traits::Obligation::new(cause.clone(), self.param_env, pred)) | ||
.zip(predicates.spans.into_iter()) | ||
.map(|(pred, span)| { | ||
let cause = self.cause(traits::BindingObligation(def_id, span)); |
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 comment has been minimized.
This comment has been minimized.
538a8e3
to
cd37a6e
Compare
LL | trait Foo { | ||
| --------- required by `Foo` | ||
| --------- required by this bound in `Foo` | ||
... | ||
LL | where &'a T : Foo, | ||
| ^^^ cannot infer type for reference `&'a T` |
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.
There are a few cases like this one where the inference error itself is already incorrect and the wording change makes them slightly worse in my eyes.
They seem rare enough that we don't need to deal with them immediately, but we should probably account for them.
--> $DIR/issue-20413.rs:8:36 | ||
| | ||
LL | trait Foo { | ||
| --------- required by `Foo` | ||
| --------- required by this bound in `Foo` | ||
... | ||
LL | impl<T> Foo for T where NoData<T>: Foo { |
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.
Another case.
FYI: I plan to review this this week. |
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.
The code seems good, but I'm not sure what I think of the final output.
@@ -3,6 +3,8 @@ error[E0277]: `MyNotSync` cannot be shared between threads safely | |||
| | |||
LL | fn is_sync<T: Sync>() {} | |||
| ------- ---- required by this bound in `is_sync` | |||
| | | |||
| required by a bound in `is_sync` |
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'm a bit confused by these diffs. That is -- I'm not quite sure what this label is trying to tell me. I guess what was happening before is that we had a span for is_sync
but lacked more precise information, so we got no label, but now we get a label?
Nonetheless, I'm not sure this is a net improvement -- the label that tells you which bound definitely seems good, and this new label kind of distracts from that.
Would it be possible to get more precise information to help us in tracking which label is causing the problem?
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 was born out of #69745 (comment), where the small separation between the two spans made @eddyb confused for a short moment. I thought that adding some label to the span might make it clearer in all cases that we're pointing at two different things. Another alternative would be to only point at the fn
ident if it is in a different line to the bound.
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.
BTW, that change is in its own commit, so you can look at the diff without it.
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 changed the second commit to check if both spans are in the same line, and if they are, to not display the span pointing at is_sync
.
This comment has been minimized.
This comment has been minimized.
dccbca2
to
ece8320
Compare
Keep more information about trait binding failures.
ece8320
to
d605a9d
Compare
@eddyb this PR has a lot of potential to bitrot and is blocking the PR to maintain chain of obligations. @nikomatsakis signed off on the code changes but not on the new output. I think the changes in the second commit should be non-controversial. |
@bors r=nikomatsakis,eddyb |
📌 Commit d605a9d has been approved by |
@bors retry |
Rollup of 9 pull requests Successful merges: - rust-lang#69745 (Use `PredicateObligation`s instead of `Predicate`s) - rust-lang#70938 (Add ThreadSanitizer test case) - rust-lang#70973 (Use forward traversal for unconditional recursion lint) - rust-lang#70978 (compiletest: let config flags overwrite -A unused) - rust-lang#70979 (Follow up on BTreeMap comments) - rust-lang#70981 (Rearrange BTreeMap::into_iter to match range_mut.) - rust-lang#70985 (Clean up E0512 explanation) - rust-lang#70988 (Setup the `@rustbot prioritize` command) - rust-lang#70991 (fix rustc-dev-guide's url in src/librustc_codegen_ssa) Failed merges: r? @ghost
rustup rust-lang/rust#69745 changelog: none
rustup rust-lang/rust#69745 changelog: none
Changes: ```` Allow UUID style formatting for `inconsistent_digit_grouping` lint rustup rust-lang#70986 rustup rust-lang#69745 Rustup to rust-lang#70913 compare with the second largest instead of the smallest variant Revert "Downgrade new_ret_no_self to pedantic" Check for clone-on-copy in argument positions Check fn header along with decl when suggesting to implement trait Downgrade implicit_hasher to pedantic Move cognitive_complexity to nursery Run fmt and update test Use int assoc consts in MANUAL_SATURATING_ARITHMETIC Use int assoc consts in checked_conversions lint Use primitive type assoc consts in more tests Use integer assoc consts in more lint example code Don't import primitive type modules Use assoc const NAN for zero_div_zero lint Fix float cmp to use assoc fxx::EPSILON Fix NAN comparison lint to use assoc NAN Refine lint message. Lint on opt.as_ref().map(|x| &**x). Include OpAssign in suspicious_op_assign_impl result_map_or_into_option: fix syntax error in example result_map_or_into: fix dogfood_clippy error => {h,l}int CONTRIBUTING.md: fix broken triage link result_map_or_into_option: fix `cargo dev fmt --check` errors result_map_or_into_option: move arg checks into tuple assignment result_map_or_into_option: add `opt.map_or(None, |_| Some(y))` test result_map_or_into_option: destructure lint tuple or return early result_map_or_into_option: add good and bad examples result_map_or_into_option: explicitly note absence of known problems Downgrade new_ret_no_self to pedantic Downgrade unreadable_literal to pedantic Update CONTRIBUTING.md Rename rustc -> rustc_middle in doc links result_map_or_into_option: add lint to catch manually adpating Result -> Option Move matches test in matches module Run update_lints Make lint modules private Don't filter lints in code generation functions Build lint lists once and the reuse them to update files Get rid of Lint::is_internal method Clean up update_lints Downgrade inefficient_to_string to pedantic Downgrade trivially_copy_pass_by_ref to pedantic Downgrade let_unit_value to pedantic ```` Fixes rust-lang#70993
submodules: update clippy from d342cee to af5940b Changes: ```` Allow UUID style formatting for `inconsistent_digit_grouping` lint rustup rust-lang#70986 rustup rust-lang#69745 Rustup to rust-lang#70913 compare with the second largest instead of the smallest variant Revert "Downgrade new_ret_no_self to pedantic" Check for clone-on-copy in argument positions Check fn header along with decl when suggesting to implement trait Downgrade implicit_hasher to pedantic Move cognitive_complexity to nursery Run fmt and update test Use int assoc consts in MANUAL_SATURATING_ARITHMETIC Use int assoc consts in checked_conversions lint Use primitive type assoc consts in more tests Use integer assoc consts in more lint example code Don't import primitive type modules Use assoc const NAN for zero_div_zero lint Fix float cmp to use assoc fxx::EPSILON Fix NAN comparison lint to use assoc NAN Refine lint message. Lint on opt.as_ref().map(|x| &**x). Include OpAssign in suspicious_op_assign_impl result_map_or_into_option: fix syntax error in example result_map_or_into: fix dogfood_clippy error => {h,l}int CONTRIBUTING.md: fix broken triage link result_map_or_into_option: fix `cargo dev fmt --check` errors result_map_or_into_option: move arg checks into tuple assignment result_map_or_into_option: add `opt.map_or(None, |_| Some(y))` test result_map_or_into_option: destructure lint tuple or return early result_map_or_into_option: add good and bad examples result_map_or_into_option: explicitly note absence of known problems Downgrade new_ret_no_self to pedantic Downgrade unreadable_literal to pedantic Update CONTRIBUTING.md Rename rustc -> rustc_middle in doc links result_map_or_into_option: add lint to catch manually adpating Result -> Option Move matches test in matches module Run update_lints Make lint modules private Don't filter lints in code generation functions Build lint lists once and the reuse them to update files Get rid of Lint::is_internal method Clean up update_lints Downgrade inefficient_to_string to pedantic Downgrade trivially_copy_pass_by_ref to pedantic Downgrade let_unit_value to pedantic ```` Fixes rust-lang#70993 r? @Dylan-DPC
FYI, this seems to have slowed down clean check builds of the |
Oh dear, it makes the stress test for #65510 way worse. That test isn't entirely artificial btw. Also, 5% on |
.into_iter() | ||
.map(|o| o.predicate) | ||
.collect::<Vec<_>>(), |
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.
Ahh I wonder if it's stuff like this - this is very wasteful and unlikely to be needed.
let obligations: Vec<_> = | ||
predicates.into_iter().map(|predicate| predicate_obligation(predicate, None)).collect(); |
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.
Again, this is Vec
-> Vec
, which we should avoid ever doing. I wish I spotted this earlier, oof.
let predicates = obligations.iter().map(|obligation| obligation.predicate).collect(); | ||
let implied_obligations = traits::elaborate_predicates(tcx, predicates); | ||
let implied_obligations = implied_obligations.map(|pred| { | ||
let implied_obligations = traits::util::elaborate_obligations(tcx, obligations.clone()); |
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.
At a glance this seems wasteful but it's not worse than it was before. Presumably we can avoid this clone altogether, but I haven't checked.
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.
The only reason I didn't strip them outright was because of retain
calls in elaborate_predicates
, but if we can change all cases of Vec<Pred>
argument types into impl Iterator<Item = Pred>
, we should be faster than before.
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()).collect(); | ||
util::elaborate_predicates(tcx, unnormalized_env.caller_bounds.to_vec()) | ||
.map(|obligation| obligation.predicate) | ||
.collect(); |
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.
Tempted to try and find every allocation in the trait system and rewrite it.
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.
Are you going to be doing it or should I try and do some of it now?
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 want to play around with it, feel free to! I was mostly considering taking this over in case you don't have time for it.
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 won't have time to look at elaborate_obligations
, which is the one that might have the biggest impact, but I can have a small PR shortly where I'm replacing a bunch of these arguments with impl Iterator<Item = PredicateObligation>
so that it becomes clearer where we're collect
ing multiple times.
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.
Looking at this in closer detail, I think I might be able to simplify this a bit.
@eddyb @ecstatic-morse #71268 seems to get us closer to the previous baseline but I also found a couple of other improvements I might be able to make. |
…ikomatsakis Maintain chain of derived obligations When evaluating the derived obligations from super traits, maintain a reference to the original obligation in order to give more actionable context in the output. Continuation (and built on) rust-lang#69745, subset of rust-lang#69709. r? @eddyb
Remove some `Vec` allocations to improve performance This claws back most of the performance lost in rust-lang#69745. r? @eddyb
Changes: ```` Allow UUID style formatting for `inconsistent_digit_grouping` lint rustup rust-lang/rust#70986 rustup rust-lang/rust#69745 Rustup to rust-lang/rust#70913 compare with the second largest instead of the smallest variant Revert "Downgrade new_ret_no_self to pedantic" Check for clone-on-copy in argument positions Check fn header along with decl when suggesting to implement trait Downgrade implicit_hasher to pedantic Move cognitive_complexity to nursery Run fmt and update test Use int assoc consts in MANUAL_SATURATING_ARITHMETIC Use int assoc consts in checked_conversions lint Use primitive type assoc consts in more tests Use integer assoc consts in more lint example code Don't import primitive type modules Use assoc const NAN for zero_div_zero lint Fix float cmp to use assoc fxx::EPSILON Fix NAN comparison lint to use assoc NAN Refine lint message. Lint on opt.as_ref().map(|x| &**x). Include OpAssign in suspicious_op_assign_impl result_map_or_into_option: fix syntax error in example result_map_or_into: fix dogfood_clippy error => {h,l}int CONTRIBUTING.md: fix broken triage link result_map_or_into_option: fix `cargo dev fmt --check` errors result_map_or_into_option: move arg checks into tuple assignment result_map_or_into_option: add `opt.map_or(None, |_| Some(y))` test result_map_or_into_option: destructure lint tuple or return early result_map_or_into_option: add good and bad examples result_map_or_into_option: explicitly note absence of known problems Downgrade new_ret_no_self to pedantic Downgrade unreadable_literal to pedantic Update CONTRIBUTING.md Rename rustc -> rustc_middle in doc links result_map_or_into_option: add lint to catch manually adpating Result -> Option Move matches test in matches module Run update_lints Make lint modules private Don't filter lints in code generation functions Build lint lists once and the reuse them to update files Get rid of Lint::is_internal method Clean up update_lints Downgrade inefficient_to_string to pedantic Downgrade trivially_copy_pass_by_ref to pedantic Downgrade let_unit_value to pedantic ```` Fixes #70993
Keep more information about trait binding failures. Use more specific spans by pointing at bindings that introduce obligations.
Subset of #69709.
r? @eddyb