Skip to content

exploration: ignoring arrays in method dispatch #84133

Closed

Description

@nikomatsakis

In #65819, we are considering adding an impl of IntoIterator for [T; N] for all N. However, this breaks existing code that relies on method dispatch:

let array = [true; 3];
for x in array.into_iter() {
    let _ = *x; // x is a reference
}

In this code, array.into_iter() winds up unsizing to a slice and hence resolving to <&[bool] as IntoIterator>::into_iter (and thus executing on refs to booleans). This issue describes a possible modification to older Rust editions that would allow us to add the impl without breaking existing code or compromising our edition guarantees.

Activity

  1. nikomatsakis commented on Apr 12, 2021

    @nikomatsakis
    ContributorAuthor

    Proposal summary

    Allow traits to be annotated with #[rustc_skip_array_during_method_dispatch]. This is a perma-unstable annotation and it has the effect that we will ignore a trait method match during method dispatch, but only if the receive is a [T; N] type.

    To use in this case

    #[rustc_skip_array_during_method_dispatch]
    trait IntoIterator { ... }

    Voila.

  2. cuviper commented on Apr 12, 2021

    @cuviper
    Member

    Should that attribute have a parameter for the edition? Or just hard-code that it only applies before 2021?

    I also wonder if it makes more sense on the impl for arrays, rather than the trait itself, but I don't know what that looks like from the perspective of method resolution.

  3. Mark-Simulacrum commented on Apr 12, 2021

    @Mark-Simulacrum
    Member

    Notably we'll also need to decide what to read the edition from - I'd suggest the . but don't feel strongly.

  4. nikomatsakis commented on Apr 12, 2021

    @nikomatsakis
    ContributorAuthor

    Mentoring instructions

    We will modify

    TraitCandidate(trait_ref) => {

    so that -- in older editions -- we look for this attribute on the trait. If that attribute is present, then we check the self_ty variable and see whether it is a [T; N] array type. If so, we return ProbeResult::NoMatch.

    As @Mark-Simulacrum notes, we need to decide what span to use to check the edition. I would propose we use the span from the method name. We can get the span from the method_name field, since it is an Ident and those contain a span. One can then invoke the edition method -- or just rust_2021.

  5. nikomatsakis commented on Apr 12, 2021

    @nikomatsakis
    ContributorAuthor

    @cuviper take a look at those brief mentoring instructions -- that may explain why I chose to put the attribute on the trait. In short, that's the easiest thing we have available to us.

  6. added
    E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.
    on Apr 12, 2021
  7. nikomatsakis commented on Apr 12, 2021

    @nikomatsakis
    ContributorAuthor

    I nominated this for @rust-lang/lang discussion to see how people react to the idea of an edition-related hack of this magnitude. It's worth noting that we could move this to a future-compatibility warning fairly easily and eventually remove it.

  8. cuviper commented on Apr 12, 2021

    @cuviper
    Member

    OK -- I am interested in working on this, but should I wait for that discussion?

  9. nikomatsakis commented on Apr 12, 2021

    @nikomatsakis
    ContributorAuthor

    @cuviper I don't think that's necessary. My guess is that the main question would be whether this is something we eventually phase out and remove, or something we keep forever. Given how small the edits are, I don't see much of an argument for breaking folks immediately when warnings and a transition period are an option.

    I can see an argument for not wanting to keep this change permanently, there is a kind of trade-off there. For example, it is a bit confusing that I can write <[T; N] as IntoIterator>::into_iter(foo) but I can't write foo.into_iter().

  10. cuviper commented on Apr 12, 2021

    @cuviper
    Member

    @rustbot claim

  11. joshtriplett commented on Apr 12, 2021

    @joshtriplett
    Member

    This seems like a great solution to me.
    I wouldn't want to keep this indefinitely; in a new edition, I think we do want into_iter to give an iterator over type T.

  12. 3 remaining items

  13. nikomatsakis commented on Apr 13, 2021

    @nikomatsakis
    ContributorAuthor

    @joshtriplett I'm inclined to agree

  14. cramertj commented on Apr 13, 2021

    @cramertj
    Member

    I think this hack is a good idea, and I think we should do it in this case, but I am worried that we're using our power as language maintainers to sidestep an issue that regularly affects end-users of the language. That is, it is effectively a breaking change to add new methods or trait impls, even though our semantic versioning rules do not consider it to be one. crate maintainers may find that they break downstream users when adding new features that should otherwise not be semver-impacting. I'd love to see steps towards a solution, though admittedly I don't have a great idea what a solution might look like. cfg(version/accessible) is one good step that helps commonly used utility libraries like futures-util and itertools adapt to known overlap issues. For the case of preventing unknown overlap issues, I think there are fewer tools available.

  15. nikomatsakis commented on Apr 14, 2021

    @nikomatsakis
    ContributorAuthor

    @cramertj that sounds quite reasonable to me.

  16. Nichts commented on Apr 22, 2021

    @Nichts

    @cramertj Issues like this seem like the prime example why python has from __future__ import. Could allow us to opt into the new behavior now and make the transition into the next edition easier.

  17. added a commit that references this issue on Apr 28, 2021
  18. added 6 commits that reference this issue on Apr 28, 2021
  19. nikomatsakis commented on May 4, 2021

    @nikomatsakis
    ContributorAuthor

    The PR is merged, I'm going to close this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

E-mentorCall for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion.T-langRelevant to the language teammaybe-future-editionSomething we may consider for a future edition.

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions