Skip to content

Commit d9d4a52

Browse files
committed
Emit an error when there are two differently inferred impl traits within a single function
1 parent 549f545 commit d9d4a52

8 files changed

+152
-6
lines changed

compiler/rustc_trait_selection/src/opaque_types.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -1109,22 +1109,26 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
11091109
} else {
11101110
// Don't emit multiple errors for the same set of substs
11111111
opaque_defn.substs.push(substs);
1112+
/*opaque_defn.concrete_ty = tcx.ty_error_with_message(
1113+
self.value_span,
1114+
"defining use generics differ from previous defining use",
1115+
);*/
11121116
tcx.sess
11131117
.struct_span_err(
11141118
self.value_span,
11151119
&format!(
1116-
"defining use generics {:?} differ from previous defining use",
1120+
"defining use generics `{:?}` differ from previous defining use",
11171121
substs
11181122
),
11191123
)
11201124
.span_note(
11211125
opaque_defn.definition_span,
11221126
&format!(
1123-
"previous defining use with different generics {:?} found here",
1127+
"previous defining use with different generics `{:?}` found here",
11241128
opaque_defn.substs[0]
11251129
),
11261130
)
1127-
.delay_as_bug();
1131+
.emit();
11281132
}
11291133
}
11301134
let span = tcx.def_span(def_id);
@@ -1161,7 +1165,7 @@ impl<'a, 'tcx> Instantiator<'a, 'tcx> {
11611165
let definition_span = self.value_span;
11621166

11631167
// We only keep the first concrete type var, as we will already error
1164-
// out if there are multiple due to the conflicting obligations
1168+
// out if there are multiple due to the conflicting obligations
11651169
if !self.opaque_types.contains_key(&def_id) {
11661170
self.opaque_types.insert(
11671171
def_id,
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// check-pass
2+
#![feature(min_type_alias_impl_trait)]
3+
4+
type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
5+
6+
fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
7+
(a.clone(), a)
8+
}
9+
10+
fn main() {
11+
println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1));
12+
}

src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,11 @@
55
#![feature(min_type_alias_impl_trait)]
66

77
type X<A, B> = impl Into<&'static A>;
8-
//~^ the trait bound `&'static B: From<&A>` is not satisfied
8+
//~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
99

1010
fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
11+
//~^ ERROR defining use generics `[B, A]` differ from previous defining use
12+
//~| ERROR defining use generics `[B, A]` differ from previous defining use
1113
(a, a)
1214
}
1315

src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr

+25-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
error: defining use generics `[B, A]` differ from previous defining use
2+
--> $DIR/multiple-def-uses-in-one-fn.rs:10:45
3+
|
4+
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
5+
| ^^^^^^^^^^^^^^^^^^
6+
|
7+
note: previous defining use with different generics `[A, B]` found here
8+
--> $DIR/multiple-def-uses-in-one-fn.rs:10:45
9+
|
10+
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
11+
| ^^^^^^^^^^^^^^^^^^
12+
113
error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
214
--> $DIR/multiple-def-uses-in-one-fn.rs:7:16
315
|
@@ -10,6 +22,18 @@ help: consider introducing a `where` bound, but there might be an alternative be
1022
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
1123
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
1224

13-
error: aborting due to previous error
25+
error: defining use generics `[B, A]` differ from previous defining use
26+
--> $DIR/multiple-def-uses-in-one-fn.rs:10:1
27+
|
28+
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
29+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
30+
|
31+
note: previous defining use with different generics `[A, B]` found here
32+
--> $DIR/multiple-def-uses-in-one-fn.rs:10:1
33+
|
34+
LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
35+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
36+
37+
error: aborting due to 3 previous errors
1438

1539
For more information about this error, try `rustc --explain E0277`.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// https://github.com/rust-lang/rust/issues/73481
2+
// This test used to cause unsoundness, since one of the two possible
3+
// resolutions was chosen at random instead of erroring due to conflicts.
4+
5+
#![feature(min_type_alias_impl_trait)]
6+
7+
type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
8+
9+
fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
10+
//~^ ERROR defining use generics `[B, A]` differ from previous defining use
11+
//~| ERROR defining use generics `[B, A]` differ from previous defining use
12+
(a.clone(), a)
13+
}
14+
15+
fn main() {
16+
println!("{}", <X<_, _> as ToString>::to_string(&f(42_i32, String::new()).1));
17+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
error: defining use generics `[B, A]` differ from previous defining use
2+
--> $DIR/multiple-def-uses-in-one-fn2.rs:9:63
3+
|
4+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
5+
| ^^^^^^^^^^^^^^^^^^
6+
|
7+
note: previous defining use with different generics `[A, B]` found here
8+
--> $DIR/multiple-def-uses-in-one-fn2.rs:9:63
9+
|
10+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
11+
| ^^^^^^^^^^^^^^^^^^
12+
13+
error: defining use generics `[B, A]` differ from previous defining use
14+
--> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
15+
|
16+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
|
19+
note: previous defining use with different generics `[A, B]` found here
20+
--> $DIR/multiple-def-uses-in-one-fn2.rs:9:1
21+
|
22+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error: aborting due to 2 previous errors
26+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// https://github.com/rust-lang/rust/issues/73481
2+
// This test used to cause unsoundness, since one of the two possible
3+
// resolutions was chosen at random instead of erroring due to conflicts.
4+
5+
#![feature(min_type_alias_impl_trait)]
6+
7+
type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
8+
9+
fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
10+
//~^ ERROR defining use generics `[B, A]` differ from previous defining use
11+
//~| ERROR defining use generics `[B, A]` differ from previous defining use
12+
(a, b)
13+
}
14+
15+
fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
16+
(a, b) //~ ERROR mismatched types
17+
}
18+
19+
fn main() {}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
error: defining use generics `[B, A]` differ from previous defining use
2+
--> $DIR/multiple-def-uses-in-one-fn3.rs:9:63
3+
|
4+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
5+
| ^^^^^^^^^^^^^^^^^^
6+
|
7+
note: previous defining use with different generics `[A, B]` found here
8+
--> $DIR/multiple-def-uses-in-one-fn3.rs:9:63
9+
|
10+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
11+
| ^^^^^^^^^^^^^^^^^^
12+
13+
error: defining use generics `[B, A]` differ from previous defining use
14+
--> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
15+
|
16+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
18+
|
19+
note: previous defining use with different generics `[A, B]` found here
20+
--> $DIR/multiple-def-uses-in-one-fn3.rs:9:1
21+
|
22+
LL | fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
23+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
24+
25+
error[E0308]: mismatched types
26+
--> $DIR/multiple-def-uses-in-one-fn3.rs:16:9
27+
|
28+
LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
29+
| - - found type parameter
30+
| |
31+
| expected type parameter
32+
LL | (a, b)
33+
| ^ expected type parameter `A`, found type parameter `B`
34+
|
35+
= note: expected type parameter `A`
36+
found type parameter `B`
37+
= note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound
38+
= note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters
39+
40+
error: aborting due to 3 previous errors
41+
42+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)