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

Handle C-variadic arguments properly when reporting region errors #86164

Merged
merged 1 commit into from
Jun 17, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Handle C-variadic arguments properly when reporting region errors
  • Loading branch information
FabianWolff committed Jun 9, 2021
commit 7dccce07066ea58d7f8d1dd8462347e91e51c67a
2 changes: 1 addition & 1 deletion compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
body.params
.iter()
.take(if fn_sig.c_variadic {
fn_sig.inputs().len()
} else {
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 {
r
None
}
});
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(
Expand Down
12 changes: 12 additions & 0 deletions src/test/ui/c-variadic/issue-86053-1.rs
Original file line number Diff line number Diff line change
@@ -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 ) {
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this need to be formatted like this or can you run rustfmt on it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't need to be, but since this is a regression test, I have tried to reproduce the example from #86053 as closely as possible (the line break had to happen in order to make test tidy happy).

101 changes: 101 additions & 0 deletions src/test/ui/c-variadic/issue-86053-1.stderr
Original file line number Diff line number Diff line change
@@ -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`.
11 changes: 11 additions & 0 deletions src/test/ui/c-variadic/issue-86053-2.rs
Original file line number Diff line number Diff line change
@@ -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() {}
16 changes: 16 additions & 0 deletions src/test/ui/c-variadic/issue-86053-2.stderr
Original file line number Diff line number Diff line change
@@ -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`.
2 changes: 1 addition & 1 deletion src/test/ui/mir/issue-83499-input-output-iteration-ice.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Original file line number Diff line number Diff line change
@@ -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 {}
Expand Down
40 changes: 20 additions & 20 deletions src/test/ui/parser/variadic-ffi-semantic-restrictions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {
Expand All @@ -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
}
Loading