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

Make deleted code in a suggestion clearer #86532

Merged
merged 2 commits into from
Aug 11, 2021

Conversation

estebank
Copy link
Contributor

@estebank estebank commented Jun 22, 2021

Show suggestions that include deletions in a way similar to diff's output.

For changes that do not have deletions, use + as an underline for additions and ~ as an underline for replacements.

For multiline suggestions, we now use ~ in the gutter to signal replacements and + to signal whole line replacements/additions.

In all cases we now use color to highlight the specific spans and snippets.

@rust-highfive
Copy link
Collaborator

r? @petrochenkov

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 22, 2021
@Nicholas-Baron
Copy link
Contributor

I personally view the narrow end of an arrow as a destination to insert some items.
Thus, the bottom line of that error message would something look like

fn foo(&self, _ : &impl Debug) { }
     \/

However, I do get the choice of /\ from an aesthetic perspective (e.g. looks like the ^).
Another idea may be using red for the /\ to signify deletion, which seems to be a common cross-platform idiom.

@iago-lito
Copy link
Contributor

iago-lito commented Jun 22, 2021

Just thinking.. what about making it clearer with underline+overline, to avoid @Nicholas-Baron "insert location" interpretation?

      \/             (* snip! *)
fn next(&mut self)
      /\

@petrochenkov petrochenkov added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 22, 2021
@jieyouxu
Copy link
Member

Adding to the bikeshed...

help: try removing the generic parameter and using `impl Trait` instead
  |
8 |         fn foo(&self, _: &impl Debug) { }
  |              --           ++++++++++

Red for deletions -, green for additions +, perhaps like diffs? This has the advantage of showing clearly what's added and should be easier to compute the width for, though the - symbol is already to highlight.

Screen Shot 2021-06-22 at 20 15 19

Maybe use x to signal deletions?

Screen Shot 2021-06-22 at 20 11 56

Maybe even highlight what the user should try to add?

Screen Shot 2021-06-22 at 20 12 34

@bjorn3
Copy link
Member

bjorn3 commented Jun 22, 2021

Maybe even highlight what the user should try to add?

The code used to be the same color as the highlights below it, but was changed to be the default color at some point.

@camsteffen
Copy link
Contributor

Another idea:
image

@bjorn3
Copy link
Member

bjorn3 commented Jun 22, 2021

That doesn't work without colors. Think about a color blind person or copy pasted error messages.

@camsteffen
Copy link
Contributor

I think it works without colors.

 help: try removing the generic parameter and using `impl Trait` instead
   |
 8 |         fn foo(&self, _: &impl Debug){ }
   |              ><          >++++++++++<

@bjorn3
Copy link
Member

bjorn3 commented Jun 22, 2021

Oh, the > and < are outside of the inserted range instead of inside. That is somewhat non-obvious.

@estebank
Copy link
Contributor Author

estebank commented Jun 22, 2021

The other option is to keep the removed code and give it a red background or color, and a different underline, like was proposed above so that it still works with colorless output:

help: try removing the generic parameter and using `impl Trait` instead
  |
8 |         fn foo<U: Debug>(&self, _: &impl Debug) { }
  |               xxxxxxxxxx            ++++++++++

What we lose with that is the ability to just copy and paste the code from the terminal (although I doubt that's a common occurrence).

@camsteffen
Copy link
Contributor

Oh, the > and < are outside of the inserted range instead of inside. That is somewhat non-obvious.

Yeah. On second thought I don't think I would use >+< for inserted code.

I think that >< may be more intuitive than /\ for deleted code. Neither seems clearly better to me.

keep the removed code

I don't like that option personally. I would like the output to show exactly what the code looks like after applying the suggestion. I can compare with the current version of the code in the first error message.

@tlyu
Copy link
Contributor

tlyu commented Jun 22, 2021

I think /\ looks too much like a proofreader's mark for insertion, so using it to signify deletion seems like a bad idea. Also, I'm not sure it always renders as a legible arrow or caret type appearance in all likely terminal fonts.

I kind of like >< because it looks like it's pointing to the empty space where the deleted text used to be.

There seems to be a suggestion for electronic texts to use marks including % to signify deletion, because of the visual similarity to the traditional handwritten proofreader's mark. For our case, that would have to go inline with the old text that we're suggesting deleting, which is probably not something we want.

Another possibility is to use inline comments like /* deleted */ to signify the deletion, or even just surround the deleted text with an inline comment. Drawbacks include less familiarity with this style of comment (it doesn't seem to be the prevailing style, and rarely appears in tutorial material) and repetition of the deleted text (if we use the "comment out the deleted text" approach).

@estebank
Copy link
Contributor Author

estebank commented Jun 22, 2021

I would like the output to show exactly what the code looks like after applying the suggestion. I can compare with the current version of the code in the first error message.

That's been my personal take, but I've encountered enough people that have gotten confused by it that it's making me reconsider my stance for the projects sake.


The problem I see with using + for the underline is that if we are replacing text it doesn't convey the right message, as we are not informing the user that the replacement occurred. That being said:

Screen Shot 2021-06-22 at 11 04 02 AM


Edit: implemented one of the proposals keeping deletions around (which is buggy, but gives an idea of what it'd look like):

Screen Shot 2021-06-22 at 11 37 11 AM

@camsteffen
Copy link
Contributor

The problem I see with using + for the underline is that if we are replacing text it doesn't convey the right message, as we are not informing the user that the replacement occurred.

I'm convinced on that. It looks like diff output but the semantics are different. That's confusing.

@Artoria2e5
Copy link
Contributor

While we’re at it with the red mark, maybe a strikethrough can be tried too? The \e[9 stuff, not the Unicode hack.

@estebank
Copy link
Contributor Author

While we’re at it with the red mark, maybe a strikethrough can be tried too? The \e[9 stuff, not the Unicode hack.

We use termcolor which doesn't have support to specify strikethrough.

Using unicode, I have this mockup. Please ignore the obvious bugs with color positions:

Screen Shot 2021-06-22 at 11 56 08 AM

I don't know if the strikethrough will help that much.

@tlyu
Copy link
Contributor

tlyu commented Jun 22, 2021

While we’re at it with the red mark, maybe a strikethrough can be tried too? The \e[9 stuff, not the Unicode hack.

I think that ANSI terminal strikethrough capability isn't widely supported? Also, I think it's important that any annotations survive copying and pasting, especially because we often ask people to copy and paste full error messages when they ask about compiler errors.

@tlyu
Copy link
Contributor

tlyu commented Jun 22, 2021

The problem I see with using + for the underline is that if we are replacing text it doesn't convey the right message, as we are not informing the user that the replacement occurred.

I'm convinced on that. It looks like diff output but the semantics are different. That's confusing.

I agree. Maybe ~ as an underline for changes? (It's similar to the proofreader's mark for transposition, which is a bit of a stretch but close enough, I think.) [edit: also, I think the existing ^ underline for insertions/changes is probably good enough, and it doesn't have the association with diff that + would]

@tlyu
Copy link
Contributor

tlyu commented Jun 22, 2021

I would like the output to show exactly what the code looks like after applying the suggestion. I can compare with the current version of the code in the first error message.

That's been my personal take, but I've encountered enough people that have gotten confused by it that it's making me reconsider my stance for the projects sake.

I think if we're going to leave the deleted text inline, I'm leaning toward surrounding it with a /* */ comment.

@estebank
Copy link
Contributor Author

Three other options. I'm partial to the second one, but the first one looks easier to understand what's going on.

Screen Shot 2021-06-22 at 4 10 49 PM

Screen Shot 2021-06-22 at 4 17 49 PM

Screen Shot 2021-06-22 at 4 24 11 PM

@estebank
Copy link
Contributor Author

Current output for this PR:

Screen Shot 2021-06-22 at 4 58 54 PM

@JohnTitor
Copy link
Member

Three other options. I'm partial to the second one, but the first one looks easier to understand what's going on.

I'm worried that how the first looks like with --color=never. The second and the current look nice to me.

@jieyouxu
Copy link
Member

Current output for this PR:

Screen Shot 2021-06-22 at 4 58 54 PM

I also like this current output. I would like to summarize some UX considerations presented in the
discussions prior that I believe contributes to good suggestion UX:

  • The replacement suggestion should be valid Rust code (or at least a step towards that
    direction) which guides the user towards a proper solution. This is the case with not leaving the
    removed spans behind in the suggestion.
  • The deletion sigil used (~) corresponds well to spell check errors (squiggly/wave-y underlines)
    commonly used by word processors, editors and browsers to hint that a "suggested replacement" is
    available; this can perhaps be more newcomer-friendly due to familiarity. I also think that
    - might collide with its use to indicate location; can be confusing especially without colors. I
    also agree that + can be ambiguous cf. diffs.

  • Different sigils are used (~ for deletion, ^ for addition) that are able to clearly
    distinguish between additions and deletions without relying on colors (friendly for those who
    are colorblind). For example:
help:  try removing the generic parameter and using `impl Trait` instead
  |
8 |         fn foo  (&self, _: &impl Debug) { }
  |               ~~            ^^^^^^^^^^
  • Simple ASCII characters used without exotic whitespace or other symbols; easy for user to type
    out and copy, wide range of terminal/editor/IDE support. The additional advantage of having
    simpler underlines such as ~~~ and ^^^ is that it should be easier to compute their respective
    spans.
  • The selected sigils also works next to each other reasonably well (contrived example...
    since currently presented mockups don't have addition/deletion spans next to each other):
help:  an interesting error message
  |
2 |     let x: u64 = 0;
  |             ~^

(On a side note, how would the addition/deletion underlines be handled if their spans overlap or
are neighbouring?)

@bjorn3
Copy link
Member

bjorn3 commented Jun 23, 2021

help:  an interesting error message
  |
2 |     let x: u64 = 0;
  |             ~^

Gcc uses the exact same squiggles for a different purpose:

<source>: In function 'int square(int)':
<source>:3:18: error: 'foo' was not declared in this scope
    3 |     return num * foo;
      |                  ^~~

or

<source>: In function 'int square(int)':
<source>:5:16: error: no match for 'operator*' (operand types are 'int' and 'Foo')
    5 |     return num * Foo{};
      |            ~~~ ^ ~~~~~
      |            |     |
      |            int   Foo

For reference this is what gcc uses for insertions:

<source>:5:16: error: stray '@' in program
    5 |     return num @ Foo{};
      |                ^
<source>: In function 'int square(int)':
<source>:5:15: error: expected ';' before 'Foo'
    5 |     return num @ Foo{};
      |               ^  ~~~
      |               ;

and clang:

<source>:5:15: error: expected ';' after return statement
    return num @ Foo{};
              ^
              ;
1 error generated.

@iago-lito
Copy link
Contributor

I agree with the following principles to stick to:

  • A. Replacement suggestion is valid rust code
    • A.1 If possible well-formatted.
  • B Deletion and insertion can be read without colors, colors is only a bonus.
  • C No fancy unicode chars or terminal strikethrough.
  • D Attach neat semantics to the chars used to delimitate deleted/added/changed regions
    • D.1 Yet don't conflict with usual diff semantics.

Then what about :
regular

With red >< for deletion, blue ~ for edition and green ^ for addition.

The only problem I see is possible overlap, in which case I would only derogate to A.1 and fix the overlap with additional whitespace, e.g.:
Additional whitespace

@bors bors added S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Aug 11, 2021
@flip1995
Copy link
Member

@estebank blessing the Clippy tests with ./x.py test src/tools/clippy --bless worked for me. Using --stage 2 shouldn't be necessary for this, but that shouldn't be the problem here...

Anyway, here's a gist of the Clippy patch

@estebank
Copy link
Contributor Author

@flip1995 thanks for checking! Somehow I changed branches some time back without realizing and that's why --stage 2 --bless wasn't working for me 🤦‍♂️

@bors r=petrochenkov rollup=never p=1

@bors
Copy link
Contributor

bors commented Aug 11, 2021

📌 Commit 657caa5 has been approved by petrochenkov

@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 Aug 11, 2021
@bors
Copy link
Contributor

bors commented Aug 11, 2021

⌛ Testing commit 657caa5 with merge d8036c085d6934bf52caa7b9ab656f95a31c1616...

@bors
Copy link
Contributor

bors commented Aug 11, 2021

💥 Test timed out

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

@bors retry

@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 Aug 11, 2021
@rust-log-analyzer
Copy link
Collaborator

A job failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

@bors
Copy link
Contributor

bors commented Aug 11, 2021

⌛ Testing commit 657caa5 with merge ccffcaf...

@bors
Copy link
Contributor

bors commented Aug 11, 2021

☀️ Test successful - checks-actions
Approved by: petrochenkov
Pushing ccffcaf to master...

@bors bors added the merged-by-bors This PR was explicitly merged by bors. label Aug 11, 2021
@bors bors merged commit ccffcaf into rust-lang:master Aug 11, 2021
@rustbot rustbot added this to the 1.56.0 milestone Aug 11, 2021
flip1995 pushed a commit to flip1995/rust that referenced this pull request Aug 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
merged-by-bors This PR was explicitly merged by bors. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.