Skip to content
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

Refine error span for trait error into borrowed expression #108254

Merged

Conversation

Nathan-Fenner
Copy link
Contributor

Extends the error span refinement in #106477 to drill into borrowed expressions just like tuples/struct/enum literals. For example,

trait Fancy {}
trait Good {}
impl <'a, T> Fancy for &'a T where T: Good {}
impl <S> Good for Option<S> where S: Iterator {}

fn want_fancy<F>(f: F) where F: Fancy {}

fn example() {
    want_fancy(&Some(5));
//  (BEFORE)   ^^^^^^^^ `{integer}` is not an iterator 
//  (AFTER)          ^  `{integer}` is not an iterator
}

Existing heuristics try to find the right part of the expression to "point at"; current heuristics look at e.g. struct constructors and tuples. This PR adds a new check for borrowed expressions when looking into a borrowed type.

@rustbot
Copy link
Collaborator

rustbot commented Feb 20, 2023

r? @WaffleLapkin

(rustbot has picked a reviewer for you, use r? to override)

@rustbot rustbot added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Feb 20, 2023
Copy link
Member

@WaffleLapkin WaffleLapkin left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable. Do you think there are any other expression kinds that we might want to "drill" into?

@WaffleLapkin
Copy link
Member

@bors r+

@bors
Copy link
Contributor

bors commented Feb 20, 2023

📌 Commit fbcca2a has been approved by WaffleLapkin

It is now in the queue for this repository.

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Feb 20, 2023
@Nathan-Fenner
Copy link
Contributor Author

There's a few more expressions that could refine further, but they're all a bit more complicated or less common

  • array literals; one issue is choosing the "best" span, since any/every element may be responsible. In an array like [None, None, Some(4), Some(5)] if the problem is that i32: Iterator fails, should we point at the 4 or the 5?
  • function calls; propagating the same constraints downward is possible in a similar way, though there's similar ambiguities in terms of which thing to highlight if multiple match
  • if/match; could drill into either case, again needing to decide which is "best"

Beyond that I don't think there's as many cases where it's useful, since often you can't point more specifically to some constant/variable that's "at fault" for a missing constraint impl.

bors added a commit to rust-lang-ci/rust that referenced this pull request Feb 20, 2023
…iaskrgr

Rollup of 6 pull requests

Successful merges:

 - rust-lang#108241 (Fix handling of reexported macro in doc hidden items)
 - rust-lang#108254 (Refine error span for trait error into borrowed expression)
 - rust-lang#108255 (Remove old FIXMEs referring to rust-lang#19596)
 - rust-lang#108257 (Remove old FIXME that no longer applies)
 - rust-lang#108276 (small `opaque_type_origin` cleanup)
 - rust-lang#108279 (Use named arguments for `{,u}int_impls` macro)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 194d52c into rust-lang:master Feb 21, 2023
@rustbot rustbot added this to the 1.69.0 milestone Feb 21, 2023
@WaffleLapkin
Copy link
Member

one issue is choosing the "best" span [...]

@Nathan-Fenner one option is to return MultiSpan so that both 4 and 5 are highlighted. Although I see how this can be tricky to implement. Another is to choose the only option if there is only one or fallback to old behaviour if there are multiple.

@WaffleLapkin
Copy link
Member

@Nathan-Fenner I've noticed that with current playground's nightly rustc (1.69.0-nightly (2023-02-26 d962ea5)) your example in the PR description doesn't produce the expected error:

trait Fancy {}
trait Good {}
impl <'a, T> Fancy for &'a T where T: Good {}
impl <S> Good for Option<S> where S: Iterator {}

fn want_fancy<F>(f: F) where F: Fancy {}

fn example() {
    want_fancy(&Some(5));
//  (BEFORE)   ^^^^^^^^ `{integer}` is not an iterator 
//  (AFTER)          ^  `{integer}` is not an iterator
}
error[[E0277]](https://doc.rust-lang.org/nightly/error_codes/E0277.html): `{integer}` is not an iterator
 --> src/lib.rs:9:17
  |
9 |     want_fancy(&Some(5));
  |     ----------  ^^^^^^^ `{integer}` is not an iterator
  |     |
  |     required by a bound introduced by this call
  |
  = help: the trait `Iterator` is not implemented for `{integer}`
  = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
  = help: the trait `Fancy` is implemented for `&'a T`
note: required for `Option<{integer}>` to implement `Good`
 --> src/lib.rs:4:10
  |
4 | impl <S> Good for Option<S> where S: Iterator {}
  |          ^^^^     ^^^^^^^^^          -------- unsatisfied trait bound introduced here
note: required for `&Option<{integer}>` to implement `Fancy`
 --> src/lib.rs:3:14
  |
3 | impl <'a, T> Fancy for &'a T where T: Good {}
  |              ^^^^^     ^^^^^          ---- unsatisfied trait bound introduced here
note: required by a bound in `want_fancy`
 --> src/lib.rs:6:33
  |
6 | fn want_fancy<F>(f: F) where F: Fancy {}
  |                                 ^^^^^ required by this bound in `want_fancy`

[play]

I'm fairly certain this version should include this PR already. Do you have an idea why the error's span is bigger than it should be? (note though that it's still smaller than stable's — stable includes & in the error span, while nightly doesn't)

@Nathan-Fenner
Copy link
Contributor Author

@WaffleLapkin That's a good catch. I think this is actually a regression/miss from #106477 which should have handled this case. I'll take a look at it later - I probably missed some case for the Some constructor, either because it's in the prelude or it's unqualified.

compiler-errors added a commit to compiler-errors/rust that referenced this pull request Mar 2, 2023
…-span-fix-Some, r=WaffleLapkin

Point error span at Some constructor argument when trait resolution fails

This is a follow up to rust-lang#108254 and rust-lang#106477 which extends error span refinement to handle a case which I mistakenly believed was handled in rust-lang#106477. The goal is to refine the error span depicted below:

```rs
trait Fancy {}
impl <T> Fancy for Option<T> where T: Iterator {}

fn want_fancy<F>(f: F) where F: Fancy {}

fn example() {
    want_fancy(Some(5));
//  (BEFORE)   ^^^^^^^ `{integer}` is not an iterator
//  (AFTER)         ^  `{integer}` is not an iterator
}
```

I had used a (slightly more complex) example as an illustrative example in rust-lang#108254 , but hadn't actually turned it into a test, because I had (incorrectly) believed at the time it was covered by existing behavior. It turns out that `Some` is slightly "special" in that it resolves differently from the other `enum` constructors I had tried, and therefore this test was actually broken.

I've now updated the tests to include this example, and fixed the code to correctly resolve the `Some` constructor so that the span of the error is reduced.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 2, 2023
…-span-fix-Some, r=WaffleLapkin

Point error span at Some constructor argument when trait resolution fails

This is a follow up to rust-lang#108254 and rust-lang#106477 which extends error span refinement to handle a case which I mistakenly believed was handled in rust-lang#106477. The goal is to refine the error span depicted below:

```rs
trait Fancy {}
impl <T> Fancy for Option<T> where T: Iterator {}

fn want_fancy<F>(f: F) where F: Fancy {}

fn example() {
    want_fancy(Some(5));
//  (BEFORE)   ^^^^^^^ `{integer}` is not an iterator
//  (AFTER)         ^  `{integer}` is not an iterator
}
```

I had used a (slightly more complex) example as an illustrative example in rust-lang#108254 , but hadn't actually turned it into a test, because I had (incorrectly) believed at the time it was covered by existing behavior. It turns out that `Some` is slightly "special" in that it resolves differently from the other `enum` constructors I had tried, and therefore this test was actually broken.

I've now updated the tests to include this example, and fixed the code to correctly resolve the `Some` constructor so that the span of the error is reduced.
matthiaskrgr added a commit to matthiaskrgr/rust that referenced this pull request Mar 2, 2023
…-span-fix-Some, r=WaffleLapkin

Point error span at Some constructor argument when trait resolution fails

This is a follow up to rust-lang#108254 and rust-lang#106477 which extends error span refinement to handle a case which I mistakenly believed was handled in rust-lang#106477. The goal is to refine the error span depicted below:

```rs
trait Fancy {}
impl <T> Fancy for Option<T> where T: Iterator {}

fn want_fancy<F>(f: F) where F: Fancy {}

fn example() {
    want_fancy(Some(5));
//  (BEFORE)   ^^^^^^^ `{integer}` is not an iterator
//  (AFTER)         ^  `{integer}` is not an iterator
}
```

I had used a (slightly more complex) example as an illustrative example in rust-lang#108254 , but hadn't actually turned it into a test, because I had (incorrectly) believed at the time it was covered by existing behavior. It turns out that `Some` is slightly "special" in that it resolves differently from the other `enum` constructors I had tried, and therefore this test was actually broken.

I've now updated the tests to include this example, and fixed the code to correctly resolve the `Some` constructor so that the span of the error is reduced.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants