Skip to content

Commit 2db744c

Browse files
committed
Improve coherence errors for wrong type order
1 parent 7e94cc3 commit 2db744c

25 files changed

+110
-47
lines changed

src/librustc/traits/coherence.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(
238238

239239
pub enum OrphanCheckErr<'tcx> {
240240
NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
241-
UncoveredTy(Ty<'tcx>),
241+
UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
242242
}
243243

244244
/// Checks the coherence orphan rules. `impl_def_id` should be the
@@ -402,7 +402,15 @@ fn orphan_check_trait_ref<'tcx>(
402402
return Ok(());
403403
} else if let ty::Param(_) = input_ty.kind {
404404
debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
405-
return Err(OrphanCheckErr::UncoveredTy(input_ty))
405+
let local_type = trait_ref
406+
.input_types()
407+
.flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
408+
.filter(|ty| ty_is_non_local_constructor(tcx, ty, in_crate).is_none())
409+
.next();
410+
411+
debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
412+
413+
return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type))
406414
}
407415
if let Some(non_local_tys) = non_local_tys {
408416
for input_ty in non_local_tys {

src/librustc_typeck/coherence/orphan.rs

+46-18
Original file line numberDiff line numberDiff line change
@@ -77,30 +77,58 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
7777
err.emit();
7878
return;
7979
}
80-
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
80+
Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => {
8181
let mut sp = sp;
8282
for param in &generics.params {
8383
if param.name.ident().to_string() == param_ty.to_string() {
8484
sp = param.span;
8585
}
8686
}
87-
let mut err = struct_span_err!(
88-
self.tcx.sess,
89-
sp,
90-
E0210,
91-
"type parameter `{}` must be used as the type parameter for some local \
92-
type (e.g., `MyStruct<{}>`)",
93-
param_ty,
94-
param_ty
95-
);
96-
err.span_label(sp, format!(
97-
"type parameter `{}` must be used as the type parameter for some local \
98-
type",
99-
param_ty,
100-
));
101-
err.note("only traits defined in the current crate can be implemented for a \
102-
type parameter");
103-
err.emit();
87+
88+
match local_type {
89+
Some(local_type) => {
90+
struct_span_err!(
91+
self.tcx.sess,
92+
sp,
93+
E0210,
94+
"type parameter `{}` must be covered by another type \
95+
when it appears before the first local type (`{}`)",
96+
param_ty,
97+
local_type
98+
).span_label(sp, format!(
99+
"type parameter `{}` must be covered by another type \
100+
when it appears before the first local type (`{}`)",
101+
param_ty,
102+
local_type
103+
)).note("implementing a foreign trait is only possible if at \
104+
least one of the types for which is it implemented is local, \
105+
and no uncovered type parameters appear before that first \
106+
local type"
107+
).note("in this case, 'before' refers to the following order: \
108+
`impl<..> ForeignTrait<T1, ..., Tn> for T0`, \
109+
where `T0` is the first and `Tn` is the last"
110+
).emit();
111+
}
112+
None => {
113+
struct_span_err!(
114+
self.tcx.sess,
115+
sp,
116+
E0210,
117+
"type parameter `{}` must be used as the type parameter for some \
118+
local type (e.g., `MyStruct<{}>`)",
119+
param_ty,
120+
param_ty
121+
).span_label(sp, format!(
122+
"type parameter `{}` must be used as the type parameter for some \
123+
local type",
124+
param_ty,
125+
)).note("implementing a foreign trait is only possible if at \
126+
least one of the types for which is it implemented is local"
127+
).note("only traits defined in the current crate can be \
128+
implemented for a type parameter"
129+
).emit();
130+
}
131+
};
104132
return;
105133
}
106134
}

src/librustc_typeck/error_codes.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2124,10 +2124,11 @@ where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
21242124
are types. One of the types `T0, ..., Tn` must be a local type (this is another
21252125
orphan rule, see the explanation for E0117).
21262126
2127-
Both of the folowing must be true:
2128-
1. At least one of the types T0..=Tn must be a local type.
2129-
Let Ti be the first such type.
2130-
2. No uncovered type parameters P1..=Pm may appear in T0..Ti (excluding Ti).
2127+
Both of the following must be true:
2128+
1. At least one of the types `T0..=Tn` must be a local type.
2129+
Let `Ti` be the first such type.
2130+
2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti`
2131+
(excluding `Ti`).
21312132
21322133
For information on the design of the orphan rules,
21332134
see [RFC 2451] and [RFC 1023].

src/test/ui/coherence/coherence-all-remote.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote1<T> for isize { }
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error: aborting due to previous error

src/test/ui/coherence/coherence-bigint-param.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
22
--> $DIR/coherence-bigint-param.rs:8:6
33
|
44
LL | impl<T> Remote1<BigInt> for T { }
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
66
|
7-
= note: only traits defined in the current crate can be implemented for a type parameter
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
8+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
89

910
error: aborting due to previous error
1011

src/test/ui/coherence/coherence-cross-crate-conflict.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ error[E0210]: type parameter `A` must be used as the type parameter for some loc
1313
LL | impl<A> Foo for A {
1414
| ^ type parameter `A` must be used as the type parameter for some local type
1515
|
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
1617
= note: only traits defined in the current crate can be implemented for a type parameter
1718

1819
error: aborting due to 2 previous errors

src/test/ui/coherence/coherence-lone-type-parameter.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote for T { }
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error: aborting due to previous error

src/test/ui/coherence/impl[t]-foreign-for-fundamental[t].stderr

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote for Box<T> {
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error: aborting due to previous error

src/test/ui/coherence/impl[t]-foreign[foreign]-for-fundamental[t].stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote1<u32> for Box<T> {
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
1213
LL | impl<'a, T> Remote1<u32> for &'a T {
1314
| ^ type parameter `T` must be used as the type parameter for some local type
1415
|
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
1517
= note: only traits defined in the current crate can be implemented for a type parameter
1618

1719
error: aborting due to 2 previous errors

src/test/ui/coherence/impl[t]-foreign[foreign]-for-t.stderr

+1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote1<u32> for T {
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error: aborting due to previous error

src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-foreign.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote1<Box<T>> for u32 {
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
1213
LL | impl<'a, T> Remote1<&'a T> for u32 {
1314
| ^ type parameter `T` must be used as the type parameter for some local type
1415
|
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
1517
= note: only traits defined in the current crate can be implemented for a type parameter
1618

1719
error: aborting due to 2 previous errors

src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-fundamental[t].stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<'a, T> Remote1<Box<T>> for &'a T {
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
1213
LL | impl<'a, T> Remote1<&'a T> for Box<T> {
1314
| ^ type parameter `T` must be used as the type parameter for some local type
1415
|
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
1517
= note: only traits defined in the current crate can be implemented for a type parameter
1618

1719
error: aborting due to 2 previous errors

src/test/ui/coherence/impl[t]-foreign[fundamental[t]]-for-t.stderr

+2
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
44
LL | impl<T> Remote1<Box<T>> for T {
55
| ^ type parameter `T` must be used as the type parameter for some local type
66
|
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
78
= note: only traits defined in the current crate can be implemented for a type parameter
89

910
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
@@ -12,6 +13,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
1213
LL | impl<'a, T> Remote1<&'a T> for T {
1314
| ^ type parameter `T` must be used as the type parameter for some local type
1415
|
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
1517
= note: only traits defined in the current crate can be implemented for a type parameter
1618

1719
error: aborting due to 2 previous errors

src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use std::rc::Rc;
88
struct Local;
99

1010
impl<T> Remote2<Box<T>, Local> for u32 {
11-
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
11+
//~^ ERROR type parameter `T` must be covered by another type
1212
}
1313

1414
impl<'a, T> Remote2<&'a T, Local> for u32 {
15-
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
15+
//~^ ERROR type parameter `T` must be covered by another type
1616
}
1717

1818
fn main() {}

src/test/ui/coherence/impl[t]-foreign[fundamental[t]_local]-for-foreign.stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
22
--> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:10:6
33
|
44
LL | impl<T> Remote2<Box<T>, Local> for u32 {
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
66
|
7-
= note: only traits defined in the current crate can be implemented for a type parameter
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
8+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
89

9-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
10+
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
1011
--> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:14:10
1112
|
1213
LL | impl<'a, T> Remote2<&'a T, Local> for u32 {
13-
| ^ type parameter `T` must be used as the type parameter for some local type
14+
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
1415
|
15-
= note: only traits defined in the current crate can be implemented for a type parameter
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
17+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
1618

1719
error: aborting due to 2 previous errors
1820

src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@ use std::rc::Rc;
88
struct Local;
99

1010
impl<T> Remote1<Local> for Box<T> {
11-
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
11+
//~^ ERROR type parameter `T` must be covered by another type
1212
}
1313

1414
impl<T> Remote1<Local> for &T {
15-
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
15+
//~^ ERROR type parameter `T` must be covered by another type
1616
}
1717

1818
fn main() {}

src/test/ui/coherence/impl[t]-foreign[local]-for-fundamental[t].stderr

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,20 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
22
--> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:10:6
33
|
44
LL | impl<T> Remote1<Local> for Box<T> {
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
66
|
7-
= note: only traits defined in the current crate can be implemented for a type parameter
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
8+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
89

9-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
10+
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
1011
--> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:14:6
1112
|
1213
LL | impl<T> Remote1<Local> for &T {
13-
| ^ type parameter `T` must be used as the type parameter for some local type
14+
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
1415
|
15-
= note: only traits defined in the current crate can be implemented for a type parameter
16+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
17+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
1618

1719
error: aborting due to 2 previous errors
1820

src/test/ui/coherence/impl[t]-foreign[local]-for-t.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ use std::rc::Rc;
88
struct Local;
99

1010
impl<T> Remote1<Local> for T {
11-
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
11+
//~^ ERROR type parameter `T` must be covered by another type
1212
}
1313

1414
fn main() {}

src/test/ui/coherence/impl[t]-foreign[local]-for-t.stderr

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
1-
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
1+
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
22
--> $DIR/impl[t]-foreign[local]-for-t.rs:10:6
33
|
44
LL | impl<T> Remote1<Local> for T {
5-
| ^ type parameter `T` must be used as the type parameter for some local type
5+
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
66
|
7-
= note: only traits defined in the current crate can be implemented for a type parameter
7+
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local, and no uncovered type parameters appear before that first local type
8+
= note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
89

910
error: aborting due to previous error
1011

0 commit comments

Comments
 (0)