Skip to content

Commit 73e5912

Browse files
Rollup merge of #156058 - qaijuang:issue-151393, r=JohnTitor
Print HRTB binders before fn qualifiers Fixes #151393 This PR updates the custom fn-signature diff used in type mismatch diagnostics to print higher-ranked binders before fn qualifiers. We might want to update reference also: https://github.com/rust-lang/reference/blob/581920f9109f141b88b860b3e1e8359e3896a150/src/items/external-blocks.md?plain=1#L60
2 parents e35334f + 5dfe784 commit 73e5912

3 files changed

Lines changed: 90 additions & 28 deletions

File tree

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

Lines changed: 30 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -779,49 +779,54 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
779779
let (lt1, sig1) = get_lifetimes(sig1);
780780
let (lt2, sig2) = get_lifetimes(sig2);
781781

782-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
782+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
783783
let mut values =
784784
(DiagStyledString::normal("".to_string()), DiagStyledString::normal("".to_string()));
785785

786-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
787-
// ^^^^^^
788-
let safety = |fn_def, sig: ty::FnSig<'_>| match fn_def {
789-
None => sig.safety().prefix_str(),
786+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
787+
// ^^^^^^^^^^^^^^^^^^
788+
let fn_item_prefix_and_safety = |fn_def, sig: ty::FnSig<'_>| match fn_def {
789+
None => ("", sig.safety().prefix_str()),
790790
Some((did, _)) => {
791791
if self.tcx.codegen_fn_attrs(did).safe_target_features {
792-
"#[target_features] "
792+
("#[target_features] ", "")
793793
} else {
794-
sig.safety().prefix_str()
794+
("", sig.safety().prefix_str())
795795
}
796796
}
797797
};
798-
let safety1 = safety(fn_def1, sig1);
799-
let safety2 = safety(fn_def2, sig2);
798+
let (prefix1, safety1) = fn_item_prefix_and_safety(fn_def1, sig1);
799+
let (prefix2, safety2) = fn_item_prefix_and_safety(fn_def2, sig2);
800+
values.0.push(prefix1, prefix1 != prefix2);
801+
values.1.push(prefix2, prefix1 != prefix2);
802+
803+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
804+
// ^^^^^^^^
805+
let lifetime_diff = lt1 != lt2;
806+
values.0.push(lt1, lifetime_diff);
807+
values.1.push(lt2, lifetime_diff);
808+
809+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
810+
// ^^^^^^
800811
values.0.push(safety1, safety1 != safety2);
801812
values.1.push(safety2, safety1 != safety2);
802813

803-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
804-
// ^^^^^^^^^^
814+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
815+
// ^^^^^^^^^^
805816
if sig1.abi() != ExternAbi::Rust {
806817
values.0.push(format!("extern {} ", sig1.abi()), sig1.abi() != sig2.abi());
807818
}
808819
if sig2.abi() != ExternAbi::Rust {
809820
values.1.push(format!("extern {} ", sig2.abi()), sig1.abi() != sig2.abi());
810821
}
811822

812-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
813-
// ^^^^^^^^
814-
let lifetime_diff = lt1 != lt2;
815-
values.0.push(lt1, lifetime_diff);
816-
values.1.push(lt2, lifetime_diff);
817-
818-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
819-
// ^^^
823+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
824+
// ^^^
820825
values.0.push_normal("fn(");
821826
values.1.push_normal("fn(");
822827

823-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
824-
// ^^^^^
828+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
829+
// ^^^^^
825830
let len1 = sig1.inputs().len();
826831
let len2 = sig2.inputs().len();
827832
if len1 == len2 {
@@ -859,13 +864,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
859864
values.1.push("...", !sig1.c_variadic());
860865
}
861866

862-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
863-
// ^
867+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
868+
// ^
864869
values.0.push_normal(")");
865870
values.1.push_normal(")");
866871

867-
// unsafe extern "C" for<'a> fn(&'a T) -> &'a T
868-
// ^^^^^^^^
872+
// #[target_features] for<'a> unsafe extern "C" fn(&'a T) -> &'a T
873+
// ^^^^^^^^
869874
let output1 = sig1.output();
870875
let output2 = sig2.output();
871876
let (x1, x2) = self.cmp(output1, output2);

tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,19 @@ fn foo(x: i32) -> u32 {
1010
0
1111
}
1212

13+
extern "C" fn extern_foo(_: &i32) {}
14+
15+
unsafe extern "C" fn unsafe_extern_foo(_: &i32) {}
16+
17+
fn rust_foo(_: &i32) {}
18+
1319
fn main() {
1420
let b: fn() -> u32 = bar; //~ ERROR mismatched types [E0308]
1521
let f: fn(i32) = foo; //~ ERROR mismatched types [E0308]
22+
23+
// See https://github.com/rust-lang/rust/issues/151393
24+
let _: for<'a> fn(&'a i32) = extern_foo; //~ ERROR mismatched types [E0308]
25+
let _: for<'a> fn(&'a i32) = unsafe_extern_foo; //~ ERROR mismatched types [E0308]
26+
let _: for<'a> extern "C" fn(&'a i32) = rust_foo; //~ ERROR mismatched types [E0308]
27+
let _: for<'a> unsafe extern "C" fn(&'a i32) = rust_foo; //~ ERROR mismatched types [E0308]
1628
}

tests/ui/mismatched_types/fn-pointer-mismatch-diagnostics.stderr

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error[E0308]: mismatched types
2-
--> $DIR/fn-pointer-mismatch-diagnostics.rs:14:26
2+
--> $DIR/fn-pointer-mismatch-diagnostics.rs:20:26
33
|
44
LL | let b: fn() -> u32 = bar;
55
| ----------- ^^^ expected fn pointer, found fn item
@@ -10,7 +10,7 @@ LL | let b: fn() -> u32 = bar;
1010
found fn item `fn() -> () {bar}`
1111

1212
error[E0308]: mismatched types
13-
--> $DIR/fn-pointer-mismatch-diagnostics.rs:15:22
13+
--> $DIR/fn-pointer-mismatch-diagnostics.rs:21:22
1414
|
1515
LL | let f: fn(i32) = foo;
1616
| ------- ^^^ expected fn pointer, found fn item
@@ -20,6 +20,51 @@ LL | let f: fn(i32) = foo;
2020
= note: expected fn pointer `fn(_) -> ()`
2121
found fn item `fn(_) -> u32 {foo}`
2222

23-
error: aborting due to 2 previous errors
23+
error[E0308]: mismatched types
24+
--> $DIR/fn-pointer-mismatch-diagnostics.rs:24:34
25+
|
26+
LL | let _: for<'a> fn(&'a i32) = extern_foo;
27+
| ------------------- ^^^^^^^^^^ expected "Rust" fn, found "C" fn
28+
| |
29+
| expected due to this
30+
|
31+
= note: expected fn pointer `for<'a> fn(&'a _)`
32+
found fn item `for<'a> extern "C" fn(&'a _) {extern_foo}`
33+
34+
error[E0308]: mismatched types
35+
--> $DIR/fn-pointer-mismatch-diagnostics.rs:25:34
36+
|
37+
LL | let _: for<'a> fn(&'a i32) = unsafe_extern_foo;
38+
| ------------------- ^^^^^^^^^^^^^^^^^ expected safe fn, found unsafe fn
39+
| |
40+
| expected due to this
41+
|
42+
= note: expected fn pointer `for<'a> fn(&'a _)`
43+
found fn item `for<'a> unsafe extern "C" fn(&'a _) {unsafe_extern_foo}`
44+
= note: unsafe functions cannot be coerced into safe function pointers
45+
46+
error[E0308]: mismatched types
47+
--> $DIR/fn-pointer-mismatch-diagnostics.rs:26:45
48+
|
49+
LL | let _: for<'a> extern "C" fn(&'a i32) = rust_foo;
50+
| ------------------------------ ^^^^^^^^ expected "C" fn, found "Rust" fn
51+
| |
52+
| expected due to this
53+
|
54+
= note: expected fn pointer `for<'a> extern "C" fn(&'a _)`
55+
found fn item `for<'a> fn(&'a _) {rust_foo}`
56+
57+
error[E0308]: mismatched types
58+
--> $DIR/fn-pointer-mismatch-diagnostics.rs:27:52
59+
|
60+
LL | let _: for<'a> unsafe extern "C" fn(&'a i32) = rust_foo;
61+
| ------------------------------------- ^^^^^^^^ expected "C" fn, found "Rust" fn
62+
| |
63+
| expected due to this
64+
|
65+
= note: expected fn pointer `for<'a> unsafe extern "C" fn(&'a _)`
66+
found fn item `for<'a> fn(&'a _) {rust_foo}`
67+
68+
error: aborting due to 6 previous errors
2469

2570
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)