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

rustc: Remove all "consider using an explicit lifetime parameter" suggestions #37057

Merged
merged 1 commit into from
Jan 28, 2017

Conversation

brson
Copy link
Contributor

@brson brson commented Oct 9, 2016

These give so many incorrect suggestions that having them is
detrimental to the user experience. The compiler should not be
suggesting changes to the code that are wrong - it is infuriating: not
only is the compiler telling you that you don't understand borrowing,
the compiler itself appears to not understand borrowing. It does not
inspire confidence.

r? @nikomatsakis

@bstrie
Copy link
Contributor

bstrie commented Oct 11, 2016

cc @jonathandturner

@withoutboats
Copy link
Contributor

withoutboats commented Oct 11, 2016

I feel like I've found these helpful many more times than they've been wrong, but the compiler giving wrong advice is indeed a frustrating experience that could cause users to believe that the borrow rules are 'not worth it,' 'not good enough,' 'not correct,' or some other negative thing.

Perhaps in the long term when the compiler could rerun the borrowck pass with the explicit annotations, recurring as necessary (and accumulating all of them to make a single suggestion), and only make the suggestion if the resulting code passes?

To provide a counterargument even to that change (though I think the negative experiences overwhelm this), in complicated (but safe) lifetime wrangling code, I have followed the compiler's suggestions to find the lifetime error I actually needed to solve.

@sophiajt
Copy link
Contributor

sophiajt commented Oct 11, 2016

@withoutboats - do you think it can be fixed rather than being removed?

That is, is there a heuristic for generally when the notes are helpful? Being wrong to me just sounds like a net loss, but if there are times we can detect that they'll be useful and only display them then, that seems like a better improvement than pulling it out altogether

@nikomatsakis
Copy link
Contributor

I think I agree with removing this code. It's bitrotted and dates from a time when the language was quite different (e.g., no 'a: 'b where clauses). The main reason I have not done so, though, is a concern about throwing the baby out with the bathwater.

I know that I have definitely found these suggestions helpful on many occasions. One particularly useful thing they can do is to highlight where there are elided lifetime parameters that you did not know about that are causing you grief.

@nikomatsakis
Copy link
Contributor

That is, is there a heuristic for generally when the notes are helpful? Being wrong to me just sounds like a net loss, but if there are times we can detect that they'll be useful and only display them then, that seems like a better improvement than pulling it out altogether

I gave a sort of "high-level" idea of where I have found them useful, and I know that anecdotally people have told me that they like them, but I think they also mislead a lot. It's a bad sign that e.g. when I see one I usually just ignore it, or I find it's quite common that it's either showing me the same signature I have or making some other non-actionable suggestion. I wish I had more specific examples at hand but I don't. Perhaps if we turn them off we will start to accumulate some, though. =)

That said, I do suspect we could identify the cases where it might be wrong and avoid them. But also the code is (as I wrote before) sort of old and done in a weird way, and I'd rather have a cleaner start. Though I'm not sure what's better. Right now it crawls the HIR and makes modifications and then pretty-prints it, as I recall. We might be able to just do some thing where it finds the parameters whose types can be changed and does a span_label() call with a suggestion and it would be nicer.

@nikomatsakis
Copy link
Contributor

I'd like a bit wider feedback here. cc @rust-lang/docs @rust-lang/compiler

@nrc
Copy link
Member

nrc commented Oct 13, 2016

Sometimes these give good suggestions, but it seems to be at 50% or less for me. I would rather they were fixed rather than thrown out, but I guess throwing out seems like an improvement over the status quo.

@GuillaumeGomez
Copy link
Member

I'm in favor for a deletion for now.

@arielb1
Copy link
Contributor

arielb1 commented Oct 14, 2016

I can sort of read it to get the bounds I want. Maybe we should just dump some of these bounds on the user directly? It does tell me when I get a type parameter missing in a method signature and inferred to something random.

@bors
Copy link
Contributor

bors commented Oct 19, 2016

☔ The latest upstream changes (presumably #37269) made this pull request unmergeable. Please resolve the merge conflicts.

@nikomatsakis nikomatsakis added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools labels Oct 19, 2016
@nagisa
Copy link
Member

nagisa commented Oct 19, 2016

I’m in of a similar mind as @withoutboats: I’ve had a multiple cases where suggestion from this class helped me out to figure out the problem at hand. While the solution in most cases ended up not being exactly what suggestion was telling me to use, it often helped me to understand what the compiler thought under the hood and figure out how my code was wrong easier.

@nikomatsakis
Copy link
Contributor

I feel like what all of us experienced users are saying is: the suggestions per se are not helpful, but they expose helpful information. Seems like we should replace this with something more targeted that does expose that information. I'd feel much better about removing if we had someone dedicated to doing that work --- and I'd love to work with them, "I have thoughts" -- but I am not sure what to do in the interim. I definitely dislike giving misleading or wrong suggestions.

@nikomatsakis
Copy link
Contributor

As a starting point, more examples where the messages were helpful would be good.

@eddyb
Copy link
Member

eddyb commented Oct 19, 2016

@nikomatsakis Lowest cost change (that can be backported to beta) would be adding "This is what a working signature might look like (please report incorrect suggestions at https://github.com/rust-lang/lang/issues):".

@eddyb
Copy link
Member

eddyb commented Oct 23, 2016

@nikomatsakis @jonathandturner See #37363 for an example of a case with an easy fix.

@nikomatsakis
Copy link
Contributor

Had some brief discussion with @brson on IRC. I think both of us are still inclined to remove, unless someone wants to take up the active task of improving. That said, I suspect there are some simple heuristics that would guide us to better suggestions. It would help if we had a corpus of actual errors people encounter in practice.

My biggest hesitation here results from the fact that the base errors do tend to be the worst we give. Another place where a corpus would be ultra-helpful! Most of my attempts to think about improvements get stuck around here, trying to gather up data.

@steveklabnik
Copy link
Member

My thoughts:

  1. False positives here are really bad
  2. I'm not sure how often this is right vs wrong for me, but when it's wrong, it's very wrong.
  3. Misleading new people in this way is brutal
  4. as such, I'd lean towards removal. Not mis-leading people is worth more than the convenience of the compiler suggesting what's right occasionally.
  5. I would also like to see a version of this feature that works, possibly in the way @withoutboats mentions. But until that comes along, better to remove.

@sophiajt
Copy link
Contributor

sophiajt commented Nov 3, 2016

+1 on "remove and file an issue to follow-up with better design"

@peschkaj
Copy link

peschkaj commented Nov 3, 2016

👍 to what Jonathan said

On Thu, Nov 3, 2016, 07:41 Jonathan Turner notifications@github.com wrote:

+1 on "remove and file an issue to follow-up with better design"


You are receiving this because you are on a team that was mentioned.
Reply to this email directly, view it on GitHub
#37057 (comment), or mute
the thread
https://github.com/notifications/unsubscribe-auth/AAEXksPNWVI3nhd-mTIdX1qLkYhbEkeAks5q6fK1gaJpZM4KSDxt
.

Jeremiah Peschka

@withoutboats
Copy link
Contributor

withoutboats commented Nov 3, 2016

I agree with @steveklabnik. I think this feature as is should be removed; I just think suggesting explicit annotations is a good idea to pursue and we shouldn't take the position that we tried this and it doesn't work.

(What I've found rather frustrating recently is that it will suggest adding lifetime annotations to impls of foreign traits. Come on compiler, you know I can't do that.)

@eddyb
Copy link
Member

eddyb commented Nov 3, 2016

What I've found rather frustrating recently is that it will suggest adding lifetime annotations to impls of foreign traits.

#37481 should fix that. Also, rewording the message to make the compiler seem less confident in its suggestions would replace user pain with bug reports along the lines of "compiler suggestion didn't work".

@alexcrichton
Copy link
Member

Sounds like this is leaning towards removal, @brson want to rebase and @nikomatsakis want to r+?

@nikomatsakis
Copy link
Contributor

@alexcrichton yeah, I've been vacillating on how to decide how to reach a decision here. =) But it does seem like the majority of people are in favor of removal, so I'm still inclined to go that way.

@eddyb
Copy link
Member

eddyb commented Nov 11, 2016

I'm worried about the potential fallaciousness of "a redesign from scratch won't have these problems".
In general, I'd prefer we word suggestions as "they might work, if not consider filing an issue".
That way the compiler is not overconfident all the time, the users get to try something and we learn.

@arielb1
Copy link
Contributor

arielb1 commented Nov 12, 2016

@nikomatsakis

I am generally able to read the desired bounds out of the suggestions. I think that just dumping the transitive reduction of the requested lifetime bounds would be OK.

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Dec 30, 2016

So ok I am quite frustrated that this PR is still open. We need to make a decision. Let me summarize as best I can the arguments on either side:

In favor of removal:

  • Suggestion code is old and hard to maintain and it makes false assumptions (i.e., it was written before 'a: 'b was an option, so it will never suggest that)
  • Suggestions are frequently wrong, and that outweights their value. E.g., @steveklabnik writes "as such, I'd lean towards removal. Not mis-leading people is worth more than the convenience of the compiler suggesting what's right occasionally."

In favor of keeping:

  • Many people feel it is right more than it is wrong
  • Even when it is wrong, it can help you to understand what the compiler "is thinking under the hood" (from [@nagisa's comment](While the solution in most cases ended up not being exactly what suggestion was telling me to use, it often helped me to understand what the compiler thought under the hood and figure out how my code was wrong easier.))
  • The general fear that we will not replace it in a timely fashion, or that the replacement will have similar flaws

Some concerns:

  • We don't have a strong "corpus" of realistic errors where this helps and realistic ones where it hurts
    • though there are a series of tests for the feature, which is a start; but they are out of date and only concern the "works" cases

Possible courses of action:

  • Reword to indicate that the suggestion may be wrong and ask users to file bugs, this could help to build a corpus
    • perhaps something like "= note: suggestions are in beta, please leave comments at [this URL]", though that would make more sense if it were placed on a new, improved system
  • Revoke and file a bug for follow-up action (roughly embodied by this PR):
    • perhaps trying to summarize the constraints, per @arielb1's suggestion
    • or perhaps taking the current approach, but being more limited, for example trying to more narrowly target the cases where we know it works (no named lifetimes around, etc)
    • this seems to be the majority of opinion based on existing comments, but certainly not universal

My ideal course of action here would probably be to back out the existing code, but identify someone who is motivated to work on improving it (I'd be happy to mentor). This overlaps with the exiting complaints about lifetime inference errors.

Seem like a reasonable summary?

…gestions

These give so many incorrect suggestions that having them is
detrimental to the user experience. The compiler should not be
suggesting changes to the code that are wrong - it is infuriating: not
only is the compiler telling you that _you don't understand_ borrowing,
_the compiler itself_ appears to not understand borrowing. It does not
inspire confidence.
@brson
Copy link
Contributor Author

brson commented Jan 26, 2017

Tests pass locally.

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Jan 27, 2017

📌 Commit a2735c0 has been approved by nikomatsakis

@nikomatsakis
Copy link
Contributor

OK, this means I have to get serious about planning out improved region errors.

People who contributed to this discussion: if you can please add candidate errors to this etherpad, I would appreciate it. I have been trying to get a good categorization of different classes of errors that occur.

@alexcrichton
Copy link
Member

Testing something, but I plan to reopen

@alexcrichton
Copy link
Member

Yup, originally the PR contained the character "…" which apparently caused homu to choke. I've now updated the PR description to have three literal dots.

wtf homu

@alexcrichton alexcrichton changed the title rustc: Remove all "consider using an explicit lifetime parameter" sug… rustc: Remove all "consider using an explicit lifetime parameter" sug... Jan 27, 2017
@alexcrichton
Copy link
Member

@bors: r=nikomatsakis

@bors
Copy link
Contributor

bors commented Jan 27, 2017

💡 This pull request was already approved, no need to approve it again.

@bors
Copy link
Contributor

bors commented Jan 27, 2017

📌 Commit a2735c0 has been approved by nikomatsakis

@eddyb eddyb changed the title rustc: Remove all "consider using an explicit lifetime parameter" sug... rustc: Remove all "consider using an explicit lifetime parameter" suggestions Jan 27, 2017
@bors
Copy link
Contributor

bors commented Jan 27, 2017

⌛ Testing commit a2735c0 with merge 154c202...

bors added a commit that referenced this pull request Jan 27, 2017
rustc: Remove all "consider using an explicit lifetime parameter" suggestions

These give so many incorrect suggestions that having them is
detrimental to the user experience. The compiler should not be
suggesting changes to the code that are wrong - it is infuriating: not
only is the compiler telling you that _you don't understand_ borrowing,
_the compiler itself_ appears to not understand borrowing. It does not
inspire confidence.

r? @nikomatsakis
@bors
Copy link
Contributor

bors commented Jan 28, 2017

☀️ Test successful - status-appveyor, status-travis
Approved by: nikomatsakis
Pushing 154c202 to master...

@shepmaster
Copy link
Member

shepmaster commented Jan 28, 2017

A recent Stack Overflow question was improved when we added the "consider using an explicit lifetime parameter as shown" error. I thought that the OP wasn't reading the error messages, but perhaps they were simply using beta / nightly (although the timeline gets complicated).

I'm pretty sure this hint is an example of @nikomatsakis comment about "locally right, globally wrong", but making the suggested change in OP's original code helped shift the error message to something else that might be more immediately resolvable.

I've removed external dependencies from that example and added it to the etherpad. I'm sad to see this hint going away, and I look forward to the replacement!

@sophiajt
Copy link
Contributor

@shepmaster - the plan is to replace it with something better. If you have ideas for improvement, I'd love to hear them (since it probably falls to me to help design the replacement)

@nikomatsakis
Copy link
Contributor

@shepmaster thanks for adding that; I definitely want to get started on some replacements right away.

frewsxcv added a commit to frewsxcv/rust that referenced this pull request Feb 20, 2017
…felix

Report full details of inference errors

When the old suggestion machinery was removed by @brson in rust-lang#37057, it was not completely removed. There was a bit of code that had the job of going through errors and finding those for which suggestions were applicable, and it remained, causing us not to emit the full details of such errors.  This PR removes that.

I've also added various lifetime tests to the UI test suite (so you can also see the before/after there). I have some concrete thoughts on how to improve these cases and am planning on writing those up in some mentoring issues (@cengizio has expressed interest in working on those changes, so I plan to work with him on it, at least to start).

cc @jonathandturner
jsonn pushed a commit to jsonn/pkgsrc that referenced this pull request Mar 20, 2017
Version 1.16.0 (2017-03-16)
===========================

Language
--------

* Lifetimes in statics and consts default to `'static`. [RFC 1623]
* [The compiler's `dead_code` lint now accounts for type aliases][38051].
* [Uninhabitable enums (those without any variants) no longer permit wildcard
  match patterns][38069]
* [Clean up semantics of `self` in an import list][38313]
* [`Self` may appear in `impl` headers][38920]
* [`Self` may appear in struct expressions][39282]

Compiler
--------

* [`rustc` now supports `--emit=metadata`, which causes rustc to emit
  a `.rmeta` file containing only crate metadata][38571]. This can be
  used by tools like the Rust Language Service to perform
  metadata-only builds.
* [Levenshtein based typo suggestions now work in most places, while
  previously they worked only for fields and sometimes for local
  variables][38927]. Together with the overhaul of "no
  resolution"/"unexpected resolution" errors (#[38154]) they result in
  large and systematic improvement in resolution diagnostics.
* [Fix `transmute::<T, U>` where `T` requires a bigger alignment than
  `U`][38670]
* [rustc: use -Xlinker when specifying an rpath with ',' in it][38798]
* [`rustc` no longer attempts to provide "consider using an explicit
  lifetime" suggestions][37057]. They were inaccurate.

Stabilized APIs
---------------

* [`VecDeque::truncate`]
* [`VecDeque::resize`]
* [`String::insert_str`]
* [`Duration::checked_add`]
* [`Duration::checked_sub`]
* [`Duration::checked_div`]
* [`Duration::checked_mul`]
* [`str::replacen`]
* [`str::repeat`]
* [`SocketAddr::is_ipv4`]
* [`SocketAddr::is_ipv6`]
* [`IpAddr::is_ipv4`]
* [`IpAddr::is_ipv6`]
* [`Vec::dedup_by`]
* [`Vec::dedup_by_key`]
* [`Result::unwrap_or_default`]
* [`<*const T>::wrapping_offset`]
* [`<*mut T>::wrapping_offset`]
* `CommandExt::creation_flags`
* [`File::set_permissions`]
* [`String::split_off`]

Libraries
---------

* [`[T]::binary_search` and `[T]::binary_search_by_key` now take
  their argument by `Borrow` parameter][37761]
* [All public types in std implement `Debug`][38006]
* [`IpAddr` implements `From<Ipv4Addr>` and `From<Ipv6Addr>`][38327]
* [`Ipv6Addr` implements `From<[u16; 8]>`][38131]
* [Ctrl-Z returns from `Stdin.read()` when reading from the console on
  Windows][38274]
* [std: Fix partial writes in `LineWriter`][38062]
* [std: Clamp max read/write sizes on Unix][38062]
* [Use more specific panic message for `&str` slicing errors][38066]
* [`TcpListener::set_only_v6` is deprecated][38304]. This
  functionality cannot be achieved in std currently.
* [`writeln!`, like `println!`, now accepts a form with no string
  or formatting arguments, to just print a newline][38469]
* [Implement `iter::Sum` and `iter::Product` for `Result`][38580]
* [Reduce the size of static data in `std_unicode::tables`][38781]
* [`char::EscapeDebug`, `EscapeDefault`, `EscapeUnicode`,
  `CaseMappingIter`, `ToLowercase`, `ToUppercase`, implement
  `Display`][38909]
* [`Duration` implements `Sum`][38712]
* [`String` implements `ToSocketAddrs`][39048]

Cargo
-----

* [The `cargo check` command does a type check of a project without
  building it][cargo/3296]
* [crates.io will display CI badges from Travis and AppVeyor, if
  specified in Cargo.toml][cargo/3546]
* [crates.io will display categories listed in Cargo.toml][cargo/3301]
* [Compilation profiles accept integer values for `debug`, in addition
  to `true` and `false`. These are passed to `rustc` as the value to
  `-C debuginfo`][cargo/3534]
* [Implement `cargo --version --verbose`][cargo/3604]
* [All builds now output 'dep-info' build dependencies compatible with
  make and ninja][cargo/3557]
* [Build all workspace members with `build --all`][cargo/3511]
* [Document all workspace members with `doc --all`][cargo/3515]
* [Path deps outside workspace are not members][cargo/3443]

Misc
----

* [`rustdoc` has a `--sysroot` argument that, like `rustc`, specifies
  the path to the Rust implementation][38589]
* [The `armv7-linux-androideabi` target no longer enables NEON
  extensions, per Google's ABI guide][38413]
* [The stock standard library can be compiled for Redox OS][38401]
* [Rust has initial SPARC support][38726]. Tier 3. No builds
  available.
* [Rust has experimental support for Nvidia PTX][38559]. Tier 3. No
  builds available.
* [Fix backtraces on i686-pc-windows-gnu by disabling FPO][39379]

Compatibility Notes
-------------------

* [Uninhabitable enums (those without any variants) no longer permit wildcard
  match patterns][38069]
* In this release, references to uninhabited types can not be
  pattern-matched. This was accidentally allowed in 1.15.
* [The compiler's `dead_code` lint now accounts for type aliases][38051].
* [Ctrl-Z returns from `Stdin.read()` when reading from the console on
  Windows][38274]
* [Clean up semantics of `self` in an import list][38313]

[37057]: rust-lang/rust#37057
[37761]: rust-lang/rust#37761
[38006]: rust-lang/rust#38006
[38051]: rust-lang/rust#38051
[38062]: rust-lang/rust#38062
[38062]: rust-lang/rust#38622
[38066]: rust-lang/rust#38066
[38069]: rust-lang/rust#38069
[38131]: rust-lang/rust#38131
[38154]: rust-lang/rust#38154
[38274]: rust-lang/rust#38274
[38304]: rust-lang/rust#38304
[38313]: rust-lang/rust#38313
[38314]: rust-lang/rust#38314
[38327]: rust-lang/rust#38327
[38401]: rust-lang/rust#38401
[38413]: rust-lang/rust#38413
[38469]: rust-lang/rust#38469
[38559]: rust-lang/rust#38559
[38571]: rust-lang/rust#38571
[38580]: rust-lang/rust#38580
[38589]: rust-lang/rust#38589
[38670]: rust-lang/rust#38670
[38712]: rust-lang/rust#38712
[38726]: rust-lang/rust#38726
[38781]: rust-lang/rust#38781
[38798]: rust-lang/rust#38798
[38909]: rust-lang/rust#38909
[38920]: rust-lang/rust#38920
[38927]: rust-lang/rust#38927
[39048]: rust-lang/rust#39048
[39282]: rust-lang/rust#39282
[39379]: rust-lang/rust#39379
[`<*const T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
[`<*mut T>::wrapping_offset`]: https://doc.rust-lang.org/std/primitive.pointer.html#method.wrapping_offset
[`Duration::checked_add`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_add
[`Duration::checked_div`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_div
[`Duration::checked_mul`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_mul
[`Duration::checked_sub`]: https://doc.rust-lang.org/std/time/struct.Duration.html#method.checked_sub
[`File::set_permissions`]: https://doc.rust-lang.org/std/fs/struct.File.html#method.set_permissions
[`IpAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_ipv4
[`IpAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.IpAddr.html#method.is_ipv6
[`Result::unwrap_or_default`]: https://doc.rust-lang.org/std/result/enum.Result.html#method.unwrap_or_default
[`SocketAddr::is_ipv4`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv4
[`SocketAddr::is_ipv6`]: https://doc.rust-lang.org/std/net/enum.SocketAddr.html#method.is_ipv6
[`String::insert_str`]: https://doc.rust-lang.org/std/string/struct.String.html#method.insert_str
[`String::split_off`]: https://doc.rust-lang.org/std/string/struct.String.html#method.split_off
[`Vec::dedup_by_key`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by_key
[`Vec::dedup_by`]: https://doc.rust-lang.org/std/vec/struct.Vec.html#method.dedup_by
[`VecDeque::resize`]:  https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.resize
[`VecDeque::truncate`]: https://doc.rust-lang.org/std/collections/vec_deque/struct.VecDeque.html#method.truncate
[`str::repeat`]: https://doc.rust-lang.org/std/primitive.str.html#method.repeat
[`str::replacen`]: https://doc.rust-lang.org/std/primitive.str.html#method.replacen
[cargo/3296]: rust-lang/cargo#3296
[cargo/3301]: rust-lang/cargo#3301
[cargo/3443]: rust-lang/cargo#3443
[cargo/3511]: rust-lang/cargo#3511
[cargo/3515]: rust-lang/cargo#3515
[cargo/3534]: rust-lang/cargo#3534
[cargo/3546]: rust-lang/cargo#3546
[cargo/3557]: rust-lang/cargo#3557
[cargo/3604]: rust-lang/cargo#3604
[RFC 1623]: https://github.com/rust-lang/rfcs/blob/master/text/1623-static.md
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-docs Area: documentation for any part of the project, including the compiler, standard library, and tools relnotes Marks issues that should be documented in the release notes of the next release. 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.