Skip to content

Commit 79e2afc

Browse files
authored
Rollup merge of rust-lang#66253 - ohadravid:improve-errors-after-re-rebalance-coherence, r=estebank
Improve errors after re rebalance coherence Following rust-lang#65247, I noticed that some error messages should be updated to reflect the changes of `re_rebalance_coherence` (also there was a [note](https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html#teaching-users) in the RFC about it). First, error message `E0210` was updated to match the RFC, and I also tried to improve a little the error when the "order" of types is problematic. For code like this: ``` #![feature(re_rebalance_coherence)] // Now stable struct Wrap<T>(T); impl<T> From<Wrap<T>> for T { fn from(x: Wrap<T>) -> T { x.0 } } ``` The old error was: ``` error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`) --> src/lib.rs:5:6 | 5 | impl<T> From<Wrap<T>> for T { | ^ type parameter `T` must be used as the type parameter for some local type | = note: only traits defined in the current crate can be implemented for a type parameter ``` and the new error is: ``` error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Wrap<T>`) --> main.rs:66:6 | 66 | impl<T> From<Wrap<T>> for T { | ^ type parameter `T` must be covered by another type when it appears before the first local type (`Wrap<T>`) | = 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 = 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 ``` I tried to point at the uncovered `T`, but couldn't get something which was reliable (but I'll be happy to try if someone points me in the right direction). r? @estebank cc @nikomatsakis Fixes rust-lang#65247
2 parents 3f07f1c + 2db744c commit 79e2afc

25 files changed

+122
-49
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

+17-6
Original file line numberDiff line numberDiff line change
@@ -2114,8 +2114,13 @@ E0210: r##"
21142114
This error indicates a violation of one of Rust's orphan rules for trait
21152115
implementations. The rule concerns the use of type parameters in an
21162116
implementation of a foreign trait (a trait defined in another crate), and
2117-
states that type parameters must be "covered" by a local type. To understand
2118-
what this means, it is perhaps easiest to consider a few examples.
2117+
states that type parameters must be "covered" by a local type.
2118+
2119+
When implementing a foreign trait for a foreign type,
2120+
the trait must have one or more type parameters.
2121+
A type local to your crate must appear before any use of any type parameters.
2122+
2123+
To understand what this means, it is perhaps easier to consider a few examples.
21192124
21202125
If `ForeignTrait` is a trait defined in some external crate `foo`, then the
21212126
following trait `impl` is an error:
@@ -2173,12 +2178,18 @@ impl<P1, ..., Pm> ForeignTrait<T1, ..., Tn> for T0 { ... }
21732178
21742179
where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
21752180
are types. One of the types `T0, ..., Tn` must be a local type (this is another
2176-
orphan rule, see the explanation for E0117). Let `i` be the smallest integer
2177-
such that `Ti` is a local type. Then no type parameter can appear in any of the
2178-
`Tj` for `j < i`.
2181+
orphan rule, see the explanation for E0117).
21792182
2180-
For information on the design of the orphan rules, see [RFC 1023].
2183+
Both of the following must be true:
2184+
1. At least one of the types `T0..=Tn` must be a local type.
2185+
Let `Ti` be the first such type.
2186+
2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti`
2187+
(excluding `Ti`).
2188+
2189+
For information on the design of the orphan rules,
2190+
see [RFC 2451] and [RFC 1023].
21812191
2192+
[RFC 2451]: https://rust-lang.github.io/rfcs/2451-re-rebalancing-coherence.html
21822193
[RFC 1023]: https://github.com/rust-lang/rfcs/blob/master/text/1023-rebalancing-coherence.md
21832194
"##,
21842195

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() {}

0 commit comments

Comments
 (0)