-
Notifications
You must be signed in to change notification settings - Fork 13.6k
Closed
Labels
A-edition-2021Area: The 2021 editionArea: The 2021 editionE-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Description
The 2021 Edition plans to have a new prelude, which will include a number of new traits. This means that new methods will be in scope which could introduce ambiguities into some code bases if they are using methods with the same name (but from different traits). We need a migration lint that detects such cases and suggests a rewrite into fully qualified form: e.g., x.foo()
would become something like Trait::foo(&x)
.
Metadata
Metadata
Assignees
Labels
A-edition-2021Area: The 2021 editionArea: The 2021 editionE-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
Type
Projects
Milestone
Relationships
Development
Select code repository
Activity
nikomatsakis commentedon Apr 26, 2021
@rustbot assign @djc
I believe @djc was planning to write mentoring instructions here, so I'm assigning to them. We discussed it a bit on zulip; my plan and @djc's somewhat simpler plan. Either of these seem great to me.
djc commentedon May 1, 2021
The latest version of this is now in RFC 3114 (rendered).
nikomatsakis commentedon May 24, 2021
Here are the instructions written in RFC 3114:
Migration Lint
As for all edition changes, we will implement a migration lint to detect cases where code would break in the new edition. It includes a MachineApplicable suggestion for an alternative that will work in both the current and next edition.
The migration lint will be implemented as follows:
This can be done either by hardcoding these method names or by setting up some
kind of registry through the use of an attribute on the relevant traits.
core
orstd
(and/or does notmatch the originating trait), and
foo.try_into()
toTryInto::try_into(foo)
). If necessary, additional levels of (de)referencingmight be needed to match the implementing type of the target trait.
Currently, diagnostics for trait methods that are not in scope suggest importing the originating trait. For traits that have become part of the prelude in a newer edition, the diagnostics should be updated such that they suggest upgrading to the latest edition as an alternative to importing the relevant trait.
nikomatsakis commentedon May 24, 2021
Here are some mentoring instructions for how to do this.
To start, I would go with hard-coding the names of the methods for now. It's easier. Those methods are the methods from
TryFrom
,TryInto
, andFromIterator
.The method call resolution is is n the
rustc_typeck::check::method
module:rust/compiler/rustc_typeck/src/check/method/mod.rs
Lines 170 to 192 in ef0ec30
The call to
lookup_probe
is what selects which method is being invoked:rust/compiler/rustc_typeck/src/check/method/mod.rs
Lines 198 to 199 in ef0ec30
We want to check if the method name is in the desired set of methods. The method name can be found in
segment.ident
, it is anIdent
. You can add thetry_from
,try_into
idents etc in this table:rust/compiler/rustc_span/src/symbol.rs
Lines 105 to 123 in ef0ec30
similar to how we already have
as_str
etc.You can then compare
segment.ident
againstsym::try_from
etc to see if the method has the desired name.Assuming it does, we want to see if the method being invoked is from a trait in libstd/libcore. If it is, we don't have to give a warning, since we are already using the method we expect. Otherwise, we should.
To determine what method is being invoked, we want to check the
PickResult
which, ifOk
, contains aPick
. This contains a fieldkind
that has aPickKind
--PickKind::Trait
corresponds to our case.We then check the
item
field to see what is invoked. If theitem.def_id
field comes from libstd or libcore, then no warning is required. You can determine that by checking thekrate
field of theDefId
. Get thecstore
from the tcx or something. (I'm not actually 100% sure the best way to do this step.)nikomatsakis commentedon May 24, 2021
@rustbot release-assignment
jam1garner commentedon May 24, 2021
@rustbot claim
future_prelude_collision
lint #85707jam1garner commentedon May 26, 2021
Currently the big issue on the PR is that a majority of the breaking changes (by cases to handle, likely not by how common it is) look involve associated functions and thus something like this:
The part of typeck we were looking at only handles dot-call syntax and can only handle
try_into
(as it's the only method). When I get back to this I'm going to start looking for where associated functions are looked up for a given path during type checking, as that'd likely be a good place to target handling the associated function for the lint.nikomatsakis commentedon May 27, 2021
@jam1garner ah, good catch, I didn't consider this case. It should be relatively easy to manage this as well.
5 remaining items