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

Lines changed: 10 additions & 2 deletions
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

Lines changed: 46 additions & 18 deletions
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

Lines changed: 17 additions & 6 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 4 additions & 3 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 1 addition & 0 deletions
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

0 commit comments

Comments
 (0)