Improve coherence errors for wrong type order

This commit is contained in:
Ohad Ravid 2019-11-09 17:32:15 +01:00
parent 7e94cc37e8
commit 2db744ca9d
25 changed files with 110 additions and 47 deletions

View file

@ -238,7 +238,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(
pub enum OrphanCheckErr<'tcx> {
NonLocalInputType(Vec<(Ty<'tcx>, bool /* Is this the first input type? */)>),
UncoveredTy(Ty<'tcx>),
UncoveredTy(Ty<'tcx>, Option<Ty<'tcx>>),
}
/// Checks the coherence orphan rules. `impl_def_id` should be the
@ -402,7 +402,15 @@ fn orphan_check_trait_ref<'tcx>(
return Ok(());
} else if let ty::Param(_) = input_ty.kind {
debug!("orphan_check_trait_ref: uncovered ty: `{:?}`", input_ty);
return Err(OrphanCheckErr::UncoveredTy(input_ty))
let local_type = trait_ref
.input_types()
.flat_map(|ty| uncover_fundamental_ty(tcx, ty, in_crate))
.filter(|ty| ty_is_non_local_constructor(tcx, ty, in_crate).is_none())
.next();
debug!("orphan_check_trait_ref: uncovered ty local_type: `{:?}`", local_type);
return Err(OrphanCheckErr::UncoveredTy(input_ty, local_type))
}
if let Some(non_local_tys) = non_local_tys {
for input_ty in non_local_tys {

View file

@ -77,30 +77,58 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
err.emit();
return;
}
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
Err(traits::OrphanCheckErr::UncoveredTy(param_ty, local_type)) => {
let mut sp = sp;
for param in &generics.params {
if param.name.ident().to_string() == param_ty.to_string() {
sp = param.span;
}
}
let mut err = struct_span_err!(
self.tcx.sess,
sp,
E0210,
"type parameter `{}` must be used as the type parameter for some local \
type (e.g., `MyStruct<{}>`)",
param_ty,
param_ty
);
err.span_label(sp, format!(
"type parameter `{}` must be used as the type parameter for some local \
type",
param_ty,
));
err.note("only traits defined in the current crate can be implemented for a \
type parameter");
err.emit();
match local_type {
Some(local_type) => {
struct_span_err!(
self.tcx.sess,
sp,
E0210,
"type parameter `{}` must be covered by another type \
when it appears before the first local type (`{}`)",
param_ty,
local_type
).span_label(sp, format!(
"type parameter `{}` must be covered by another type \
when it appears before the first local type (`{}`)",
param_ty,
local_type
)).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"
).emit();
}
None => {
struct_span_err!(
self.tcx.sess,
sp,
E0210,
"type parameter `{}` must be used as the type parameter for some \
local type (e.g., `MyStruct<{}>`)",
param_ty,
param_ty
).span_label(sp, format!(
"type parameter `{}` must be used as the type parameter for some \
local type",
param_ty,
)).note("implementing a foreign trait is only possible if at \
least one of the types for which is it implemented is local"
).note("only traits defined in the current crate can be \
implemented for a type parameter"
).emit();
}
};
return;
}
}

View file

@ -2124,10 +2124,11 @@ where `P1, ..., Pm` are the type parameters of the `impl` and `T0, ..., Tn`
are types. One of the types `T0, ..., Tn` must be a local type (this is another
orphan rule, see the explanation for E0117).
Both of the folowing must be true:
1. At least one of the types T0..=Tn must be a local type.
Let Ti be the first such type.
2. No uncovered type parameters P1..=Pm may appear in T0..Ti (excluding Ti).
Both of the following must be true:
1. At least one of the types `T0..=Tn` must be a local type.
Let `Ti` be the first such type.
2. No uncovered type parameters `P1..=Pm` may appear in `T0..Ti`
(excluding `Ti`).
For information on the design of the orphan rules,
see [RFC 2451] and [RFC 1023].

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<T> for isize { }
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error

View file

@ -1,10 +1,11 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
--> $DIR/coherence-bigint-param.rs:8:6
|
LL | impl<T> Remote1<BigInt> for T { }
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`BigInt`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= 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
error: aborting due to previous error

View file

@ -13,6 +13,7 @@ error[E0210]: type parameter `A` must be used as the type parameter for some loc
LL | impl<A> Foo for A {
| ^ type parameter `A` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote for T { }
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote for Box<T> {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<u32> for Box<T> {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
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
LL | impl<'a, T> Remote1<u32> for &'a T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<u32> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<Box<T>> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
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
LL | impl<'a, T> Remote1<&'a T> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<'a, T> Remote1<Box<T>> for &'a T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
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
LL | impl<'a, T> Remote1<&'a T> for Box<T> {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<Box<T>> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
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
LL | impl<'a, T> Remote1<&'a T> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors

View file

@ -8,11 +8,11 @@ use std::rc::Rc;
struct Local;
impl<T> Remote2<Box<T>, Local> for u32 {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be covered by another type
}
impl<'a, T> Remote2<&'a T, Local> for u32 {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be covered by another type
}
fn main() {}

View file

@ -1,18 +1,20 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:10:6
|
LL | impl<T> Remote2<Box<T>, Local> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= 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
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/impl[t]-foreign[fundamental[t]_local]-for-foreign.rs:14:10
|
LL | impl<'a, T> Remote2<&'a T, Local> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= 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
error: aborting due to 2 previous errors

View file

@ -8,11 +8,11 @@ use std::rc::Rc;
struct Local;
impl<T> Remote1<Local> for Box<T> {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be covered by another type
}
impl<T> Remote1<Local> for &T {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be covered by another type
}
fn main() {}

View file

@ -1,18 +1,20 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:10:6
|
LL | impl<T> Remote1<Local> for Box<T> {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= 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
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/impl[t]-foreign[local]-for-fundamental[t].rs:14:6
|
LL | impl<T> Remote1<Local> for &T {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= 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
error: aborting due to 2 previous errors

View file

@ -8,7 +8,7 @@ use std::rc::Rc;
struct Local;
impl<T> Remote1<Local> for T {
//~^ ERROR type parameter `T` must be used as the type parameter for some local type
//~^ ERROR type parameter `T` must be covered by another type
}
fn main() {}

View file

@ -1,10 +1,11 @@
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
--> $DIR/impl[t]-foreign[local]-for-t.rs:10:6
|
LL | impl<T> Remote1<Local> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
| ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
|
= note: only traits defined in the current crate can be implemented for a type parameter
= 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
error: aborting due to previous error

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<T> for u32 {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error

View file

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

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Remote1<T> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error

View file

@ -14,6 +14,7 @@ error[E0210]: type parameter `Foo` must be used as the type parameter for some l
LL | impl<Foo> Deref for Foo { }
| ^^^ type parameter `Foo` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors

View file

@ -21,6 +21,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> Drop for T where T: A {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 3 previous errors

View file

@ -4,6 +4,7 @@ error[E0210]: type parameter `T` must be used as the type parameter for some loc
LL | impl<T> RemoteTrait for T where T: LocalTrait {}
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to previous error