Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Coherence diagnostic tweaks #49037

Merged
merged 1 commit into from
Mar 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 26 additions & 21 deletions src/librustc_typeck/coherence/mod.rs
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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`.