Skip to content

vec::IntoIter is now invariant #35721

@asajeffrey

Description

@asajeffrey

#35447 replaced a *const T by a *mut T in IntoIter<T>, which changed IntoIter from being covariant to being invariant. This breaks crates like vec_map which relied on IntoIter being invariant, e.g. https://travis-ci.org/asajeffrey/presort/jobs/152720189#L208 has error:

error[E0308]: mismatched types
   --> /home/ajeffrey/.cargo/registry/src/github.com-1ecc6299db9ec823/vec_map-0.6.0/src/lib.rs:952:84
    |
952 |     fn into_iter_covariant<'a, T>(iter: IntoIter<&'static T>) -> IntoIter<&'a T> { iter }
    |                                                                                    ^^^^ lifetime mismatch
    |
    = note: expected type `IntoIter<&'a T>`
    = note:    found type `IntoIter<&'static T>`
note: the lifetime 'a as defined on the block at 952:81...
   --> /home/ajeffrey/.cargo/registry/src/github.com-1ecc6299db9ec823/vec_map-0.6.0/src/lib.rs:952:82
    |
952 |     fn into_iter_covariant<'a, T>(iter: IntoIter<&'static T>) -> IntoIter<&'a T> { iter }
    |                                                                                  ^^^^^^^^
    = note: ...does not necessarily outlive the static lifetime

   Compiling rustc-serialize v0.3.19
error: aborting due to previous error

cc @alexcrichton @frewsxcv @apasel422

Activity

apasel422

apasel422 commented on Aug 16, 2016

@apasel422
Contributor

See my comment here: #35447 (comment)

frewsxcv

frewsxcv commented on Aug 16, 2016

@frewsxcv
Member

I'll be honest, I don't entirely know what covariant means, but I'm sorry for whatever pain it caused and wouldn't be offended if it got reverted.

Does anyone know of a resource explaining the terms 'covariant' and 'invariant' in this context?

asajeffrey

asajeffrey commented on Aug 16, 2016

@asajeffrey
Author
apasel422

apasel422 commented on Aug 16, 2016

@apasel422
Contributor

@frewsxcv: Basically, we just need to change ptr: *mut T back to ptr: *const T.

asajeffrey

asajeffrey commented on Aug 16, 2016

@asajeffrey
Author

@apasel422 is it safe to do that without also removing as_mut_slice?

frewsxcv

frewsxcv commented on Aug 16, 2016

@frewsxcv
Member

We probably need something like this for IntoIter.

apasel422

apasel422 commented on Aug 16, 2016

@apasel422
Contributor

@asajeffrey It seems to me that IntoIter<T> is logically a Vec<T>, so if Vec<T> is covariant in T and supports deref-ing to a mutable slice, then IntoIter<T> should also be OK to provide as_mut_slice.

asajeffrey

asajeffrey commented on Aug 16, 2016

@asajeffrey
Author

@apasel422 okay, good point. The thing that's worrying me is that the *const T is being treated as a constant pointer by LLVM, which may trigger unsafe LLVM optimizations it it's then exposed as a &mut[T].

asajeffrey

asajeffrey commented on Aug 16, 2016

@asajeffrey
Author

@apasel422 I think the difference is that Vec can be a Unique pointer, whereas IntoIter has two pointers into the vector, in order to be double-ended, so can't be Unique.

apasel422

apasel422 commented on Aug 16, 2016

@apasel422
Contributor

@asajeffrey It's already safe to cast a *const T to a *mut T. The standard library does this all over the place, including in RawVec (which internally uses Unique), which is how Vec<T> is covariant in the first place.

In terms of duplicating Unique, yes, eventually Rust might make use of optimizations that indicate that the underlying pointer is globally unaliased, so we should probably use Shared here, or at the very least, something that isn't Unique (e.g. two *const Ts). I made a similar fix in #34608.

asajeffrey

asajeffrey commented on Aug 16, 2016

@asajeffrey
Author

@apasel422 okay, sounds like I'm being overly conservative!

added
T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.
on Aug 16, 2016

17 remaining items

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

Metadata

Metadata

Assignees

Labels

T-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.regression-from-stable-to-nightlyPerformance or correctness regression from stable to nightly.

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    No branches or pull requests

      Participants

      @alexcrichton@asajeffrey@frewsxcv@apasel422

      Issue actions

        vec::IntoIter is now invariant · Issue #35721 · rust-lang/rust