Talk about specific types and remove lifetimes from output

This commit is contained in:
Esteban Küber 2019-10-13 11:25:30 -07:00
parent 56aa89cdbe
commit daeafd895d
14 changed files with 100 additions and 43 deletions

View file

@ -237,7 +237,7 @@ pub fn trait_ref_is_local_or_fundamental<'tcx>(
}
pub enum OrphanCheckErr<'tcx> {
NonLocalInputType(Vec<(Ty<'tcx>, usize)>),
NonLocalInputType(Vec<(Ty<'tcx>, bool)>),
UncoveredTy(Ty<'tcx>),
}
@ -355,7 +355,7 @@ pub fn orphan_check(
/// Note that this function is never called for types that have both type
/// parameters and inference variables.
fn orphan_check_trait_ref<'tcx>(
tcx: TyCtxt<'_>,
tcx: TyCtxt<'tcx>,
trait_ref: ty::TraitRef<'tcx>,
in_crate: InCrate,
) -> Result<(), OrphanCheckErr<'tcx>> {
@ -397,14 +397,19 @@ fn orphan_check_trait_ref<'tcx>(
.enumerate()
{
debug!("orphan_check_trait_ref: check ty `{:?}`", input_ty);
if ty_is_local(tcx, input_ty, in_crate) {
let non_local_tys = ty_is_non_local(tcx, input_ty, in_crate);
if non_local_tys.is_none() {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
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))
}
non_local_spans.push((input_ty, i));
if let Some(non_local_tys) = non_local_tys {
for input_ty in non_local_tys {
non_local_spans.push((input_ty, i == 0));
}
}
}
// If we exit above loop, never found a local type.
debug!("orphan_check_trait_ref: no local type");
@ -416,7 +421,8 @@ fn orphan_check_trait_ref<'tcx>(
// first. Find the first input type that either references a
// type parameter OR some local type.
for (i, input_ty) in trait_ref.input_types().enumerate() {
if ty_is_local(tcx, input_ty, in_crate) {
let non_local_tys = ty_is_non_local(tcx, input_ty, in_crate);
if non_local_tys.is_none() {
debug!("orphan_check_trait_ref: ty_is_local `{:?}`", input_ty);
// First local input type. Check that there are no
@ -444,7 +450,11 @@ fn orphan_check_trait_ref<'tcx>(
return Err(OrphanCheckErr::UncoveredTy(param));
}
non_local_spans.push((input_ty, i));
if let Some(non_local_tys) = non_local_tys {
for input_ty in non_local_tys {
non_local_spans.push((input_ty, i == 0));
}
}
}
// If we exit above loop, never found a local type.
debug!("orphan_check_trait_ref: no local type");
@ -452,8 +462,8 @@ fn orphan_check_trait_ref<'tcx>(
}
}
fn uncovered_tys<'tcx>(tcx: TyCtxt<'_>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec<Ty<'tcx>> {
if ty_is_local_constructor(tcx, ty, in_crate) {
fn uncovered_tys<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, in_crate: InCrate) -> Vec<Ty<'tcx>> {
if ty_is_non_local_constructor(tcx, ty, in_crate).is_none() {
vec![]
} else if fundamental_ty(ty) {
ty.walk_shallow()
@ -471,9 +481,23 @@ fn is_possibly_remote_type(ty: Ty<'_>, _in_crate: InCrate) -> bool {
}
}
fn ty_is_local(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool {
ty_is_local_constructor(tcx, ty, in_crate) ||
fundamental_ty(ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, in_crate))
fn ty_is_non_local<'t>(tcx: TyCtxt<'t>, ty: Ty<'t>, in_crate: InCrate) -> Option<Vec<Ty<'t>>> {
match ty_is_non_local_constructor(tcx, ty, in_crate) {
Some(ty) => if !fundamental_ty(ty) {
Some(vec![ty])
} else {
let tys: Vec<_> = ty.walk_shallow()
.filter_map(|t| ty_is_non_local(tcx, t, in_crate))
.flat_map(|i| i)
.collect();
if tys.is_empty() {
None
} else {
Some(tys)
}
},
None => None,
}
}
fn fundamental_ty(ty: Ty<'_>) -> bool {
@ -493,8 +517,12 @@ fn def_id_is_local(def_id: DefId, in_crate: InCrate) -> bool {
}
}
fn ty_is_local_constructor(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bool {
debug!("ty_is_local_constructor({:?})", ty);
fn ty_is_non_local_constructor<'tcx>(
tcx: TyCtxt<'tcx>,
ty: Ty<'tcx>,
in_crate: InCrate,
) -> Option<Ty<'tcx>> {
debug!("ty_is_non_local_constructor({:?})", ty);
match ty.kind {
ty::Bool |
@ -513,18 +541,26 @@ fn ty_is_local_constructor(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bo
ty::Tuple(..) |
ty::Param(..) |
ty::Projection(..) => {
false
Some(ty)
}
ty::Placeholder(..) | ty::Bound(..) | ty::Infer(..) => match in_crate {
InCrate::Local => false,
InCrate::Local => Some(ty),
// The inference variable might be unified with a local
// type in that remote crate.
InCrate::Remote => true,
InCrate::Remote => None,
},
ty::Adt(def, _) => def_id_is_local(def.did, in_crate),
ty::Foreign(did) => def_id_is_local(did, in_crate),
ty::Adt(def, _) => if def_id_is_local(def.did, in_crate) {
None
} else {
Some(ty)
},
ty::Foreign(did) => if def_id_is_local(did, in_crate) {
None
} else {
Some(ty)
},
ty::Opaque(did, _) => {
// Check the underlying type that this opaque
// type resolves to.
@ -532,18 +568,22 @@ fn ty_is_local_constructor(tcx: TyCtxt<'_>, ty: Ty<'_>, in_crate: InCrate) -> bo
// since we've already managed to successfully
// resolve all opaque types by this point
let real_ty = tcx.type_of(did);
ty_is_local_constructor(tcx, real_ty, in_crate)
ty_is_non_local_constructor(tcx, real_ty, in_crate)
}
ty::Dynamic(ref tt, ..) => {
if let Some(principal) = tt.principal() {
def_id_is_local(principal.def_id(), in_crate)
if def_id_is_local(principal.def_id(), in_crate) {
None
} else {
Some(ty)
}
} else {
false
Some(ty)
}
}
ty::Error => true,
ty::Error => None,
ty::UnnormalizedProjection(..) |
ty::Closure(..) |

View file

@ -42,11 +42,28 @@ impl ItemLikeVisitor<'v> for OrphanChecker<'tcx> {
arbitrary types"
);
err.span_label(sp, "impl doesn't use only types from inside the current crate");
for (ty, i) in &tys {
let msg = format!("`{}` is not defined in the current crate", ty);
if *i == 0 {
for (ty, is_target_ty) in &tys {
// FIXME: We want to remove the type arguments from the displayed type.
// The reverse of `resolve_vars_if_possible`.
let mut ty = *ty;
self.tcx.infer_ctxt().enter(|infcx| {
// Remove the lifetimes unnecessary for this error.
ty = infcx.freshen(ty);
});
let msg = format!(
"`{}` is not defined in the current crate{}",
ty,
match &ty.kind {
ty::Slice(_) => " because slices are always considered foreign",
ty::Array(..) => " because arrays are always considered foreign",
_ => "",
},
);
if *is_target_ty {
// Point at `D<A>` in `impl<A, B> for C<B> in D<A>`
err.span_label(impl_ty.span, &msg);
} else {
// Point at `C<B>` in `impl<A, B> for C<B> in D<A>`
err.span_label(tr.path.span, &msg);
}
}

View file

@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Misc for dyn Fundamental<Local> {}
| ^^^^^^^^^^^^^^----------------------
| | |
| | `(dyn coherence_fundamental_trait_lib::Fundamental<Local> + 'static)` is not defined in the current crate
| | `dyn coherence_fundamental_trait_lib::Fundamental<Local>` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -4,7 +4,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Misc for dyn Fundamental<Local> {}
| ^^^^^^^^^^^^^^----------------------
| | |
| | `(dyn coherence_fundamental_trait_lib::Fundamental<Local> + 'static)` is not defined in the current crate
| | `dyn coherence_fundamental_trait_lib::Fundamental<Local>` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -16,7 +16,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl !Send for dyn Marker2 {}
| ^^^^^^^^^^^^^^^-----------
| | |
| | `(dyn Marker2 + 'static)` is not defined in the current crate
| | `dyn Marker2` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -16,7 +16,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | unsafe impl Send for dyn Marker2 {}
| ^^^^^^^^^^^^^^^^^^^^^-----------
| | |
| | `(dyn Marker2 + 'static)` is not defined in the current crate
| | `dyn Marker2` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -73,7 +73,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Copy for [MyType] {}
| ^^^^^^^^^^^^^^--------
| | |
| | `[MyType]` is not defined in the current crate
| | `[MyType]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
@ -84,7 +84,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Copy for &'static [NotSync] {}
| ^^^^^^^^^^^^^^------------------
| | |
| | `&'static [NotSync]` is not defined in the current crate
| | `[NotSync]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -73,7 +73,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Copy for [MyType] {}
| ^^^^^^^^^^^^^^--------
| | |
| | `[MyType]` is not defined in the current crate
| | `[MyType]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
@ -84,7 +84,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Copy for &'static [NotSync] {}
| ^^^^^^^^^^^^^^------------------
| | |
| | `[NotSync]` is not defined in the current crate
| | `[NotSync]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -21,7 +21,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | unsafe impl Send for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^--------
| | |
| | `[MyType]` is not defined in the current crate
| | `[MyType]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
@ -32,7 +32,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | unsafe impl Send for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^------------------
| | |
| | `&'static [NotSync]` is not defined in the current crate
| | `[NotSync]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -21,7 +21,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | unsafe impl Send for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^--------
| | |
| | `[MyType]` is not defined in the current crate
| | `[MyType]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
@ -32,7 +32,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | unsafe impl Send for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^------------------
| | |
| | `[NotSync]` is not defined in the current crate
| | `[NotSync]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -51,7 +51,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Sized for [MyType] {}
| ^^^^^^^^^^^^^^^--------
| | |
| | `[MyType]` is not defined in the current crate
| | `[MyType]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
@ -62,7 +62,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Sized for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^------------------
| | |
| | `&'static [NotSync]` is not defined in the current crate
| | `[NotSync]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -51,7 +51,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Sized for [MyType] {}
| ^^^^^^^^^^^^^^^--------
| | |
| | `[MyType]` is not defined in the current crate
| | `[MyType]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
@ -62,7 +62,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Sized for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^------------------
| | |
| | `[NotSync]` is not defined in the current crate
| | `[NotSync]` is not defined in the current crate because slices are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -10,7 +10,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl<'a> Drop for &'a mut isize {
| ^^^^^^^^^^^^^^^^^^-------------
| | |
| | `&'a mut isize` is not defined in the current crate
| | `isize` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead

View file

@ -16,7 +16,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
LL | impl Copy for Foo { }
| ^^^^^^^^^^^^^^---
| | |
| | `[u8; _]` is not defined in the current crate
| | `[u8; _]` is not defined in the current crate because arrays are always considered foreign
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead