Auto merge of #86164 - FabianWolff:issue-86053, r=davidtwco

Handle C-variadic arguments properly when reporting region errors

This pull request fixes #86053. The issue is that for a C-variadic function
```rust
#![feature(c_variadic)]
unsafe extern "C" fn foo(_: (), ...) {}
```
`foo`'s signature will contain only the first parameter (and have `c_variadic` set to `true`), whereas its body has a second argument (a `hir::Pat` for the `...`).

The code for reporting region errors iterates over the body's parameters and tries to fetch the corresponding parameter from the signature; this causes an out-of-bounds ICE for the `...` (though not in the example above, because there are no region errors to report).

I have simply restricted the iteration over the body parameters to exclude `...`, which is fine because `...` cannot cause a region error.
This commit is contained in:
bors 2021-06-17 06:34:12 +00:00
commit cb3c4ee718
10 changed files with 218 additions and 69 deletions

View File

@ -652,7 +652,7 @@ impl<'a> AstValidator<'a> {
self.err_handler()
.struct_span_err(
*span,
"only foreign or `unsafe extern \"C\" functions may be C-variadic",
"only foreign or `unsafe extern \"C\"` functions may be C-variadic",
)
.emit();
}

View File

@ -56,33 +56,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
let poly_fn_sig = self.tcx().fn_sig(id);
let fn_sig = self.tcx().liberate_late_bound_regions(id, poly_fn_sig);
body.params.iter().enumerate().find_map(|(index, param)| {
// May return None; sometimes the tables are not yet populated.
let ty = fn_sig.inputs()[index];
let mut found_anon_region = false;
let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
if *r == *anon_region {
found_anon_region = true;
replace_region
} else {
r
}
});
if found_anon_region {
let ty_hir_id = fn_decl.inputs[index].hir_id;
let param_ty_span = hir.span(ty_hir_id);
let is_first = index == 0;
Some(AnonymousParamInfo {
param,
param_ty: new_param_ty,
param_ty_span,
bound_region,
is_first,
})
body.params
.iter()
.take(if fn_sig.c_variadic {
fn_sig.inputs().len()
} else {
None
}
})
assert_eq!(fn_sig.inputs().len(), body.params.len());
body.params.len()
})
.enumerate()
.find_map(|(index, param)| {
// May return None; sometimes the tables are not yet populated.
let ty = fn_sig.inputs()[index];
let mut found_anon_region = false;
let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
if *r == *anon_region {
found_anon_region = true;
replace_region
} else {
r
}
});
if found_anon_region {
let ty_hir_id = fn_decl.inputs[index].hir_id;
let param_ty_span = hir.span(ty_hir_id);
let is_first = index == 0;
Some(AnonymousParamInfo {
param,
param_ty: new_param_ty,
param_ty_span,
bound_region,
is_first,
})
} else {
None
}
})
}
pub(super) fn future_return_type(

View File

@ -0,0 +1,12 @@
// Regression test for the ICE described in issue #86053.
// error-pattern:unexpected `self` parameter in function
// error-pattern:`...` must be the last argument of a C-variadic function
// error-pattern:cannot find type `F` in this scope
// error-pattern:in type `&'a &'b usize`, reference has a longer lifetime than the data it references
#![feature(c_variadic)]
#![crate_type="lib"]
fn ordering4 < 'a , 'b > ( a : , self , self , self ,
self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
}

View File

@ -0,0 +1,101 @@
error: expected type, found `,`
--> $DIR/issue-86053-1.rs:10:47
|
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
| ^ expected type
error: unexpected `self` parameter in function
--> $DIR/issue-86053-1.rs:10:51
|
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
| ^^^^ must be the first parameter of an associated function
error: unexpected `self` parameter in function
--> $DIR/issue-86053-1.rs:10:58
|
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
| ^^^^ must be the first parameter of an associated function
error: unexpected `self` parameter in function
--> $DIR/issue-86053-1.rs:10:67
|
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
| ^^^^ must be the first parameter of an associated function
error: unexpected `self` parameter in function
--> $DIR/issue-86053-1.rs:11:5
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^ must be the first parameter of an associated function
error: unexpected `self` parameter in function
--> $DIR/issue-86053-1.rs:11:20
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^ must be the first parameter of an associated function
error: unexpected `self` parameter in function
--> $DIR/issue-86053-1.rs:11:29
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^ must be the first parameter of an associated function
error: `...` must be the last argument of a C-variadic function
--> $DIR/issue-86053-1.rs:11:12
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/issue-86053-1.rs:11:12
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/issue-86053-1.rs:11:36
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^
error[E0412]: cannot find type `F` in this scope
--> $DIR/issue-86053-1.rs:11:48
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^
|
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
|
LL | pub trait Fn<Args>: FnMut<Args> {
| ------------------------------- similarly named trait `Fn` defined here
|
help: a trait with a similar name exists
|
LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) {
| ^^
help: you might be missing a type parameter
|
LL | fn ordering4 < 'a , 'b, F > ( a : , self , self , self ,
| ^^^
error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
--> $DIR/issue-86053-1.rs:11:52
|
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the pointer is valid for the lifetime `'a` as defined on the function body at 10:16
--> $DIR/issue-86053-1.rs:10:16
|
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
| ^^
note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 10:21
--> $DIR/issue-86053-1.rs:10:21
|
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
| ^^
error: aborting due to 12 previous errors
Some errors have detailed explanations: E0412, E0491.
For more information about an error, try `rustc --explain E0412`.

View File

@ -0,0 +1,11 @@
// Regression test for the ICE caused by the example in
// https://github.com/rust-lang/rust/issues/86053#issuecomment-855672258
#![feature(c_variadic)]
trait H<T> {}
unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
//~^ ERROR: in type `&'static &'a ()`, reference has a longer lifetime than the data it references [E0491]
fn main() {}

View File

@ -0,0 +1,16 @@
error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references
--> $DIR/issue-86053-2.rs:8:39
|
LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
| ^^^^^^^^^^^^^^^^^^
|
= note: the pointer is valid for the static lifetime
note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 8:32
--> $DIR/issue-86053-2.rs:8:32
|
LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
| ^^
error: aborting due to previous error
For more information about this error, try `rustc --explain E0491`.

View File

@ -5,6 +5,6 @@
fn main() {}
fn foo(_: Bar, ...) -> impl {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR cannot find type `Bar` in this scope
//~| ERROR at least one trait must be specified

View File

@ -1,4 +1,4 @@
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/issue-83499-input-output-iteration-ice.rs:7:16
|
LL | fn foo(_: Bar, ...) -> impl {}

View File

@ -4,32 +4,32 @@
fn main() {}
fn f1_1(x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
fn f1_2(...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR C-variadic function must be declared with at least one named argument
extern "C" fn f2_1(x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
extern "C" fn f2_2(...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR C-variadic function must be declared with at least one named argument
extern "C" fn f2_3(..., x: isize) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR `...` must be the last argument of a C-variadic function
extern "C" fn f3_1(x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
extern "C" fn f3_2(...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR C-variadic function must be declared with at least one named argument
extern "C" fn f3_3(..., x: isize) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR `...` must be the last argument of a C-variadic function
extern "C" {
@ -43,35 +43,35 @@ struct X;
impl X {
fn i_f1(x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
fn i_f2(...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR C-variadic function must be declared with at least one named argument
fn i_f3(..., x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR `...` must be the last argument of a C-variadic function
fn i_f4(..., x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR `...` must be the last argument of a C-variadic function
}
trait T {
fn t_f1(x: isize, ...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
fn t_f2(x: isize, ...);
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
fn t_f3(...) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR C-variadic function must be declared with at least one named argument
fn t_f4(...);
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR C-variadic function must be declared with at least one named argument
fn t_f5(..., x: isize) {}
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR `...` must be the last argument of a C-variadic function
fn t_f6(..., x: isize);
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
//~| ERROR `...` must be the last argument of a C-variadic function
}

View File

@ -1,4 +1,4 @@
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:6:19
|
LL | fn f1_1(x: isize, ...) {}
@ -10,13 +10,13 @@ error: C-variadic function must be declared with at least one named argument
LL | fn f1_2(...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:9:9
|
LL | fn f1_2(...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:13:30
|
LL | extern "C" fn f2_1(x: isize, ...) {}
@ -28,7 +28,7 @@ error: C-variadic function must be declared with at least one named argument
LL | extern "C" fn f2_2(...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:16:20
|
LL | extern "C" fn f2_2(...) {}
@ -40,13 +40,13 @@ error: `...` must be the last argument of a C-variadic function
LL | extern "C" fn f2_3(..., x: isize) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:20:20
|
LL | extern "C" fn f2_3(..., x: isize) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:24:30
|
LL | extern "C" fn f3_1(x: isize, ...) {}
@ -58,7 +58,7 @@ error: C-variadic function must be declared with at least one named argument
LL | extern "C" fn f3_2(...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:27:20
|
LL | extern "C" fn f3_2(...) {}
@ -70,7 +70,7 @@ error: `...` must be the last argument of a C-variadic function
LL | extern "C" fn f3_3(..., x: isize) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:31:20
|
LL | extern "C" fn f3_3(..., x: isize) {}
@ -88,7 +88,7 @@ error: `...` must be the last argument of a C-variadic function
LL | fn e_f2(..., x: isize);
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:45:23
|
LL | fn i_f1(x: isize, ...) {}
@ -100,7 +100,7 @@ error: C-variadic function must be declared with at least one named argument
LL | fn i_f2(...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:47:13
|
LL | fn i_f2(...) {}
@ -112,13 +112,13 @@ error: `...` must be the last argument of a C-variadic function
LL | fn i_f3(..., x: isize, ...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:13
|
LL | fn i_f3(..., x: isize, ...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:50:28
|
LL | fn i_f3(..., x: isize, ...) {}
@ -130,25 +130,25 @@ error: `...` must be the last argument of a C-variadic function
LL | fn i_f4(..., x: isize, ...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:13
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:54:28
|
LL | fn i_f4(..., x: isize, ...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:61:23
|
LL | fn t_f1(x: isize, ...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:63:23
|
LL | fn t_f2(x: isize, ...);
@ -160,7 +160,7 @@ error: C-variadic function must be declared with at least one named argument
LL | fn t_f3(...) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:65:13
|
LL | fn t_f3(...) {}
@ -172,7 +172,7 @@ error: C-variadic function must be declared with at least one named argument
LL | fn t_f4(...);
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:68:13
|
LL | fn t_f4(...);
@ -184,7 +184,7 @@ error: `...` must be the last argument of a C-variadic function
LL | fn t_f5(..., x: isize) {}
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:71:13
|
LL | fn t_f5(..., x: isize) {}
@ -196,7 +196,7 @@ error: `...` must be the last argument of a C-variadic function
LL | fn t_f6(..., x: isize);
| ^^^
error: only foreign or `unsafe extern "C" functions may be C-variadic
error: only foreign or `unsafe extern "C"` functions may be C-variadic
--> $DIR/variadic-ffi-semantic-restrictions.rs:74:13
|
LL | fn t_f6(..., x: isize);