From 4d5cd21a0db601636d88f4c95f50435b04bf71df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 14 Mar 2018 19:10:28 -0700 Subject: [PATCH] Coherence diagnostic tweaks --- src/librustc_typeck/coherence/mod.rs | 47 +++++++++-------- src/librustc_typeck/coherence/orphan.rs | 56 +++++++++++++-------- src/test/ui/codemap_tests/empty_span.stderr | 2 +- src/test/ui/coherence-impls-copy.stderr | 6 +-- src/test/ui/e0119/complex-impl.stderr | 6 ++- src/test/ui/e0119/issue-28981.stderr | 6 ++- src/test/ui/error-codes/E0117.stderr | 2 +- src/test/ui/error-codes/E0206.stderr | 2 +- src/test/ui/error-codes/E0328.rs | 20 ++++++++ src/test/ui/error-codes/E0328.stderr | 9 ++++ 10 files changed, 104 insertions(+), 52 deletions(-) create mode 100644 src/test/ui/error-codes/E0328.rs create mode 100644 src/test/ui/error-codes/E0328.stderr diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index d3de31d630a97..07b7c600b9f30 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -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, @@ -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; } @@ -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) { @@ -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(); } } } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index c2dfd798a3c4a..6d6594e55437d 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -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`); 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; } } @@ -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; } } diff --git a/src/test/ui/codemap_tests/empty_span.stderr b/src/test/ui/codemap_tests/empty_span.stderr index 63b19c9e0c6ab..2df1d69acdbd9 100644 --- a/src/test/ui/codemap_tests/empty_span.stderr +++ b/src/test/ui/codemap_tests/empty_span.stderr @@ -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 diff --git a/src/test/ui/coherence-impls-copy.stderr b/src/test/ui/coherence-impls-copy.stderr index 029b04789525c..c276d8b95102a 100644 --- a/src/test/ui/coherence-impls-copy.stderr +++ b/src/test/ui/coherence-impls-copy.stderr @@ -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 @@ -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 @@ -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 diff --git a/src/test/ui/e0119/complex-impl.stderr b/src/test/ui/e0119/complex-impl.stderr index b268c75540452..7e0e8ff0372f2 100644 --- a/src/test/ui/e0119/complex-impl.stderr +++ b/src/test/ui/e0119/complex-impl.stderr @@ -8,11 +8,13 @@ LL | impl 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, V, W>) where >::Output == V, ::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, ::Output: std::marker::Copy; -error[E0210]: type parameter `R` must be used as the type parameter for some local type (e.g. `MyStruct`); 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`) --> $DIR/complex-impl.rs:19:1 | LL | impl 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 diff --git a/src/test/ui/e0119/issue-28981.stderr b/src/test/ui/e0119/issue-28981.stderr index b1ec1111ede91..ade072336bccd 100644 --- a/src/test/ui/e0119/issue-28981.stderr +++ b/src/test/ui/e0119/issue-28981.stderr @@ -8,11 +8,13 @@ LL | impl 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`); 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`) --> $DIR/issue-28981.rs:15:1 | LL | impl 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 diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr index 240aa4240cc6f..397028863484a 100644 --- a/src/test/ui/error-codes/E0117.stderr +++ b/src/test/ui/error-codes/E0117.stderr @@ -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 diff --git a/src/test/ui/error-codes/E0206.stderr b/src/test/ui/error-codes/E0206.stderr index 0cd22a454e122..6c671967e84f1 100644 --- a/src/test/ui/error-codes/E0206.stderr +++ b/src/test/ui/error-codes/E0206.stderr @@ -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 diff --git a/src/test/ui/error-codes/E0328.rs b/src/test/ui/error-codes/E0328.rs new file mode 100644 index 0000000000000..e08532b02491f --- /dev/null +++ b/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 or the MIT license +// , 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 Unsize for MyType {} +//~^ ERROR explicit impls for the `Unsize` trait are not permitted [E0328] + +fn main() {} diff --git a/src/test/ui/error-codes/E0328.stderr b/src/test/ui/error-codes/E0328.stderr new file mode 100644 index 0000000000000..ad3a224279ce5 --- /dev/null +++ b/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 Unsize for MyType {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Unsize` not allowed + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0328`.