-
Notifications
You must be signed in to change notification settings - Fork 13.3k
Add a new mismatched-lifetime-syntaxes
lint
#138677
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
base: master
Are you sure you want to change the base?
Add a new mismatched-lifetime-syntaxes
lint
#138677
Conversation
r? @wesleywiser rustbot has assigned @wesleywiser. Use |
This comment has been minimized.
This comment has been minimized.
Thanks to:
|
478a98e
to
e15c083
Compare
This comment has been minimized.
This comment has been minimized.
e15c083
to
ca86221
Compare
mismatched_elided_lifetime_styles
lintmismatched-lifetime-syntaxes
lint
This comment has been minimized.
This comment has been minimized.
ca86221
to
6b4ba02
Compare
This comment has been minimized.
This comment has been minimized.
☔ The latest upstream changes (presumably #138719) made this pull request unmergeable. Please resolve the merge conflicts. |
6b4ba02
to
7ff70d4
Compare
Some changes occurred to the CTFE machinery
cc @davidtwco, @compiler-errors, @TaKO8Ki Some changes occurred in exhaustiveness checking cc @Nadrieril Some changes occurred to MIR optimizations cc @rust-lang/wg-mir-opt |
This comment has been minimized.
This comment has been minimized.
7ff70d4
to
3a95f66
Compare
Some changes occurred in src/tools/clippy cc @rust-lang/clippy |
This comment has been minimized.
This comment has been minimized.
3a95f66
to
1625496
Compare
This comment has been minimized.
This comment has been minimized.
1625496
to
1cd8999
Compare
☔ The latest upstream changes (presumably #138965) made this pull request unmergeable. Please resolve the merge conflicts. |
85b9c5a
to
573f332
Compare
This comment has been minimized.
This comment has been minimized.
573f332
to
702e59d
Compare
☔ The latest upstream changes (presumably #139336) made this pull request unmergeable. Please resolve the merge conflicts. |
e5616d0
to
e6dafb6
Compare
☔ The latest upstream changes (presumably #139826) made this pull request unmergeable. Please resolve the merge conflicts. |
e6dafb6
to
5611e54
Compare
☔ The latest upstream changes (presumably #139938) made this pull request unmergeable. Please resolve the merge conflicts. |
5611e54
to
8d56830
Compare
r? compiler |
☔ The latest upstream changes (presumably #140581) made this pull request unmergeable. Please resolve the merge conflicts. |
8d56830
to
9da1ebb
Compare
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.
@rustbot author
|
||
struct S(u8); | ||
|
||
fn named_ref_to_hidden_ref<'a>(v: &'a u8) -> &u8 { |
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 named to elided.
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 do not agree that this test name should be changed.
These test names are based on the syntax used, not the behavior. If they were not, there would be no naming scheme to disambiguate these materially different cases:
fn named_ref_to_elided_ref<'a>(v: &'a u8) -> &u8
fn named_ref_to_elided_ref<'a>(v: &'a u8) -> &'_ u8
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.
That enum was added recently by you as part of this same work. I'd probably recommend changing that as well. Otherwise it's going to be one of those continually confusing areas where the compiler and the lang team / Reference disagree about terminology.
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 lang team reviews UI tests to evaluate stabilizations and for other such purposes. If we want to actually use the terms differently between how we've decided to use them on the lang side and how we use them in the compiler, I feel like we're going to need to write this down carefully somewhere and then cite it widely in all the places we divergently use these terms.
(I'd prefer we find a way to avoid that and to either use the same terms to mean the same things or, if we can't align our concepts, at least to use non-overlapping terms.)
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.
That enum was added recently by you as part of this same work
Yes. The only reason it's not part of this PR is that it was blocking other compiler contributors and was extracted to a separate PR. I link to it as a listing of the choices available, not to prove its authoritativeness.
one of those continually confusing areas where the compiler and the lang team / Reference disagree about terminology
I see the point and wish there were not confusion, but there are two related yet different concepts:
- What the user typed / what the source code shows (what I'm calling "syntax")
- The higher-level meaning (what I'm calling "style")
I assert that using the same name for the syntax of &T
and &'_ T
will likely be confusing to users 1 and will almost certainly be confusing to compiler developers. That's why I've chosen the implementation path of having the two enums (LifetimeSyntax
, LifetimeSource
) as the primary representation through the compiler and restricted the confusing meaning to the lint.
User-facing parts of the lint (the documentation, lint messages) should indeed use the lang-team-decided terminology of named/elided/hidden where needed.
For my own part (which I don't think I've done a good job expressing), I think that saying that fn x(&u8) -> ContainsLifetime
has one "elided lifetime" and one "hidden lifetime" when the action of lifetime elision occurs equally for both will already confuse users 2.
I'd prefer we find a way to avoid that and to either use the same terms to mean the same things or, if we can't align our concepts, at least to use non-overlapping terms.
That would be wonderful, but I'm not seeing how to align the terms completely because of the intrinsic differences. The source code allows for the product of {Reference, Path} ✕ {NoSyntax, AnonymousLifetime, NamedLifetime}
but meaning-wise we group it as
(Reference, NoSyntax)
/(Reference, AnonymousLifetime)
/(Path, AnonymousLifetime)
("elided")(Path, NoSyntax)
("hidden")(Reference, NamedLifetime)
/(Path, NamedLifetime)
("named")
At least until the HIR level, I argue that the compiler should correspond to what the user entered.
Footnotes
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 the concern is syntactic, and you want to apply the same categorization to both references and paths, I'd suggest that either can have an "explicit" lifetime parameter (e.g. &'a ()
, &'_ ()
, Ref<'a>
, Ref<'_>
) or an "implicit" one (e.g. &()
, Ref
), and that explicit lifetime parameters can be either a "bound" lifetime (e.g. &'a ()
, Ref<'a>
), the "anonymous" one (e.g. &'_ ()
, Ref<'_>
), or 'static
.
ContainsLifetime(v) | ||
} | ||
|
||
fn hidden_path_to_hidden_ref(v: ContainsLifetime) -> &u8 { |
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 a mismatch and should fire the lint.
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.
Will fix.
v | ||
} | ||
|
||
fn hidden_ref_to_hidden_path(v: &u8) -> ContainsLifetime { |
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 a mismatch and should fire the lint.
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.
Will fix.
tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs
Show resolved
Hide resolved
Reminder, once the PR becomes ready for a review, use |
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 haven't been able to address the corrections I agree with, but wanted to comment quickly in an attempt to reduce the month-long review cycle by a few hours.
tests/ui/lifetimes/lifetime-errors/ex1-return-one-existing-name-if-else-using-impl-3.rs
Show resolved
Hide resolved
|
||
struct S(u8); | ||
|
||
fn named_ref_to_hidden_ref<'a>(v: &'a u8) -> &u8 { |
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 do not agree that this test name should be changed.
These test names are based on the syntax used, not the behavior. If they were not, there would be no naming scheme to disambiguate these materially different cases:
fn named_ref_to_elided_ref<'a>(v: &'a u8) -> &u8
fn named_ref_to_elided_ref<'a>(v: &'a u8) -> &'_ u8
ContainsLifetime(v) | ||
} | ||
|
||
fn hidden_path_to_hidden_ref(v: ContainsLifetime) -> &u8 { |
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.
Will fix.
v | ||
} | ||
|
||
fn hidden_ref_to_hidden_path(v: &u8) -> ContainsLifetime { |
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.
Will fix.
The lang-team discussed this and I attempted to summarize their decision. The summary-of-the-summary is:
Using two different kinds of syntax for elided lifetimes is confusing. In rare cases, it may even lead to unsound code! Some examples:
Matching up references with no lifetime syntax, references with anonymous lifetime syntax, and paths with anonymous lifetime syntax is an exception to the simplest possible rule:
Having a lint for consistent syntax of elided lifetimes will make the future goal of warning-by-default for paths participating in elision much simpler.
This new lint attempts to accomplish the goal of enforcing consistent syntax. In the process, it supersedes and replaces the existing
elided-named-lifetimes
lint, which means it starts out life as warn-by-default.