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

indexing is invariant with respect to key #46060

Closed
nikomatsakis opened this issue Nov 17, 2017 · 6 comments
Closed

indexing is invariant with respect to key #46060

nikomatsakis opened this issue Nov 17, 2017 · 6 comments
Assignees
Labels
A-type-system Area: Type system C-enhancement Category: An issue proposing an enhancement or a PR with one. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. S-types-deferred Status: Identified as a valid potential future enhancement that is not currently being worked on T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@nikomatsakis
Copy link
Contributor

nikomatsakis commented Nov 17, 2017

The [] operator is treated as invariant with respect to the key type. We should allow subtyping, I think. Consider this example:

#![allow(warnings)]

use std::collections::HashMap;
use std::ops::Index;

fn test<'long, 'short>(map: HashMap<&'long String, u32>, key: &'short String) -> u32 {
    // works: 
    // *map.get(&key).unwrap()
    
    // works:
    // *Index::index(&map, &key)
    
    // does not work, but should:
    map[&key]
}

fn main() {}

Indexing is by-value, so really it should be fine to "upcast" the key.

For reference, there are many workarounds. The example shows 2, but another is to "upcast" the map:

{ let map: &HashMap<&'short String, u32> = &map; map[&key]; }
@nikomatsakis nikomatsakis added A-type-system Area: Type system C-enhancement Category: An issue proposing an enhancement or a PR with one. E-needs-mentor T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. labels Nov 17, 2017
@arielb1
Copy link
Contributor

arielb1 commented Nov 19, 2017

This should be fixed by rust-lang/rfcs#2147 if that is implemented

@jackh726 jackh726 added WG-traits Working group: Traits, https://internals.rust-lang.org/t/announcing-traits-working-group/6804 and removed WG-compiler-middle labels Jan 29, 2022
@jackh726
Copy link
Member

I reassigned this to wg-traits; nowadays we do a lot around the typesystem

@jackh726 jackh726 added T-types Relevant to the types team, which will review and decide on the PR/issue. S-types-deferred Status: Identified as a valid potential future enhancement that is not currently being worked on E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. and removed WG-traits Working group: Traits, https://internals.rust-lang.org/t/announcing-traits-working-group/6804 labels Jun 17, 2022
@jackh726
Copy link
Member

We talked about this in the types triage meeting today. We decided that this would be a nice enhancement, and really only needs someone to put in the time to implement it. But it's not on our roadmap.

@compiler-errors
Copy link
Member

compiler-errors commented Jun 17, 2022

Mentor instructions:

This seems pretty easy to do, though it needs some consideration for where to actually place the modifications, some testing, and some research into (and subsequent fixing of) whether this affects other operators such as + -- I believe it does based off of my cursory investigation into this issue. We'll also possibly need to run crater, though I doubt this affects inference heavily so I don't expect to see much there.

Anywho, the simple steps are:

  • determine the discrepancy between type-checking the index operator and type-checking methods
  • fix the problem with the lifetime of the index's LHS not being shortened
  • generalize the fix to other operators as needed (binops and indexmut come to mind)
  • add relevant tests, queue up a crater run if needed
  • analyze the crater run if needed
  • land, profit 🎉

I've embedded what I think is an accurate description of the issue here, though you're welcome to not look at it if you want to work out this issue alone. I don't recommend going through the investigation alone, but just in case, I've nested the explanation.

Specifically, the way that autoderef works for the index operator differs from the way that method probing and subsequent confirmation works. For method probe, the self ty ("receiver") of a method call always is "generalized" by supertyping it against a fresh inference variable. This means that instead of thinking of Index::index(&map, &key) as being equivalent to <HashMap<&'long String, u32> as Index<_>>::index(...), it instead looks more like <HashMap<&'1 String, u32>>::index(&map, &key) where 'long: '1.

We instantiate no such fresh inference variable for the LHS of the index operator, and instead pass the type of the thing being indexed directly into the final steps of method confirmation. Thus the 'long lifetime stays in the method call we end up with, and we are required to relate 'short = 'long. So map[&key] turns into something like: <HashMap<&'long String, u32> as Index<_>>::index(&map, &key). In fact, if you try that on playground, you can see it reproduces the exact same issue.

Interestingly, this is also due to the fact that we're passing &key, and not key into the index's RHS. That means that we end up using this implementation of Borrow, which requires strict type equality between the type and the key.

@compiler-errors compiler-errors added E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. and removed E-needs-mentor labels Jun 17, 2022
@ekuecks
Copy link

ekuecks commented Jun 17, 2022

@rustbot claim

@ekuecks
Copy link

ekuecks commented Jul 27, 2022

This is now fixed on master, presumably by NLL Stabilization, cc @compiler-errors

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-type-system Area: Type system C-enhancement Category: An issue proposing an enhancement or a PR with one. E-medium Call for participation: Medium difficulty. Experience needed to fix: Intermediate. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. S-types-deferred Status: Identified as a valid potential future enhancement that is not currently being worked on T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants