Skip to content

Commit 7dccce0

Browse files
committed
Handle C-variadic arguments properly when reporting region errors
1 parent d45d205 commit 7dccce0

10 files changed

+217
-68
lines changed

compiler/rustc_ast_passes/src/ast_validation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ impl<'a> AstValidator<'a> {
652652
self.err_handler()
653653
.struct_span_err(
654654
*span,
655-
"only foreign or `unsafe extern \"C\" functions may be C-variadic",
655+
"only foreign or `unsafe extern \"C\"` functions may be C-variadic",
656656
)
657657
.emit();
658658
}

compiler/rustc_infer/src/infer/error_reporting/nice_region_error/util.rs

+34-25
Original file line numberDiff line numberDiff line change
@@ -56,33 +56,42 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
5656
let fn_decl = hir.fn_decl_by_hir_id(owner_id).unwrap();
5757
let poly_fn_sig = self.tcx().fn_sig(id);
5858
let fn_sig = self.tcx().liberate_late_bound_regions(id, poly_fn_sig);
59-
body.params.iter().enumerate().find_map(|(index, param)| {
60-
// May return None; sometimes the tables are not yet populated.
61-
let ty = fn_sig.inputs()[index];
62-
let mut found_anon_region = false;
63-
let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
64-
if *r == *anon_region {
65-
found_anon_region = true;
66-
replace_region
59+
body.params
60+
.iter()
61+
.take(if fn_sig.c_variadic {
62+
fn_sig.inputs().len()
63+
} else {
64+
assert_eq!(fn_sig.inputs().len(), body.params.len());
65+
body.params.len()
66+
})
67+
.enumerate()
68+
.find_map(|(index, param)| {
69+
// May return None; sometimes the tables are not yet populated.
70+
let ty = fn_sig.inputs()[index];
71+
let mut found_anon_region = false;
72+
let new_param_ty = self.tcx().fold_regions(ty, &mut false, |r, _| {
73+
if *r == *anon_region {
74+
found_anon_region = true;
75+
replace_region
76+
} else {
77+
r
78+
}
79+
});
80+
if found_anon_region {
81+
let ty_hir_id = fn_decl.inputs[index].hir_id;
82+
let param_ty_span = hir.span(ty_hir_id);
83+
let is_first = index == 0;
84+
Some(AnonymousParamInfo {
85+
param,
86+
param_ty: new_param_ty,
87+
param_ty_span,
88+
bound_region,
89+
is_first,
90+
})
6791
} else {
68-
r
92+
None
6993
}
70-
});
71-
if found_anon_region {
72-
let ty_hir_id = fn_decl.inputs[index].hir_id;
73-
let param_ty_span = hir.span(ty_hir_id);
74-
let is_first = index == 0;
75-
Some(AnonymousParamInfo {
76-
param,
77-
param_ty: new_param_ty,
78-
param_ty_span,
79-
bound_region,
80-
is_first,
81-
})
82-
} else {
83-
None
84-
}
85-
})
94+
})
8695
}
8796

8897
pub(super) fn future_return_type(
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// Regression test for the ICE described in issue #86053.
2+
// error-pattern:unexpected `self` parameter in function
3+
// error-pattern:`...` must be the last argument of a C-variadic function
4+
// error-pattern:cannot find type `F` in this scope
5+
// error-pattern:in type `&'a &'b usize`, reference has a longer lifetime than the data it references
6+
7+
#![feature(c_variadic)]
8+
#![crate_type="lib"]
9+
10+
fn ordering4 < 'a , 'b > ( a : , self , self , self ,
11+
self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
12+
}
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
error: expected type, found `,`
2+
--> $DIR/issue-86053-1.rs:10:47
3+
|
4+
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
5+
| ^ expected type
6+
7+
error: unexpected `self` parameter in function
8+
--> $DIR/issue-86053-1.rs:10:51
9+
|
10+
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
11+
| ^^^^ must be the first parameter of an associated function
12+
13+
error: unexpected `self` parameter in function
14+
--> $DIR/issue-86053-1.rs:10:58
15+
|
16+
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
17+
| ^^^^ must be the first parameter of an associated function
18+
19+
error: unexpected `self` parameter in function
20+
--> $DIR/issue-86053-1.rs:10:67
21+
|
22+
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
23+
| ^^^^ must be the first parameter of an associated function
24+
25+
error: unexpected `self` parameter in function
26+
--> $DIR/issue-86053-1.rs:11:5
27+
|
28+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
29+
| ^^^^ must be the first parameter of an associated function
30+
31+
error: unexpected `self` parameter in function
32+
--> $DIR/issue-86053-1.rs:11:20
33+
|
34+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
35+
| ^^^^ must be the first parameter of an associated function
36+
37+
error: unexpected `self` parameter in function
38+
--> $DIR/issue-86053-1.rs:11:29
39+
|
40+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
41+
| ^^^^ must be the first parameter of an associated function
42+
43+
error: `...` must be the last argument of a C-variadic function
44+
--> $DIR/issue-86053-1.rs:11:12
45+
|
46+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
47+
| ^^^^
48+
49+
error: only foreign or `unsafe extern "C"` functions may be C-variadic
50+
--> $DIR/issue-86053-1.rs:11:12
51+
|
52+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
53+
| ^^^^
54+
55+
error: only foreign or `unsafe extern "C"` functions may be C-variadic
56+
--> $DIR/issue-86053-1.rs:11:36
57+
|
58+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
59+
| ^^^^
60+
61+
error[E0412]: cannot find type `F` in this scope
62+
--> $DIR/issue-86053-1.rs:11:48
63+
|
64+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
65+
| ^
66+
|
67+
::: $SRC_DIR/core/src/ops/function.rs:LL:COL
68+
|
69+
LL | pub trait Fn<Args>: FnMut<Args> {
70+
| ------------------------------- similarly named trait `Fn` defined here
71+
|
72+
help: a trait with a similar name exists
73+
|
74+
LL | self , ... , self , self , ... ) where Fn : FnOnce ( & 'a & 'b usize ) {
75+
| ^^
76+
help: you might be missing a type parameter
77+
|
78+
LL | fn ordering4 < 'a , 'b, F > ( a : , self , self , self ,
79+
| ^^^
80+
81+
error[E0491]: in type `&'a &'b usize`, reference has a longer lifetime than the data it references
82+
--> $DIR/issue-86053-1.rs:11:52
83+
|
84+
LL | self , ... , self , self , ... ) where F : FnOnce ( & 'a & 'b usize ) {
85+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
86+
|
87+
note: the pointer is valid for the lifetime `'a` as defined on the function body at 10:16
88+
--> $DIR/issue-86053-1.rs:10:16
89+
|
90+
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
91+
| ^^
92+
note: but the referenced data is only valid for the lifetime `'b` as defined on the function body at 10:21
93+
--> $DIR/issue-86053-1.rs:10:21
94+
|
95+
LL | fn ordering4 < 'a , 'b > ( a : , self , self , self ,
96+
| ^^
97+
98+
error: aborting due to 12 previous errors
99+
100+
Some errors have detailed explanations: E0412, E0491.
101+
For more information about an error, try `rustc --explain E0412`.
+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// Regression test for the ICE caused by the example in
2+
// https://github.com/rust-lang/rust/issues/86053#issuecomment-855672258
3+
4+
#![feature(c_variadic)]
5+
6+
trait H<T> {}
7+
8+
unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
9+
//~^ ERROR: in type `&'static &'a ()`, reference has a longer lifetime than the data it references [E0491]
10+
11+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0491]: in type `&'static &'a ()`, reference has a longer lifetime than the data it references
2+
--> $DIR/issue-86053-2.rs:8:39
3+
|
4+
LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
5+
| ^^^^^^^^^^^^^^^^^^
6+
|
7+
= note: the pointer is valid for the static lifetime
8+
note: but the referenced data is only valid for the lifetime `'a` as defined on the function body at 8:32
9+
--> $DIR/issue-86053-2.rs:8:32
10+
|
11+
LL | unsafe extern "C" fn ordering4<'a, F: H<&'static &'a ()>>(_: (), ...) {}
12+
| ^^
13+
14+
error: aborting due to previous error
15+
16+
For more information about this error, try `rustc --explain E0491`.

src/test/ui/mir/issue-83499-input-output-iteration-ice.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,6 @@
55
fn main() {}
66

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

src/test/ui/mir/issue-83499-input-output-iteration-ice.stderr

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

src/test/ui/parser/variadic-ffi-semantic-restrictions.rs

+20-20
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,32 @@
44
fn main() {}
55

66
fn f1_1(x: isize, ...) {}
7-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
7+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
88

99
fn f1_2(...) {}
10-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
10+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
1111
//~| ERROR C-variadic function must be declared with at least one named argument
1212

1313
extern "C" fn f2_1(x: isize, ...) {}
14-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
14+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
1515

1616
extern "C" fn f2_2(...) {}
17-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
17+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
1818
//~| ERROR C-variadic function must be declared with at least one named argument
1919

2020
extern "C" fn f2_3(..., x: isize) {}
21-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
21+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
2222
//~| ERROR `...` must be the last argument of a C-variadic function
2323

2424
extern "C" fn f3_1(x: isize, ...) {}
25-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
25+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
2626

2727
extern "C" fn f3_2(...) {}
28-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
28+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
2929
//~| ERROR C-variadic function must be declared with at least one named argument
3030

3131
extern "C" fn f3_3(..., x: isize) {}
32-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
32+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
3333
//~| ERROR `...` must be the last argument of a C-variadic function
3434

3535
extern "C" {
@@ -43,35 +43,35 @@ struct X;
4343

4444
impl X {
4545
fn i_f1(x: isize, ...) {}
46-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
46+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
4747
fn i_f2(...) {}
48-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
48+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
4949
//~| ERROR C-variadic function must be declared with at least one named argument
5050
fn i_f3(..., x: isize, ...) {}
51-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
52-
//~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
51+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
52+
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
5353
//~| ERROR `...` must be the last argument of a C-variadic function
5454
fn i_f4(..., x: isize, ...) {}
55-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
56-
//~| ERROR only foreign or `unsafe extern "C" functions may be C-variadic
55+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
56+
//~| ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
5757
//~| ERROR `...` must be the last argument of a C-variadic function
5858
}
5959

6060
trait T {
6161
fn t_f1(x: isize, ...) {}
62-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
62+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
6363
fn t_f2(x: isize, ...);
64-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
64+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
6565
fn t_f3(...) {}
66-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
66+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
6767
//~| ERROR C-variadic function must be declared with at least one named argument
6868
fn t_f4(...);
69-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
69+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
7070
//~| ERROR C-variadic function must be declared with at least one named argument
7171
fn t_f5(..., x: isize) {}
72-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
72+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
7373
//~| ERROR `...` must be the last argument of a C-variadic function
7474
fn t_f6(..., x: isize);
75-
//~^ ERROR only foreign or `unsafe extern "C" functions may be C-variadic
75+
//~^ ERROR only foreign or `unsafe extern "C"` functions may be C-variadic
7676
//~| ERROR `...` must be the last argument of a C-variadic function
7777
}

0 commit comments

Comments
 (0)