Skip to content

Commit

Permalink
Coherence diagnostic tweaks
Browse files Browse the repository at this point in the history
  • Loading branch information
estebank committed Mar 15, 2018
1 parent 883e746 commit 4d5cd21
Show file tree
Hide file tree
Showing 10 changed files with 104 additions and 52 deletions.
47 changes: 26 additions & 21 deletions src/librustc_typeck/coherence/mod.rs
Expand Up @@ -52,10 +52,10 @@ fn check_impl<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeId) {
fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_def_id: DefId) {
let did = Some(trait_def_id);
let li = tcx.lang_items();
let span = tcx.sess.codemap().def_span(tcx.span_of_impl(impl_def_id).unwrap());

// Disallow *all* explicit impls of `Sized` and `Unsize` for now.
if did == li.sized_trait() {
let span = tcx.span_of_impl(impl_def_id).unwrap();
struct_span_err!(tcx.sess,
span,
E0322,
Expand All @@ -66,11 +66,12 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d
}

if did == li.unsize_trait() {
let span = tcx.span_of_impl(impl_def_id).unwrap();
span_err!(tcx.sess,
span,
E0328,
"explicit impls for the `Unsize` trait are not permitted");
struct_span_err!(tcx.sess,
span,
E0328,
"explicit impls for the `Unsize` trait are not permitted")
.span_label(span, "impl of `Unsize` not allowed")
.emit();
return;
}

Expand All @@ -88,14 +89,14 @@ fn enforce_trait_manually_implementable(tcx: TyCtxt, impl_def_id: DefId, trait_d
} else {
return; // everything OK
};
let mut err = struct_span_err!(tcx.sess,
tcx.span_of_impl(impl_def_id).unwrap(),
E0183,
"manual implementations of `{}` are experimental",
trait_name);
help!(&mut err,
"add `#![feature(unboxed_closures)]` to the crate attributes to enable");
err.emit();
struct_span_err!(tcx.sess,
span,
E0183,
"manual implementations of `{}` are experimental",
trait_name)
.span_label(span, format!("manual implementations of `{}` are experimental", trait_name))
.help("add `#![feature(unboxed_closures)]` to the crate attributes to enable")
.emit();
}

pub fn provide(providers: &mut Providers) {
Expand Down Expand Up @@ -168,13 +169,17 @@ fn check_impl_overlap<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, node_id: ast::NodeI
traits::supertrait_def_ids(tcx,
data.principal().unwrap().def_id());
if supertrait_def_ids.any(|d| d == trait_def_id) {
span_err!(tcx.sess,
tcx.span_of_impl(impl_def_id).unwrap(),
E0371,
"the object type `{}` automatically \
implements the trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id));
let sp = tcx.sess.codemap().def_span(tcx.span_of_impl(impl_def_id).unwrap());
struct_span_err!(tcx.sess,
sp,
E0371,
"the object type `{}` automatically implements the trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id))
.span_label(sp, format!("`{}` automatically implements trait `{}`",
trait_ref.self_ty(),
tcx.item_path_str(trait_def_id)))
.emit();
}
}
}
Expand Down
56 changes: 35 additions & 21 deletions src/librustc_typeck/coherence/orphan.rs
Expand Up @@ -40,29 +40,36 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
self.tcx.hir.node_to_string(item.id));
let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
let trait_def_id = trait_ref.def_id;
let cm = self.tcx.sess.codemap();
let sp = cm.def_span(item.span);
match traits::orphan_check(self.tcx, def_id) {
Ok(()) => {}
Err(traits::OrphanCheckErr::NoLocalInputType) => {
struct_span_err!(self.tcx.sess,
item.span,
sp,
E0117,
"only traits defined in the current crate can be \
implemented for arbitrary types")
.span_label(item.span, "impl doesn't use types inside crate")
.note(&format!("the impl does not reference any types defined in \
this crate"))
.span_label(sp, "impl doesn't use types inside crate")
.note("the impl does not reference any types defined in this crate")
.note("define and implement a trait or new type instead")
.emit();
return;
}
Err(traits::OrphanCheckErr::UncoveredTy(param_ty)) => {
span_err!(self.tcx.sess,
item.span,
E0210,
"type parameter `{}` must be used as the type parameter for \
some local type (e.g. `MyStruct<T>`); only traits defined in \
the current crate can be implemented for a type parameter",
param_ty);
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("only traits defined in the current crate can be implemented \
for a type parameter")
.emit();
return;
}
}
Expand Down Expand Up @@ -121,22 +128,29 @@ impl<'cx, 'tcx, 'v> ItemLikeVisitor<'v> for OrphanChecker<'cx, 'tcx> {
if self_def_id.is_local() {
None
} else {
Some(format!("cross-crate traits with a default impl, like `{}`, \
can only be implemented for a struct/enum type \
defined in the current crate",
self.tcx.item_path_str(trait_def_id)))
Some((
format!("cross-crate traits with a default impl, like `{}`, \
can only be implemented for a struct/enum type \
defined in the current crate",
self.tcx.item_path_str(trait_def_id)),
"can't implement cross-crate trait for type in another crate"
))
}
}
_ => {
Some(format!("cross-crate traits with a default impl, like `{}`, can \
only be implemented for a struct/enum type, not `{}`",
self.tcx.item_path_str(trait_def_id),
self_ty))
Some((format!("cross-crate traits with a default impl, like `{}`, can \
only be implemented for a struct/enum type, not `{}`",
self.tcx.item_path_str(trait_def_id),
self_ty),
"can't implement cross-crate trait with a default impl for \
non-struct/enum type"))
}
};

if let Some(msg) = msg {
span_err!(self.tcx.sess, item.span, E0321, "{}", msg);
if let Some((msg, label)) = msg {
struct_span_err!(self.tcx.sess, sp, E0321, "{}", msg)
.span_label(sp, label)
.emit();
return;
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/codemap_tests/empty_span.stderr
Expand Up @@ -2,7 +2,7 @@ error[E0321]: cross-crate traits with a default impl, like `std::marker::Send`,
--> $DIR/empty_span.rs:17:5
|
LL | unsafe impl Send for &'static Foo { } //~ ERROR cross-crate traits with a default impl
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait with a default impl for non-struct/enum type

error: aborting due to previous error

Expand Down
6 changes: 3 additions & 3 deletions src/test/ui/coherence-impls-copy.stderr
Expand Up @@ -32,7 +32,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
--> $DIR/coherence-impls-copy.rs:33:1
|
LL | impl Copy for (MyType, MyType) {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead
Expand All @@ -41,7 +41,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
--> $DIR/coherence-impls-copy.rs:40:1
|
LL | impl Copy for [MyType] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
| ^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead
Expand All @@ -50,7 +50,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
--> $DIR/coherence-impls-copy.rs:44:1
|
LL | impl Copy for &'static [NotSync] {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead
Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/e0119/complex-impl.stderr
Expand Up @@ -8,11 +8,13 @@ LL | impl<R> External for (Q, R) {} //~ ERROR must be used
- impl<'a, 'b, 'c, T, U, V, W> complex_impl_support::External for (T, complex_impl_support::M<'a, 'b, 'c, std::boxed::Box<U>, V, W>)
where <U as std::ops::FnOnce<(T,)>>::Output == V, <V as std::iter::Iterator>::Item == T, 'b : 'a, T : 'a, U: std::ops::FnOnce<(T,)>, U : 'static, V: std::iter::Iterator, V: std::clone::Clone, W: std::ops::Add, <W as std::ops::Add>::Output: std::marker::Copy;

error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g. `MyStruct<R>`)
--> $DIR/complex-impl.rs:19:1
|
LL | impl<R> External for (Q, R) {} //~ ERROR must be used
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^ type parameter `R` 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

error: aborting due to 2 previous errors

Expand Down
6 changes: 4 additions & 2 deletions src/test/ui/e0119/issue-28981.stderr
Expand Up @@ -8,11 +8,13 @@ LL | impl<Foo> Deref for Foo { } //~ ERROR must be used
- impl<'a, T> std::ops::Deref for &'a T
where T: ?Sized;

error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct<T>`); only traits defined in the current crate can be implemented for a type parameter
error[E0210]: type parameter `Foo` must be used as the type parameter for some local type (e.g. `MyStruct<Foo>`)
--> $DIR/issue-28981.rs:15:1
|
LL | impl<Foo> Deref for Foo { } //~ ERROR must be used
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
| ^^^^^^^^^^^^^^^^^^^^^^^ type parameter `Foo` 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

error: aborting due to 2 previous errors

Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0117.stderr
Expand Up @@ -8,7 +8,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
--> $DIR/E0117.rs:11:1
|
LL | impl Drop for u32 {} //~ ERROR E0117
| ^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead
Expand Down
2 changes: 1 addition & 1 deletion src/test/ui/error-codes/E0206.stderr
Expand Up @@ -14,7 +14,7 @@ error[E0117]: only traits defined in the current crate can be implemented for ar
--> $DIR/E0206.rs:13:1
|
LL | impl Copy for Foo { }
| ^^^^^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
| ^^^^^^^^^^^^^^^^^ impl doesn't use types inside crate
|
= note: the impl does not reference any types defined in this crate
= note: define and implement a trait or new type instead
Expand Down
20 changes: 20 additions & 0 deletions src/test/ui/error-codes/E0328.rs
@@ -0,0 +1,20 @@
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

#![feature(unsize)]

use std::marker::Unsize;

pub struct MyType;

impl<T> Unsize<T> for MyType {}
//~^ ERROR explicit impls for the `Unsize` trait are not permitted [E0328]

fn main() {}
9 changes: 9 additions & 0 deletions src/test/ui/error-codes/E0328.stderr
@@ -0,0 +1,9 @@
error[E0328]: explicit impls for the `Unsize` trait are not permitted
--> $DIR/E0328.rs:17:1
|
LL | impl<T> Unsize<T> for MyType {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unsize` not allowed

error: aborting due to previous error

For more information about this error, try `rustc --explain E0328`.

0 comments on commit 4d5cd21

Please sign in to comment.