Skip to content

Commit

Permalink
Rollup merge of rust-lang#62639 - immunant:invariant_valistimpl, r=eddyb
Browse files Browse the repository at this point in the history
Make VaListImpl<'f> invariant over the 'f lifetime

After doing some research on variance and going back to look at `VaList` and `VaListImpl`, I realized that `VaList<'a, 'f>` is invariant over the `'f` lifetime (and covariant over `'a`), but `VaListImpl<'f>` isn't invariant but probably should be. This patch makes `VaListImpl<'f>` invariant over `'f`.

r? @eddyb
cc @dlrobertson
  • Loading branch information
Mark-Simulacrum authored Jul 15, 2019
2 parents caf10b5 + 0c981e0 commit ee81940
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 49 deletions.
13 changes: 8 additions & 5 deletions src/libcore/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ impl fmt::Debug for c_void {
#[lang = "va_list"]
pub struct VaListImpl<'f> {
ptr: *mut c_void,
_marker: PhantomData<&'f c_void>,

// Invariant over `'f`, so each `VaListImpl<'f>` object is tied to
// the region of the function it's defined in
_marker: PhantomData<&'f mut &'f c_void>,
}

#[cfg(any(all(not(target_arch = "aarch64"), not(target_arch = "powerpc"),
Expand Down Expand Up @@ -96,7 +99,7 @@ pub struct VaListImpl<'f> {
vr_top: *mut c_void,
gr_offs: i32,
vr_offs: i32,
_marker: PhantomData<&'f c_void>,
_marker: PhantomData<&'f mut &'f c_void>,
}

/// PowerPC ABI implementation of a `va_list`.
Expand All @@ -114,7 +117,7 @@ pub struct VaListImpl<'f> {
reserved: u16,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomData<&'f c_void>,
_marker: PhantomData<&'f mut &'f c_void>,
}

/// x86_64 ABI implementation of a `va_list`.
Expand All @@ -131,7 +134,7 @@ pub struct VaListImpl<'f> {
fp_offset: i32,
overflow_arg_area: *mut c_void,
reg_save_area: *mut c_void,
_marker: PhantomData<&'f c_void>,
_marker: PhantomData<&'f mut &'f c_void>,
}

/// asm.js ABI implementation of a `va_list`.
Expand All @@ -148,7 +151,7 @@ pub struct VaListImpl<'f> {
#[lang = "va_list"]
pub struct VaListImpl<'f> {
inner: [crate::mem::MaybeUninit<i32>; 4],
_marker: PhantomData<&'f c_void>,
_marker: PhantomData<&'f mut &'f c_void>,
}

#[cfg(all(target_arch = "asmjs", not(windows)))]
Expand Down
34 changes: 27 additions & 7 deletions src/test/ui/c-variadic/variadic-ffi-4.nll.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,16 @@ LL | let _ = ap.with_copy(|ap| { ap });
| | return type of closure is core::ffi::VaList<'2, '_>
| has type `core::ffi::VaList<'1, '_>`

error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:20:5
|
LL | pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1;
| ^^^^ assignment requires that `'1` must outlive `'2`

error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:20:5
|
Expand All @@ -34,7 +44,7 @@ LL | *ap0 = ap1;
| ^^^^ assignment requires that `'1` must outlive `'2`

error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:24:5
--> $DIR/variadic-ffi-4.rs:25:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| --- ------- has type `core::ffi::VaListImpl<'2>`
Expand All @@ -44,7 +54,7 @@ LL | ap0 = &mut ap1;
| ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`

error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:24:5
--> $DIR/variadic-ffi-4.rs:25:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| --- ------- has type `core::ffi::VaListImpl<'1>`
Expand All @@ -54,15 +64,15 @@ LL | ap0 = &mut ap1;
| ^^^^^^^^^^^^^^ assignment requires that `'1` must outlive `'2`

error[E0384]: cannot assign to immutable argument `ap0`
--> $DIR/variadic-ffi-4.rs:24:5
--> $DIR/variadic-ffi-4.rs:25:5
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| --- help: make this binding mutable: `mut ap0`
LL | ap0 = &mut ap1;
| ^^^^^^^^^^^^^^ cannot assign to immutable argument

error[E0597]: `ap1` does not live long enough
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
| - let's call the lifetime of this reference `'1`
Expand All @@ -76,16 +86,26 @@ LL | }
| - `ap1` dropped here while still borrowed

error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:32:5
--> $DIR/variadic-ffi-4.rs:33:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'2>`
| |
| has type `&mut core::ffi::VaListImpl<'1>`
LL | *ap0 = ap1.clone();
| ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`

error: lifetime may not live long enough
--> $DIR/variadic-ffi-4.rs:33:12
|
LL | pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
| ------- ------- has type `core::ffi::VaListImpl<'1>`
| |
| has type `&mut core::ffi::VaListImpl<'2>`
LL | *ap0 = ap1.clone();
| ^^^^ assignment requires that `'1` must outlive `'2`
| ^^^^^^^^^^^ argument requires that `'1` must outlive `'2`

error: aborting due to 9 previous errors
error: aborting due to 11 previous errors

Some errors have detailed explanations: E0384, E0597, E0621.
For more information about an error, try `rustc --explain E0384`.
4 changes: 3 additions & 1 deletion src/test/ui/c-variadic/variadic-ffi-4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub unsafe extern "C" fn no_escape2(_: usize, ap: ...) {

pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
*ap0 = ap1; //~ ERROR: mismatched types
//~^ ERROR: mismatched types
}

pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
Expand All @@ -29,5 +30,6 @@ pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...
}

pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
*ap0 = ap1.clone(); //~ ERROR: cannot infer an appropriate lifetime
*ap0 = ap1.clone(); //~ ERROR: mismatched types
//~^ ERROR: mismatched types
}
122 changes: 86 additions & 36 deletions src/test/ui/c-variadic/variadic-ffi-4.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,51 @@ note: the anonymous lifetime #3 defined on the function body at 19:1...
|
LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1;
LL | |
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 19:1
--> $DIR/variadic-ffi-4.rs:19:1
|
LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1;
LL | |
LL | | }
| |_^

error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:20:12
|
LL | *ap0 = ap1;
| ^^^ lifetime mismatch
|
= note: expected type `core::ffi::VaListImpl<'_>`
found type `core::ffi::VaListImpl<'_>`
note: the anonymous lifetime #2 defined on the function body at 19:1...
--> $DIR/variadic-ffi-4.rs:19:1
|
LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1;
LL | |
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 19:1
--> $DIR/variadic-ffi-4.rs:19:1
|
LL | / pub unsafe extern "C" fn no_escape3(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1;
LL | |
LL | | }
| |_^

error[E0490]: a value of type `core::ffi::VaListImpl<'_>` is borrowed for too long
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^
|
note: the type is valid for the anonymous lifetime #1 defined on the function body at 23:1
--> $DIR/variadic-ffi-4.rs:23:1
note: the type is valid for the anonymous lifetime #1 defined on the function body at 24:1
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -79,8 +106,8 @@ LL | |
LL | |
LL | | }
| |_^
note: but the borrow lasts for the anonymous lifetime #3 defined on the function body at 23:1
--> $DIR/variadic-ffi-4.rs:23:1
note: but the borrow lasts for the anonymous lifetime #3 defined on the function body at 24:1
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -92,15 +119,15 @@ LL | | }
| |_^

error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^ lifetime mismatch
|
= note: expected type `&mut core::ffi::VaListImpl<'_>`
found type `&mut core::ffi::VaListImpl<'_>`
note: the anonymous lifetime #3 defined on the function body at 23:1...
--> $DIR/variadic-ffi-4.rs:23:1
note: the anonymous lifetime #3 defined on the function body at 24:1...
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -110,8 +137,8 @@ LL | |
LL | |
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 23:1
--> $DIR/variadic-ffi-4.rs:23:1
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 24:1
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -123,15 +150,15 @@ LL | | }
| |_^

error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^ lifetime mismatch
|
= note: expected type `&mut core::ffi::VaListImpl<'_>`
found type `&mut core::ffi::VaListImpl<'_>`
note: the anonymous lifetime #2 defined on the function body at 23:1...
--> $DIR/variadic-ffi-4.rs:23:1
note: the anonymous lifetime #2 defined on the function body at 24:1...
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -141,8 +168,8 @@ LL | |
LL | |
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 23:1
--> $DIR/variadic-ffi-4.rs:23:1
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 24:1
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -154,13 +181,13 @@ LL | | }
| |_^

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the function body at 23:1...
--> $DIR/variadic-ffi-4.rs:23:1
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the function body at 24:1...
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -171,12 +198,12 @@ LL | |
LL | | }
| |_^
note: ...so that the type `core::ffi::VaListImpl<'_>` is not borrowed for too long
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 23:1...
--> $DIR/variadic-ffi-4.rs:23:1
note: but, the lifetime must be valid for the anonymous lifetime #1 defined on the function body at 24:1...
--> $DIR/variadic-ffi-4.rs:24:1
|
LL | / pub unsafe extern "C" fn no_escape4(_: usize, ap0: &mut VaListImpl, mut ap1: ...) {
LL | | ap0 = &mut ap1;
Expand All @@ -187,39 +214,62 @@ LL | |
LL | | }
| |_^
note: ...so that reference does not outlive borrowed content
--> $DIR/variadic-ffi-4.rs:24:11
--> $DIR/variadic-ffi-4.rs:25:11
|
LL | ap0 = &mut ap1;
| ^^^^^^^^

error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
--> $DIR/variadic-ffi-4.rs:32:16
error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:33:12
|
LL | *ap0 = ap1.clone();
| ^^^^^
| ^^^^^^^^^^^ lifetime mismatch
|
note: first, the lifetime cannot outlive the anonymous lifetime #3 defined on the function body at 31:1...
--> $DIR/variadic-ffi-4.rs:31:1
= note: expected type `core::ffi::VaListImpl<'_>`
found type `core::ffi::VaListImpl<'_>`
note: the anonymous lifetime #3 defined on the function body at 32:1...
--> $DIR/variadic-ffi-4.rs:32:1
|
LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1.clone();
LL | |
LL | | }
| |_^
= note: ...so that the types are compatible:
expected &core::ffi::VaListImpl<'_>
found &core::ffi::VaListImpl<'_>
note: but, the lifetime must be valid for the anonymous lifetime #2 defined on the function body at 31:1...
--> $DIR/variadic-ffi-4.rs:31:1
note: ...does not necessarily outlive the anonymous lifetime #2 defined on the function body at 32:1
--> $DIR/variadic-ffi-4.rs:32:1
|
LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1.clone();
LL | |
LL | | }
| |_^

error[E0308]: mismatched types
--> $DIR/variadic-ffi-4.rs:33:12
|
LL | *ap0 = ap1.clone();
| ^^^^^^^^^^^ lifetime mismatch
|
= note: expected type `core::ffi::VaListImpl<'_>`
found type `core::ffi::VaListImpl<'_>`
note: the anonymous lifetime #2 defined on the function body at 32:1...
--> $DIR/variadic-ffi-4.rs:32:1
|
LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1.clone();
LL | |
LL | | }
| |_^
note: ...does not necessarily outlive the anonymous lifetime #3 defined on the function body at 32:1
--> $DIR/variadic-ffi-4.rs:32:1
|
LL | / pub unsafe extern "C" fn no_escape5(_: usize, mut ap0: &mut VaListImpl, mut ap1: ...) {
LL | | *ap0 = ap1.clone();
LL | |
LL | | }
| |_^
= note: ...so that the expression is assignable:
expected core::ffi::VaListImpl<'_>
found core::ffi::VaListImpl<'_>

error: aborting due to 9 previous errors
error: aborting due to 11 previous errors

Some errors have detailed explanations: E0308, E0621.
For more information about an error, try `rustc --explain E0308`.

0 comments on commit ee81940

Please sign in to comment.