From 81e40278bd0ad707a3be2396a076f151d1ff1072 Mon Sep 17 00:00:00 2001 From: Erin Power Date: Sun, 9 Feb 2020 10:39:48 +0100 Subject: [PATCH 01/31] Update RELEASES.md for 1.42.0 --- RELEASES.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 10e485c1a40d5..715c6b5eaaaf1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,80 @@ +Version 1.42.0 (2020-03-12) +========================== + +Language +-------- +- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning + that you can create an enum that has the exact layout and ABI of the type + it contains. +- [You can now use the slice pattern syntax with subslices.][67712] e.g. + ```rust + fn foo(words: &[&str]) { + match words { + ["Hello", "World", "!", ..] => println!("Hello World!"), + ["Foo", "Bar", ..] => println!("Baz"), + rest => println!("{}", rest), + } + } + ``` + +- [Merge `TraitItem` & `ImplItem into `AssocItem`][67131] + +Compiler +-------- +- [Added tier 3\* support for `armv7a-none-eabi`.][68253] +- [Added tier 3 support for `riscv64gc-unknown-linux-gnu`.][68037] +- [`Option::{expect,unwrap}` and + `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages + pointing to the location where they were called, rather than + `core`'s internals. ][67887] + +Libraries +--------- +- [`iter::Empty` now implements Send and Sync for any `T`.][68348] +- [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type + to implement `Sized`.][67935] +- [`io::Cursor` now derives `PartialEq` and `Eq`.][67233] +- [`Layout::new` is now `const`.][66254] +- [Added Standard Library support for `riscv64gc-unknown-linux-gnu`.][66899] + + +Stabilized APIs +--------------- +- [`DebugMap::key`] +- [`DebugMap::value`] +- [`ManuallyDrop::take`] +- [`matches!`] +- [`ptr::slice_from_raw_parts_mut`] +- [`ptr::slice_from_raw_parts`] +- [`wait_timeout_while`] +- [`wait_while`] + +Compatibility Notes +------------------- +- [`Error::description` has been deprecated, and its use will now produce a + warning.][66919] It's recommended to use `Display`/`to_string` instead. + +[68253]: https://github.com/rust-lang/rust/pull/68253/ +[68348]: https://github.com/rust-lang/rust/pull/68348/ +[67935]: https://github.com/rust-lang/rust/pull/67935/ +[68037]: https://github.com/rust-lang/rust/pull/68037/ +[68122]: https://github.com/rust-lang/rust/pull/68122/ +[67712]: https://github.com/rust-lang/rust/pull/67712/ +[67887]: https://github.com/rust-lang/rust/pull/67887/ +[67131]: https://github.com/rust-lang/rust/pull/67131/ +[67233]: https://github.com/rust-lang/rust/pull/67233/ +[66899]: https://github.com/rust-lang/rust/pull/66899/ +[66919]: https://github.com/rust-lang/rust/pull/66919/ +[66254]: https://github.com/rust-lang/rust/pull/66254/ +[`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key +[`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value +[`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take +[`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html +[`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html +[`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html +[`wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while + + Version 1.41.0 (2020-01-30) =========================== From 26fdcbbc2810474770bb7f87d410a1e34b142b87 Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Sun, 9 Feb 2020 14:35:08 +0100 Subject: [PATCH 02/31] Update RELEASES.md --- RELEASES.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 715c6b5eaaaf1..ddd2a0a0e3b6a 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -49,6 +49,11 @@ Stabilized APIs - [`wait_timeout_while`] - [`wait_while`] +Cargo +----- +- [You no longer need to include `extern crate proc_macro;` to be able to + `use proc_macro;` in the `2018` edition.][cargo/7700] + Compatibility Notes ------------------- - [`Error::description` has been deprecated, and its use will now produce a @@ -66,6 +71,7 @@ Compatibility Notes [66899]: https://github.com/rust-lang/rust/pull/66899/ [66919]: https://github.com/rust-lang/rust/pull/66919/ [66254]: https://github.com/rust-lang/rust/pull/66254/ +[cargo/7700]: https://github.com/rust-lang/cargo/pull/7700 [`DebugMap::key`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.key [`DebugMap::value`]: https://doc.rust-lang.org/stable/std/fmt/struct.DebugMap.html#method.value [`ManuallyDrop::take`]: https://doc.rust-lang.org/stable/std/mem/struct.ManuallyDrop.html#method.take From 7ab01b24674b88ff4927b0eb445a582fb9e12aba Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Mon, 10 Feb 2020 05:07:39 +0100 Subject: [PATCH 03/31] Update RELEASES.md Co-Authored-By: Mazdak Farrokhzad --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index ddd2a0a0e3b6a..f97d902d332e2 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -30,7 +30,7 @@ Compiler Libraries --------- -- [`iter::Empty` now implements Send and Sync for any `T`.][68348] +- [`iter::Empty` now implements `Send` and `Sync` for any `T`.][68348] - [`Pin::{map_unchecked, map_unchecked_mut}` no longer require the return type to implement `Sized`.][67935] - [`io::Cursor` now derives `PartialEq` and `Eq`.][67233] From 32daa2aa38fafd731ddc27374dece22f38069bc8 Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Mon, 10 Feb 2020 15:29:14 +0100 Subject: [PATCH 04/31] Update RELEASES.md --- RELEASES.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/RELEASES.md b/RELEASES.md index f97d902d332e2..5d10e658f9015 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -12,7 +12,7 @@ Language match words { ["Hello", "World", "!", ..] => println!("Hello World!"), ["Foo", "Bar", ..] => println!("Baz"), - rest => println!("{}", rest), + rest => println!("{:?}", rest), } } ``` From b0302806680da26e686ce6f0432044fcbdb4b373 Mon Sep 17 00:00:00 2001 From: Ana-Maria Date: Tue, 18 Feb 2020 15:36:05 +0000 Subject: [PATCH 05/31] Blacklist powerpc-unknown-linux-gnu as having non-ignored GNU C ZSTs. --- src/librustc/ty/layout.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index e8bf2eb9a12c9..753808bc25492 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2547,6 +2547,8 @@ where target.target_os == "linux" && target.arch == "s390x" && target.target_env == "gnu"; let linux_sparc64 = target.target_os == "linux" && target.arch == "sparc64" && target.target_env == "gnu"; + let linux_powerpc = + target.target_os == "linux" && target.arch == "powerpc" && target.target_env == "gnu"; let rust_abi = match sig.abi { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true, _ => false, @@ -2617,9 +2619,12 @@ where if arg.layout.is_zst() { // For some forsaken reason, x86_64-pc-windows-gnu // doesn't ignore zero-sized struct arguments. - // The same is true for s390x-unknown-linux-gnu - // and sparc64-unknown-linux-gnu. - if is_return || rust_abi || (!win_x64_gnu && !linux_s390x && !linux_sparc64) { + // The same is true for s390x-unknown-linux-gnu, + // sparc64-unknown-linux-gnu and powerpc-unknown-linux-gnu. + if is_return + || rust_abi + || (!win_x64_gnu && !linux_s390x && !linux_sparc64 && !linux_powerpc) + { arg.mode = PassMode::Ignore; } } From 9fa8d87797f153b9b672cf0e3795e8cba545ee6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 17 Feb 2020 23:22:19 -0800 Subject: [PATCH 06/31] Add more context to E0599 errors Point at the intermediary unfullfilled trait bounds. --- .../infer/error_reporting/note.rs | 3 +- src/librustc_typeck/check/method/probe.rs | 43 ++++++++++++++---- src/librustc_typeck/check/method/suggest.rs | 45 +++++++++++++++++-- .../ui/consts/too_generic_eval_ice.stderr | 4 +- .../derives/derive-assoc-type-not-impl.stderr | 11 ++++- src/test/ui/issues/issue-21596.stderr | 3 +- src/test/ui/issues/issue-31173.rs | 4 ++ src/test/ui/issues/issue-31173.stderr | 19 +++++--- src/test/ui/issues/issue-35677.stderr | 4 +- .../option-as_deref.stderr | 2 +- .../option-as_deref_mut.stderr | 2 +- .../result-as_deref.stderr | 2 +- .../result-as_deref_err.stderr | 2 +- .../result-as_deref_mut.stderr | 2 +- .../result-as_deref_mut_err.stderr | 2 +- .../ui/methods/method-call-err-msg.stderr | 8 +++- src/test/ui/mismatched_types/issue-36053-2.rs | 4 ++ .../ui/mismatched_types/issue-36053-2.stderr | 18 +++++--- .../method-help-unsatisfied-bound.stderr | 5 ++- ...pecialization-trait-not-implemented.stderr | 7 ++- .../suggestions/mut-borrow-needed-by-trait.rs | 4 ++ .../mut-borrow-needed-by-trait.stderr | 16 ++++--- src/test/ui/union/union-derive-clone.stderr | 11 ++++- src/test/ui/unique-object-noncopyable.rs | 4 ++ src/test/ui/unique-object-noncopyable.stderr | 17 ++++++- src/test/ui/unique-pinned-nocopy.rs | 4 ++ src/test/ui/unique-pinned-nocopy.stderr | 13 +++++- 27 files changed, 203 insertions(+), 56 deletions(-) diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs index 7a7cfdecbaf7d..5c0caa48d0e77 100644 --- a/src/librustc_infer/infer/error_reporting/note.rs +++ b/src/librustc_infer/infer/error_reporting/note.rs @@ -645,8 +645,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { self.tcx.sess, span, E0491, - "in type `{}`, reference has a longer lifetime \ - than the data it references", + "in type `{}`, reference has a longer lifetime than the data it references", self.ty_to_string(ty) ); note_and_explain_region( diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index ea90aef486839..0d6f8e9b7e683 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1404,15 +1404,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { // `potentially_unsatisfied_predicates`. return ProbeResult::NoMatch; } else { - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); + self.probe(|_| { + match self.select_trait_candidate(trait_ref) { + Ok(Some(traits::VtableImpl(traits::VtableImplData { + nested, + .. + }))) if !nested.is_empty() => { + for obligation in nested { + // Determine exactly which obligation wasn't met, so + // that we can give more context in the error. + if !self.predicate_may_hold(&obligation) { + result = ProbeResult::NoMatch; + if let Some(poly_trait_ref) = + obligation.predicate.to_opt_poly_trait_ref() + { + let trait_ref = poly_trait_ref.clone(); + let trait_ref = trait_ref.skip_binder(); + possibly_unsatisfied_predicates + .push(*trait_ref); + } + } + } + } + _ => {} + } + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let trait_ref = self.resolve_vars_if_possible(&trait_ref); + possibly_unsatisfied_predicates.push(trait_ref); + }); } } vec![] diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index ea83b40a1cb6b..bd87626b438d0 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -394,6 +394,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.diagnostic().struct_dummy() }; + // FIXME: Unify with unmet bound label. if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir().span_if_local(def.did) { let def_sp = tcx.sess.source_map().def_span(full_sp); @@ -535,16 +536,54 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !unsatisfied_predicates.is_empty() { + let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .map(|p| format!("`{} : {}`", p.self_ty(), p.print_only_trait_path())) + .map(|p| { + let self_ty = p.self_ty(); + match &self_ty.kind { + ty::Adt(def, _) => bound_spans.push(( + self.tcx.sess.source_map().def_span(self.tcx.def_span(def.did)), + format!( + "this type doesn't satisfy the bound `{}`", + p.print_only_trait_path() + ), + )), + ty::Dynamic(preds, _) => { + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans + .push(( + self.tcx + .sess + .source_map() + .def_span(self.tcx.def_span(tr.def_id)), + format!( + "this trait doesn't satisfy the bound `{}`", + p.print_only_trait_path() + ), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } + } + } + _ => {} + }; + format!("`{}: {}`", p.self_ty(), p.print_only_trait_path()) + }) .collect::>(); bound_list.sort(); bound_list.dedup(); // #35677 + bound_spans.sort(); + bound_spans.dedup(); // #35677 + for (span, msg) in bound_spans.into_iter() { + err.span_label(span, &msg); + } let bound_list = bound_list.join("\n"); err.note(&format!( - "the method `{}` exists but the following trait bounds \ - were not satisfied:\n{}", + "the method `{}` exists but the following trait bounds were not \ + satisfied:\n{}", item_name, bound_list )); } diff --git a/src/test/ui/consts/too_generic_eval_ice.stderr b/src/test/ui/consts/too_generic_eval_ice.stderr index fd68cb9c6cf85..8836de0023c9d 100644 --- a/src/test/ui/consts/too_generic_eval_ice.stderr +++ b/src/test/ui/consts/too_generic_eval_ice.stderr @@ -8,8 +8,8 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | ^^^^^^^^^ associated item not found in `Foo` | = note: the method `HOST_SIZE` exists but the following trait bounds were not satisfied: - `A : std::marker::Sized` - `B : std::marker::Sized` + `A: std::marker::Sized` + `B: std::marker::Sized` error[E0277]: the size for values of type `A` cannot be known at compilation time --> $DIR/too_generic_eval_ice.rs:7:13 diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 2083a1d65220f..2746d8b7a14e1 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,13 +2,20 @@ error[E0599]: no method named `clone` found for struct `Bar` in the cu --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ method `clone` not found for this + | ------------------ + | | + | method `clone` not found for this + | this type doesn't satisfy the bound `std::clone::Clone` +... +LL | struct NotClone; + | ---------------- this type doesn't satisfy the bound `std::clone::Clone` ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `Bar : std::clone::Clone` + `Bar: std::clone::Clone` + `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index efde16167b71b..d98302552cad4 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -7,7 +7,8 @@ LL | println!("{}", z.to_string()); = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: - `*const u8 : std::string::ToString` + `*const u8: std::fmt::Display` + `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs index 26195318380d2..25be266c52893 100644 --- a/src/test/ui/issues/issue-31173.rs +++ b/src/test/ui/issues/issue-31173.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl use std::vec::IntoIter; pub fn get_tok(it: &mut IntoIter) { diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index a614b96ac1439..77cb7fb0426e5 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -1,5 +1,5 @@ -error[E0271]: type mismatch resolving `, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]> as std::iter::Iterator>::Item == &_` - --> $DIR/issue-31173.rs:10:10 +error[E0271]: type mismatch resolving `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item == &_` + --> $DIR/issue-31173.rs:14:10 | LL | .cloned() | ^^^^^^ expected `u8`, found reference @@ -7,15 +7,20 @@ LL | .cloned() = note: expected type `u8` found reference `&_` -error[E0599]: no method named `collect` found for struct `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` in the current scope - --> $DIR/issue-31173.rs:14:10 +error[E0599]: no method named `collect` found for struct `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` in the current scope + --> $DIR/issue-31173.rs:18:10 | LL | .collect(); - | ^^^^^^^ method not found in `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>>` + | ^^^^^^^ method not found in `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>` + | + ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL + | +LL | pub struct Cloned { + | -------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator` - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:6:39: 9:6 found_e:_]>> : std::iter::Iterator` + `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-35677.stderr b/src/test/ui/issues/issue-35677.stderr index a998f95d306cb..978221e502f80 100644 --- a/src/test/ui/issues/issue-35677.stderr +++ b/src/test/ui/issues/issue-35677.stderr @@ -5,8 +5,8 @@ LL | this.is_subset(other) | ^^^^^^^^^ method not found in `&std::collections::HashSet` | = note: the method `is_subset` exists but the following trait bounds were not satisfied: - `T : std::cmp::Eq` - `T : std::hash::Hash` + `T: std::cmp::Eq` + `T: std::hash::Hash` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index f91f6e891ed90..c6d9a8415dd6c 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,7 +5,7 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` + `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index 583236345cac1..ae51052a22c3a 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,7 +5,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` + `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index fae11fe62b16c..3f7904a852165 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,7 +5,7 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` + `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index 1d98361c46198..eb591b419ea82 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,7 +5,7 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::Deref` + `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 2c6231fb3b589..115518dcf6760 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,7 +5,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` + `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 950a050ea9f81..49f4a16d8ae97 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,7 +5,7 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: - `{integer} : std::ops::DerefMut` + `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index ab1ef5b9d5aed..0c48e93347d85 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -35,13 +35,17 @@ error[E0599]: no method named `take` found for struct `Foo` in the current scope --> $DIR/method-call-err-msg.rs:19:7 | LL | pub struct Foo; - | --------------- method `take` not found for this + | --------------- + | | + | method `take` not found for this + | this type doesn't satisfy the bound `std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `&mut Foo : std::iter::Iterator` + `&mut Foo: std::iter::Iterator` + `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.rs b/src/test/ui/mismatched_types/issue-36053-2.rs index 9035e3380b0c5..36211b4ce701d 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.rs +++ b/src/test/ui/mismatched_types/issue-36053-2.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl // Regression test for #36053. ICE was caused due to obligations // being added to a special, dedicated fulfillment cx during // a probe. diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index f8d677b99d693..2b8b2d82ec23c 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -1,15 +1,21 @@ -error[E0599]: no method named `count` found for struct `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` in the current scope - --> $DIR/issue-36053-2.rs:7:55 +error[E0599]: no method named `count` found for struct `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` in the current scope + --> $DIR/issue-36053-2.rs:11:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]>` + | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` + | + ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL + | +LL | pub struct Filter { + | ----------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:7:39: 7:53]> : std::iter::Iterator` + `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments - --> $DIR/issue-36053-2.rs:7:32 + --> $DIR/issue-36053-2.rs:11:32 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); | ^^^^^^ -------------- found signature of `for<'r> fn(&'r str) -> _` diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index bbfb00050566a..a7681f9af5b22 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -1,11 +1,14 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), Foo>` in the current scope --> $DIR/method-help-unsatisfied-bound.rs:5:7 | +LL | struct Foo; + | ----------- this type doesn't satisfy the bound `std::fmt::Debug` +... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` | = note: the method `unwrap` exists but the following trait bounds were not satisfied: - `Foo : std::fmt::Debug` + `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 19809778a5e36..2d0caf1dd8755 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -2,13 +2,16 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | struct MyStruct; - | ---------------- method `foo_one` not found for this + | ---------------- + | | + | method `foo_one` not found for this + | this type doesn't satisfy the bound `Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | = note: the method `foo_one` exists but the following trait bounds were not satisfied: - `MyStruct : Foo` + `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `foo_one`, perhaps you need to implement it: candidate #1: `Foo` diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs index f8b86377187c5..49a37498fd955 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl use std::env::args; use std::fs::File; use std::io::{stdout, Write, BufWriter}; diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 8dc041ace3662..5de7295f4f4fa 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:29 + --> $DIR/mut-borrow-needed-by-trait.rs:21:29 | LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -8,7 +8,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter::::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + --> $DIR/mut-borrow-needed-by-trait.rs:21:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -17,7 +17,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:17:14 + --> $DIR/mut-borrow-needed-by-trait.rs:21:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -26,13 +26,19 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope - --> $DIR/mut-borrow-needed-by-trait.rs:22:5 + --> $DIR/mut-borrow-needed-by-trait.rs:26:5 | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` + | + ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL + | +LL | pub struct BufWriter { + | ------------------------------ this type doesn't satisfy the bound `std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `std::io::BufWriter<&dyn std::io::Write> : std::io::Write` + `&dyn std::io::Write: std::io::Write` + `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 12b5321331a79..289b680a46ea1 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,13 +11,20 @@ error[E0599]: no method named `clone` found for union `U5` in the c --> $DIR/union-derive-clone.rs:37:15 | LL | union U5 { - | ----------- method `clone` not found for this + | ----------- + | | + | method `clone` not found for this + | this type doesn't satisfy the bound `std::clone::Clone` +... +LL | struct CloneNoCopy; + | ------------------- this type doesn't satisfy the bound `std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `U5 : std::clone::Clone` + `CloneNoCopy: std::marker::Copy` + `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index dd38a7190aa0e..bedaf27c2dddf 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl #![feature(box_syntax)] trait Foo { diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 92cda6482c0d9..192558f6b0923 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,11 +1,24 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-object-noncopyable.rs:24:16 + --> $DIR/unique-object-noncopyable.rs:28:16 | +LL | trait Foo { + | --------- + | | + | this trait doesn't satisfy the bound `std::clone::Clone` + | this trait doesn't satisfy the bound `std::marker::Sized` +... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `std::boxed::Box : std::clone::Clone` + `dyn Foo: std::clone::Clone` + `dyn Foo: std::marker::Sized` + `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs index 4c30450c70455..091b8a4386235 100644 --- a/src/test/ui/unique-pinned-nocopy.rs +++ b/src/test/ui/unique-pinned-nocopy.rs @@ -1,3 +1,7 @@ +// FIXME: missing sysroot spans (#53081) +// ignore-i586-unknown-linux-gnu +// ignore-i586-unknown-linux-musl +// ignore-i686-unknown-linux-musl #[derive(Debug)] struct R { b: bool, diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index e5c3eaccbd3ec..7c1bef072184b 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,11 +1,20 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-pinned-nocopy.rs:12:16 + --> $DIR/unique-pinned-nocopy.rs:16:16 | +LL | struct R { + | -------- this type doesn't satisfy the bound `std::clone::Clone` +... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `std::boxed::Box : std::clone::Clone` + `R: std::clone::Clone` + `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 24bfa1690efa5e09a33288bf73abf6e058e1833c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 17 Feb 2020 23:59:21 -0800 Subject: [PATCH 07/31] Reduce vebosity of E0599 --- src/librustc_typeck/check/method/probe.rs | 21 ++++++++++--------- src/librustc_typeck/check/method/suggest.rs | 3 +-- .../derives/derive-assoc-type-not-impl.stderr | 6 +----- src/test/ui/issues/issue-21596.stderr | 1 - src/test/ui/issues/issue-31173.stderr | 1 - .../ui/methods/method-call-err-msg.stderr | 1 - .../ui/mismatched_types/issue-36053-2.stderr | 1 - .../suggestions/mut-borrow-needed-by-trait.rs | 4 ---- .../mut-borrow-needed-by-trait.stderr | 14 ++++--------- src/test/ui/union/union-derive-clone.stderr | 6 +----- src/test/ui/unique-object-noncopyable.rs | 4 ---- src/test/ui/unique-object-noncopyable.stderr | 8 +------ src/test/ui/unique-pinned-nocopy.rs | 4 ---- src/test/ui/unique-pinned-nocopy.stderr | 8 +------ 14 files changed, 20 insertions(+), 62 deletions(-) diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 0d6f8e9b7e683..1bf173e3b1310 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -1426,17 +1426,18 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } } - _ => {} + _ => { + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let trait_ref = self.resolve_vars_if_possible(&trait_ref); + possibly_unsatisfied_predicates.push(trait_ref); + } } - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); }); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index bd87626b438d0..c6c404c5c7820 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -394,7 +394,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { tcx.sess.diagnostic().struct_dummy() }; - // FIXME: Unify with unmet bound label. if let Some(def) = actual.ty_adt_def() { if let Some(full_sp) = tcx.hir().span_if_local(def.did) { let def_sp = tcx.sess.source_map().def_span(full_sp); @@ -576,7 +575,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { bound_list.sort(); bound_list.dedup(); // #35677 bound_spans.sort(); - bound_spans.dedup(); // #35677 + bound_spans.dedup(); for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 2746d8b7a14e1..0b55b3f2ec9c1 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,10 +2,7 @@ error[E0599]: no method named `clone` found for struct `Bar` in the cu --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ - | | - | method `clone` not found for this - | this type doesn't satisfy the bound `std::clone::Clone` + | ------------------ method `clone` not found for this ... LL | struct NotClone; | ---------------- this type doesn't satisfy the bound `std::clone::Clone` @@ -14,7 +11,6 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `Bar: std::clone::Clone` `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index d98302552cad4..10b634b460309 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -8,7 +8,6 @@ LL | println!("{}", z.to_string()); = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: `*const u8: std::fmt::Display` - `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 77cb7fb0426e5..28b3b872220b7 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -19,7 +19,6 @@ LL | pub struct Cloned { | -------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 0c48e93347d85..2b683f8aa2a58 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -44,7 +44,6 @@ LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `&mut Foo: std::iter::Iterator` `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 2b8b2d82ec23c..98d71b460db5d 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -10,7 +10,6 @@ LL | pub struct Filter { | ----------------------- this type doesn't satisfy the bound `std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs index 49a37498fd955..f8b86377187c5 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.rs @@ -1,7 +1,3 @@ -// FIXME: missing sysroot spans (#53081) -// ignore-i586-unknown-linux-gnu -// ignore-i586-unknown-linux-musl -// ignore-i686-unknown-linux-musl use std::env::args; use std::fs::File; use std::io::{stdout, Write, BufWriter}; diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 5de7295f4f4fa..3a9fddc474a9f 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:29 + --> $DIR/mut-borrow-needed-by-trait.rs:17:29 | LL | let fp = BufWriter::new(fp); | ^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -8,7 +8,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter::::new` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:14 + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -17,7 +17,7 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0277]: the trait bound `&dyn std::io::Write: std::io::Write` is not satisfied - --> $DIR/mut-borrow-needed-by-trait.rs:21:14 + --> $DIR/mut-borrow-needed-by-trait.rs:17:14 | LL | let fp = BufWriter::new(fp); | ^^^^^^^^^^^^^^^^^^ the trait `std::io::Write` is not implemented for `&dyn std::io::Write` @@ -26,19 +26,13 @@ LL | let fp = BufWriter::new(fp); = note: required by `std::io::BufWriter` error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<&dyn std::io::Write>` in the current scope - --> $DIR/mut-borrow-needed-by-trait.rs:26:5 + --> $DIR/mut-borrow-needed-by-trait.rs:22:5 | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` - | - ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL - | -LL | pub struct BufWriter { - | ------------------------------ this type doesn't satisfy the bound `std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: `&dyn std::io::Write: std::io::Write` - `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 289b680a46ea1..c8537afd3bdea 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,10 +11,7 @@ error[E0599]: no method named `clone` found for union `U5` in the c --> $DIR/union-derive-clone.rs:37:15 | LL | union U5 { - | ----------- - | | - | method `clone` not found for this - | this type doesn't satisfy the bound `std::clone::Clone` + | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; | ------------------- this type doesn't satisfy the bound `std::marker::Copy` @@ -24,7 +21,6 @@ LL | let w = u.clone(); | = note: the method `clone` exists but the following trait bounds were not satisfied: `CloneNoCopy: std::marker::Copy` - `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.rs b/src/test/ui/unique-object-noncopyable.rs index bedaf27c2dddf..dd38a7190aa0e 100644 --- a/src/test/ui/unique-object-noncopyable.rs +++ b/src/test/ui/unique-object-noncopyable.rs @@ -1,7 +1,3 @@ -// FIXME: missing sysroot spans (#53081) -// ignore-i586-unknown-linux-gnu -// ignore-i586-unknown-linux-musl -// ignore-i686-unknown-linux-musl #![feature(box_syntax)] trait Foo { diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 192558f6b0923..1ada663129fa0 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-object-noncopyable.rs:28:16 + --> $DIR/unique-object-noncopyable.rs:24:16 | LL | trait Foo { | --------- @@ -9,16 +9,10 @@ LL | trait Foo { ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` - | - ::: $SRC_DIR/liballoc/boxed.rs:LL:COL - | -LL | pub struct Box(Unique); - | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: `dyn Foo: std::clone::Clone` `dyn Foo: std::marker::Sized` - `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.rs b/src/test/ui/unique-pinned-nocopy.rs index 091b8a4386235..4c30450c70455 100644 --- a/src/test/ui/unique-pinned-nocopy.rs +++ b/src/test/ui/unique-pinned-nocopy.rs @@ -1,7 +1,3 @@ -// FIXME: missing sysroot spans (#53081) -// ignore-i586-unknown-linux-gnu -// ignore-i586-unknown-linux-musl -// ignore-i686-unknown-linux-musl #[derive(Debug)] struct R { b: bool, diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 7c1bef072184b..2557ea8acb8ef 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -1,20 +1,14 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in the current scope - --> $DIR/unique-pinned-nocopy.rs:16:16 + --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { | -------- this type doesn't satisfy the bound `std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` - | - ::: $SRC_DIR/liballoc/boxed.rs:LL:COL - | -LL | pub struct Box(Unique); - | ------------------------------------- this type doesn't satisfy the bound `std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: `R: std::clone::Clone` - `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 70255ef7d7ca78e037941f99f5a34ce5cc474df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 01:35:18 -0800 Subject: [PATCH 08/31] On single local candidate, use span label --- src/librustc_typeck/check/method/suggest.rs | 33 +++++++++++++------ .../associated-const-no-item.stderr | 5 +-- src/test/ui/auto-ref-slice-plus-ref.stderr | 20 ++++++----- ...e-21659-show-relevant-trait-impls-3.stderr | 5 +-- .../no-method-suggested-traits.stderr | 30 ++++++++++------- src/test/ui/issues/issue-5153.stderr | 5 +-- src/test/ui/issues/issue-57362-1.stderr | 5 +-- src/test/ui/issues/issue-57362-2.stderr | 5 +-- src/test/ui/never_type/issue-2149.stderr | 5 +-- src/test/ui/object-pointer-types.stderr | 10 +++--- ...at-arbitrary-self-type-trait-method.stderr | 6 ++-- ...pecialization-trait-not-implemented.stderr | 5 +-- src/test/ui/traits/trait-item-privacy.stderr | 15 +++++---- .../trivial-bounds/trivial-bounds-leak.stderr | 5 +-- 14 files changed, 95 insertions(+), 59 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index c6c404c5c7820..3fa5d4baa76b4 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -846,7 +846,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let message = |action| { format!( "the following {traits_define} an item `{name}`, perhaps you need to {action} \ - {one_of_them}:", + {one_of_them}:", traits_define = if candidates.len() == 1 { "trait defines" } else { "traits define" }, action = action, @@ -944,19 +944,32 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !suggested { - let mut msg = message(if let Some(param) = param_type { + let action = if let Some(param) = param_type { format!("restrict type parameter `{}` with", param) } else { "implement".to_string() - }); - for (i, trait_info) in candidates.iter().enumerate() { - msg.push_str(&format!( - "\ncandidate #{}: `{}`", - i + 1, - self.tcx.def_path_str(trait_info.def_id), - )); + }; + let mut use_note = true; + if let [trait_info] = &candidates[..] { + if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { + err.span_label( + self.tcx.sess.source_map().def_span(span), + &format!("this trait defines an item `{}`", item_name), + ); + use_note = false + } + } + if use_note { + let mut msg = message(action); + for (i, trait_info) in candidates.iter().enumerate() { + msg.push_str(&format!( + "\ncandidate #{}: `{}`", + i + 1, + self.tcx.def_path_str(trait_info.def_id), + )); + } + err.note(&msg[..]); } - err.note(&msg[..]); } } } diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index d96cf67b87578..e6765bc3dd65e 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -1,12 +1,13 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current scope --> $DIR/associated-const-no-item.rs:5:23 | +LL | trait Foo { + | --------- this trait defines an item `ID` +... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `ID`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index a0739a7a90b0a..3e14dc801221c 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -3,40 +3,44 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege | LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` +... +LL | trait MyIter { + | ------------ this trait defines an item `test_mut` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test_mut`, perhaps you need to implement it: - candidate #1: `MyIter` error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:8:7 | LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` +... +LL | trait MyIter { + | ------------ this trait defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `MyIter` error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:10:11 | LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` +... +LL | trait MyIter { + | ------------ this trait defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `MyIter` error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:11:12 | LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` +... +LL | trait MyIter { + | ------------ this trait defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `MyIter` error: aborting due to 4 previous errors diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 57417975474f7..32a677a7d7fc1 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | +LL | trait Foo { + | ------------ this trait defines an item `foo` +... LL | struct Bar; | ----------- method `foo` not found for this ... @@ -8,8 +11,6 @@ LL | f1.foo(1usize); | ^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index da25617e18759..8025c12047fef 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -122,62 +122,68 @@ LL | std::rc::Rc::new(&mut Box::new(&Foo)).method(); error[E0599]: no method named `method2` found for type `u64` in the current scope --> $DIR/no-method-suggested-traits.rs:45:10 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope --> $DIR/no-method-suggested-traits.rs:47:44 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:50:37 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:52:71 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:54:40 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:56:74 | +LL | pub trait Bar { + | ------------- this trait defines an item `method2` +... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `method2`, perhaps you need to implement it: - candidate #1: `foo::Bar` error[E0599]: no method named `method3` found for struct `Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:59:9 diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 4680c8b131c50..730da21ddf5fe 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -1,12 +1,13 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope --> $DIR/issue-5153.rs:10:27 | +LL | trait Foo { + | --------- this trait defines an item `foo` +... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index ad596db13ccfd..3a5189b132da2 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,13 +1,14 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope --> $DIR/issue-57362-1.rs:20:7 | +LL | trait Trait { + | ----------- this trait defines an item `f` +... LL | a.f(); | ^ method not found in `fn(&u8)` | = note: `a` is a function, perhaps you wish to call it = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `f`, perhaps you need to implement it: - candidate #1: `Trait` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index 3528084f6ceb4..e2d80b3b4df73 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,12 +1,13 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope --> $DIR/issue-57362-2.rs:22:25 | +LL | trait X { + | ------- this trait defines an item `make_g` +... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `make_g`, perhaps you need to implement it: - candidate #1: `X` error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index 9645244751dab..4fadf49bd6d28 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -9,12 +9,13 @@ LL | for elt in self { r = r + f(*elt); } error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope --> $DIR/issue-2149.rs:13:12 | +LL | trait VecMonad { + | ----------------- this trait defines an item `bind` +... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `bind`, perhaps you need to implement it: - candidate #1: `VecMonad` error: aborting due to 2 previous errors diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 855894b4495c6..5ca326bca31c5 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -1,22 +1,24 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:11:7 | +LL | trait Foo { + | --------- this trait defines an item `owned` +... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `owned`, perhaps you need to implement it: - candidate #1: `Foo` error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:17:7 | +LL | trait Foo { + | --------- this trait defines an item `owned` +... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `owned`, perhaps you need to implement it: - candidate #1: `Foo` error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope --> $DIR/object-pointer-types.rs:23:7 diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 28a7b68a6821f..8ed2b8b5c9521 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -2,7 +2,9 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 | LL | trait B { fn foo(self: Box); } - | --- the method is available for `std::boxed::Box` here + | ------- --- the method is available for `std::boxed::Box` here + | | + | this trait defines an item `foo` LL | struct A; | --------- method `foo` not found for this ... @@ -10,8 +12,6 @@ LL | A.foo() | ^^^ method not found in `A` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo`, perhaps you need to implement it: - candidate #1: `B` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 2d0caf1dd8755..ccbb2aae05d1b 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -1,6 +1,9 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope --> $DIR/specialization-trait-not-implemented.rs:22:29 | +LL | trait Foo { + | --------- this trait defines an item `foo_one` +... LL | struct MyStruct; | ---------------- | | @@ -13,8 +16,6 @@ LL | println!("{}", MyStruct.foo_one()); = note: the method `foo_one` exists but the following trait bounds were not satisfied: `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `foo_one`, perhaps you need to implement it: - candidate #1: `Foo` error: aborting due to previous error diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 072328ab50c70..5b7f0a8ce5ff1 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -4,12 +4,13 @@ error[E0599]: no method named `a` found for struct `S` in the current scope LL | struct S; | --------- method `a` not found for this ... +LL | trait A { + | ------- this trait defines an item `a` +... LL | S.a(); | ^ method not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `a`, perhaps you need to implement it: - candidate #1: `method::A` error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:68:7 @@ -45,12 +46,13 @@ error[E0599]: no function or associated item named `a` found for struct `S` in t LL | struct S; | --------- function or associated item `a` not found for this ... +LL | trait A { + | ------- this trait defines an item `a` +... LL | S::a(&S); | ^ function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `a`, perhaps you need to implement it: - candidate #1: `method::A` error[E0599]: no function or associated item named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:80:8 @@ -79,12 +81,13 @@ error[E0599]: no associated item named `A` found for struct `S` in the current s LL | struct S; | --------- associated item `A` not found for this ... +LL | trait A { + | ------- this trait defines an item `A` +... LL | S::A; | ^ associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `A`, perhaps you need to implement it: - candidate #1: `assoc_const::A` error[E0599]: no associated item named `B` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:98:8 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index acf309ac60872..7ed24591e66ab 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -11,12 +11,13 @@ LL | fn cant_return_str() -> str { error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | +LL | pub trait Foo { + | ------------- this trait defines an item `test` +... LL | 3i32.test(); | ^^^^ method not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `test`, perhaps you need to implement it: - candidate #1: `Foo` error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:15 From 2e8399de22a10463bde964595bbad1b2d75cb40f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 02:13:30 -0800 Subject: [PATCH 09/31] Deduplicate information in E0599 --- src/librustc_typeck/check/method/suggest.rs | 54 ++++++++++++------- .../derives/derive-assoc-type-not-impl.stderr | 4 +- src/test/ui/issues/issue-31173.stderr | 5 +- .../ui/methods/method-call-err-msg.stderr | 4 +- .../ui/mismatched_types/issue-36053-2.stderr | 3 +- .../method-help-unsatisfied-bound.stderr | 5 +- ...pecialization-trait-not-implemented.stderr | 4 +- src/test/ui/union/union-derive-clone.stderr | 4 +- src/test/ui/unique-object-noncopyable.stderr | 7 +-- src/test/ui/unique-pinned-nocopy.stderr | 4 +- 10 files changed, 46 insertions(+), 48 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 3fa5d4baa76b4..8eb42f019843d 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -538,16 +538,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .map(|p| { + .filter_map(|p| { let self_ty = p.self_ty(); match &self_ty.kind { - ty::Adt(def, _) => bound_spans.push(( - self.tcx.sess.source_map().def_span(self.tcx.def_span(def.did)), - format!( - "this type doesn't satisfy the bound `{}`", - p.print_only_trait_path() - ), - )), + ty::Adt(def, _) => { + bound_spans.push(( + self.tcx + .sess + .source_map() + .def_span(self.tcx.def_span(def.did)), + format!( + "the method `{}` exists but this type doesn't satisfy \ + the bound `{}: {}`", + item_name, + p.self_ty(), + p.print_only_trait_path() + ), + )); + None + } ty::Dynamic(preds, _) => { for pred in *preds.skip_binder() { match pred { @@ -558,7 +567,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .source_map() .def_span(self.tcx.def_span(tr.def_id)), format!( - "this trait doesn't satisfy the bound `{}`", + "the method `{}` exists but this trait \ + doesn't satisfy the bound `{}: {}`", + item_name, + p.self_ty(), p.print_only_trait_path() ), )), @@ -566,10 +578,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { | ty::ExistentialPredicate::AutoTrait(_) => {} } } + None } - _ => {} - }; - format!("`{}: {}`", p.self_ty(), p.print_only_trait_path()) + _ => Some(format!( + "`{}: {}`", + p.self_ty(), + p.print_only_trait_path() + )), + } }) .collect::>(); bound_list.sort(); @@ -579,12 +595,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } - let bound_list = bound_list.join("\n"); - err.note(&format!( - "the method `{}` exists but the following trait bounds were not \ - satisfied:\n{}", - item_name, bound_list - )); + if !bound_list.is_empty() { + let bound_list = bound_list.join("\n"); + err.note(&format!( + "the method `{}` exists but the following trait bounds were not \ + satisfied:\n{}", + item_name, bound_list + )); + } } if actual.is_numeric() && actual.is_fresh() { diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 0b55b3f2ec9c1..fd74d99229914 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -5,13 +5,11 @@ LL | struct Bar { | ------------------ method `clone` not found for this ... LL | struct NotClone; - | ---------------- this type doesn't satisfy the bound `std::clone::Clone` + | ---------------- the method `clone` exists but this type doesn't satisfy the bound `NotClone: std::clone::Clone` ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 28b3b872220b7..4a5940f610e66 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,10 +16,7 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned { - | -------------------- this type doesn't satisfy the bound `std::iter::Iterator` - | - = note: the method `collect` exists but the following trait bounds were not satisfied: - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- the method `collect` exists but this type doesn't satisfy the bound `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index 2b683f8aa2a58..aa38e4da01885 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -38,13 +38,11 @@ LL | pub struct Foo; | --------------- | | | method `take` not found for this - | this type doesn't satisfy the bound `std::iter::Iterator` + | the method `take` exists but this type doesn't satisfy the bound `Foo: std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | - = note: the method `take` exists but the following trait bounds were not satisfied: - `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 98d71b460db5d..dc0bd310de81c 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -7,11 +7,10 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter { - | ----------------------- this type doesn't satisfy the bound `std::iter::Iterator` + | ----------------------- the method `count` exists but this type doesn't satisfy the bound `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index a7681f9af5b22..e95141b393ae0 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,13 +2,10 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), F --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | struct Foo; - | ----------- this type doesn't satisfy the bound `std::fmt::Debug` + | ----------- the method `unwrap` exists but this type doesn't satisfy the bound `Foo: std::fmt::Debug` ... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` - | - = note: the method `unwrap` exists but the following trait bounds were not satisfied: - `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index ccbb2aae05d1b..2738bac8cc857 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -8,13 +8,11 @@ LL | struct MyStruct; | ---------------- | | | method `foo_one` not found for this - | this type doesn't satisfy the bound `Foo` + | the method `foo_one` exists but this type doesn't satisfy the bound `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | - = note: the method `foo_one` exists but the following trait bounds were not satisfied: - `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index c8537afd3bdea..c0d99c56cc038 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -14,13 +14,11 @@ LL | union U5 { | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; - | ------------------- this type doesn't satisfy the bound `std::marker::Copy` + | ------------------- the method `clone` exists but this type doesn't satisfy the bound `CloneNoCopy: std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `CloneNoCopy: std::marker::Copy` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 1ada663129fa0..b786a3d6d86fc 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -4,15 +4,12 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box LL | trait Foo { | --------- | | - | this trait doesn't satisfy the bound `std::clone::Clone` - | this trait doesn't satisfy the bound `std::marker::Sized` + | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::clone::Clone` + | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::marker::Sized` ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` - `dyn Foo: std::marker::Sized` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 2557ea8acb8ef..26b82ecda48e9 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -2,13 +2,11 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in t --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { - | -------- this type doesn't satisfy the bound `std::clone::Clone` + | -------- the method `clone` exists but this type doesn't satisfy the bound `R: std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` | - = note: the method `clone` exists but the following trait bounds were not satisfied: - `R: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 1b4c5b5fc648493525f760a9f246eb989a9a6e40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 16:35:47 -0800 Subject: [PATCH 10/31] Track all predicates in errors, not just trait obligations Surface associated type projection bounds that could not be fulfilled in E0599 errors. Always present the list of unfulfilled trait bounds, regardless of whether we're pointing at the ADT or trait that didn't satisfy it. --- src/librustc/traits/mod.rs | 14 +++ src/librustc_typeck/check/method/mod.rs | 6 +- src/librustc_typeck/check/method/probe.rs | 80 ++++++++--------- src/librustc_typeck/check/method/suggest.rs | 87 +++++++++---------- .../derives/derive-assoc-type-not-impl.stderr | 4 +- src/test/ui/issues/issue-31173.stderr | 6 +- .../option-as_deref.stderr | 1 + .../option-as_deref_mut.stderr | 1 + .../result-as_deref.stderr | 1 + .../result-as_deref_err.stderr | 1 + .../result-as_deref_mut.stderr | 1 + .../result-as_deref_mut_err.stderr | 1 + .../ui/methods/method-call-err-msg.stderr | 4 +- .../ui/mismatched_types/issue-36053-2.stderr | 6 +- .../method-help-unsatisfied-bound.stderr | 5 +- ...pecialization-trait-not-implemented.stderr | 4 +- src/test/ui/union/union-derive-clone.stderr | 4 +- src/test/ui/unique-object-noncopyable.stderr | 7 +- src/test/ui/unique-pinned-nocopy.stderr | 4 +- 19 files changed, 134 insertions(+), 103 deletions(-) diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index c000aa7c25e97..ab50ddd37697f 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -579,6 +579,20 @@ impl<'tcx, N> Vtable<'tcx, N> { } } + pub fn borrow_nested_obligations(&self) -> &[N] { + match &self { + VtableImpl(i) => &i.nested[..], + VtableParam(n) => &n[..], + VtableBuiltin(i) => &i.nested[..], + VtableAutoImpl(d) => &d.nested[..], + VtableClosure(c) => &c.nested[..], + VtableGenerator(c) => &c.nested[..], + VtableObject(d) => &d.nested[..], + VtableFnPointer(d) => &d.nested[..], + VtableTraitAlias(d) => &d.nested[..], + } + } + pub fn map(self, f: F) -> Vtable<'tcx, M> where F: FnMut(N) -> M, diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index de824648a25d9..fd85397760af7 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -14,7 +14,7 @@ use crate::check::FnCtxt; use rustc::ty::subst::Subst; use rustc::ty::subst::{InternalSubsts, SubstsRef}; use rustc::ty::GenericParamDefKind; -use rustc::ty::{self, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TypeFoldable, WithConstness}; +use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TypeFoldable, WithConstness}; use rustc_data_structures::sync::Lrc; use rustc_errors::{Applicability, DiagnosticBuilder}; use rustc_hir as hir; @@ -67,7 +67,7 @@ pub enum MethodError<'tcx> { // could lead to matches if satisfied, and a list of not-in-scope traits which may work. pub struct NoMatchData<'tcx> { pub static_candidates: Vec, - pub unsatisfied_predicates: Vec>, + pub unsatisfied_predicates: Vec>, pub out_of_scope_traits: Vec, pub lev_candidate: Option, pub mode: probe::Mode, @@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> { impl<'tcx> NoMatchData<'tcx> { pub fn new( static_candidates: Vec, - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec>, out_of_scope_traits: Vec, lev_candidate: Option, mode: probe::Mode, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 1bf173e3b1310..4f729c593cba4 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -14,8 +14,7 @@ use rustc::session::config::nightly_options; use rustc::ty::subst::{InternalSubsts, Subst, SubstsRef}; use rustc::ty::GenericParamDefKind; use rustc::ty::{ - self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, TraitRef, Ty, TyCtxt, TypeFoldable, - WithConstness, + self, ParamEnvAnd, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness, }; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sync::Lrc; @@ -78,7 +77,7 @@ struct ProbeContext<'a, 'tcx> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec>, is_suggestion: IsSuggestion, } @@ -1224,7 +1223,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probes: ProbesIter, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec>, unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, ) -> Option> where @@ -1343,7 +1342,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec>, ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); @@ -1398,47 +1397,40 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let predicate = trait_ref.without_const().to_predicate(); let obligation = traits::Obligation::new(cause, self.param_env, predicate); if !self.predicate_may_hold(&obligation) { - if self.probe(|_| self.select_trait_candidate(trait_ref).is_err()) { + if self.probe(|_| { + match self.select_trait_candidate(trait_ref) { + Err(_) => return true, + Ok(Some(vtable)) + if !vtable.borrow_nested_obligations().is_empty() => + { + for obligation in vtable.borrow_nested_obligations() { + // Determine exactly which obligation wasn't met, so + // that we can give more context in the error. + if !self.predicate_may_hold(&obligation) { + result = ProbeResult::NoMatch; + let o = self.resolve_vars_if_possible(obligation); + possibly_unsatisfied_predicates.push(o.predicate); + } + } + } + _ => { + // Some nested subobligation of this predicate + // failed. + // + // FIXME: try to find the exact nested subobligation + // and point at it rather than reporting the entire + // trait-ref? + result = ProbeResult::NoMatch; + let predicate = self.resolve_vars_if_possible(&predicate); + possibly_unsatisfied_predicates.push(predicate); + } + } + false + }) { // This candidate's primary obligation doesn't even // select - don't bother registering anything in // `potentially_unsatisfied_predicates`. return ProbeResult::NoMatch; - } else { - self.probe(|_| { - match self.select_trait_candidate(trait_ref) { - Ok(Some(traits::VtableImpl(traits::VtableImplData { - nested, - .. - }))) if !nested.is_empty() => { - for obligation in nested { - // Determine exactly which obligation wasn't met, so - // that we can give more context in the error. - if !self.predicate_may_hold(&obligation) { - result = ProbeResult::NoMatch; - if let Some(poly_trait_ref) = - obligation.predicate.to_opt_poly_trait_ref() - { - let trait_ref = poly_trait_ref.clone(); - let trait_ref = trait_ref.skip_binder(); - possibly_unsatisfied_predicates - .push(*trait_ref); - } - } - } - } - _ => { - // Some nested subobligation of this predicate - // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? - result = ProbeResult::NoMatch; - let trait_ref = self.resolve_vars_if_possible(&trait_ref); - possibly_unsatisfied_predicates.push(trait_ref); - } - } - }); } } vec![] @@ -1455,9 +1447,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - if let &ty::Predicate::Trait(ref pred, _) = &o.predicate { - possibly_unsatisfied_predicates.push(pred.skip_binder().trait_ref); - } + possibly_unsatisfied_predicates.push(o.predicate); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 8eb42f019843d..6edceeb15b3de 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -535,57 +535,56 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } if !unsatisfied_predicates.is_empty() { + let def_span = + |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; let mut bound_list = unsatisfied_predicates .iter() - .filter_map(|p| { - let self_ty = p.self_ty(); - match &self_ty.kind { - ty::Adt(def, _) => { - bound_spans.push(( - self.tcx - .sess - .source_map() - .def_span(self.tcx.def_span(def.did)), - format!( - "the method `{}` exists but this type doesn't satisfy \ - the bound `{}: {}`", - item_name, - p.self_ty(), - p.print_only_trait_path() - ), - )); - None - } - ty::Dynamic(preds, _) => { - for pred in *preds.skip_binder() { - match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans - .push(( - self.tcx - .sess - .source_map() - .def_span(self.tcx.def_span(tr.def_id)), - format!( - "the method `{}` exists but this trait \ - doesn't satisfy the bound `{}: {}`", - item_name, - p.self_ty(), - p.print_only_trait_path() - ), - )), - ty::ExistentialPredicate::Projection(_) - | ty::ExistentialPredicate::AutoTrait(_) => {} + .filter_map(|pred| match pred { + ty::Predicate::Projection(pred) => { + // `::Item = String`. + let trait_ref = + pred.skip_binder().projection_ty.trait_ref(self.tcx); + let assoc = self + .tcx + .associated_item(pred.skip_binder().projection_ty.item_def_id); + let ty = pred.skip_binder().ty; + Some(format!("`{}::{} = {}`", trait_ref, assoc.ident, ty)) + } + ty::Predicate::Trait(poly_trait_ref, _) => { + let p = poly_trait_ref.skip_binder().trait_ref; + let self_ty = p.self_ty(); + let path = p.print_only_trait_path(); + match &self_ty.kind { + ty::Adt(def, _) => { + // Point at the type that couldn't satisfy the bound. + bound_spans.push(( + def_span(def.did), + format!("doesn't satisfy `{}: {}`", self_ty, path), + )); + } + ty::Dynamic(preds, _) => { + // Point at the trait object that couldn't satisfy the bound. + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans + .push(( + def_span(tr.def_id), + format!( + "doesn't satisfy `{}: {}`", + self_ty, path + ), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } } } - None + _ => {} } - _ => Some(format!( - "`{}: {}`", - p.self_ty(), - p.print_only_trait_path() - )), + Some(format!("`{}: {}`", self_ty, path)) } + _ => None, }) .collect::>(); bound_list.sort(); diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index fd74d99229914..3ed726dea35b6 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -5,11 +5,13 @@ LL | struct Bar { | ------------------ method `clone` not found for this ... LL | struct NotClone; - | ---------------- the method `clone` exists but this type doesn't satisfy the bound `NotClone: std::clone::Clone` + | ---------------- doesn't satisfy `NotClone: std::clone::Clone` ... LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `NotClone: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 4a5940f610e66..d5e3cf48f38eb 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,7 +16,11 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned { - | -------------------- the method `collect` exists but this type doesn't satisfy the bound `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- doesn't satisfy `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | + = note: the method `collect` exists but the following trait bounds were not satisfied: + `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index c6d9a8415dd6c..63359be56bf41 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,6 +5,7 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index ae51052a22c3a..b01b3448e17fd 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 3f7904a852165..754828419872b 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,6 +5,7 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index eb591b419ea82..cf31bc4b56bf8 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,6 +5,7 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 115518dcf6760..586b35554553e 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index 49f4a16d8ae97..fd0e43d7dbc15 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,6 +5,7 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: + `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` error: aborting due to previous error diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index aa38e4da01885..b0d747d201d3f 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -38,11 +38,13 @@ LL | pub struct Foo; | --------------- | | | method `take` not found for this - | the method `take` exists but this type doesn't satisfy the bound `Foo: std::iter::Iterator` + | doesn't satisfy `Foo: std::iter::Iterator` ... LL | .take() | ^^^^ method not found in `Foo` | + = note: the method `take` exists but the following trait bounds were not satisfied: + `Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index dc0bd310de81c..5f3353c89ccbe 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -7,10 +7,12 @@ LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter { - | ----------------------- the method `count` exists but this type doesn't satisfy the bound `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + | ----------------------- doesn't satisfy `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&_,)>` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr index e95141b393ae0..5ab191b927049 100644 --- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr +++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr @@ -2,10 +2,13 @@ error[E0599]: no method named `unwrap` found for enum `std::result::Result<(), F --> $DIR/method-help-unsatisfied-bound.rs:5:7 | LL | struct Foo; - | ----------- the method `unwrap` exists but this type doesn't satisfy the bound `Foo: std::fmt::Debug` + | ----------- doesn't satisfy `Foo: std::fmt::Debug` ... LL | a.unwrap(); | ^^^^^^ method not found in `std::result::Result<(), Foo>` + | + = note: the method `unwrap` exists but the following trait bounds were not satisfied: + `Foo: std::fmt::Debug` error: aborting due to previous error diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 2738bac8cc857..14f37150c8070 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -8,11 +8,13 @@ LL | struct MyStruct; | ---------------- | | | method `foo_one` not found for this - | the method `foo_one` exists but this type doesn't satisfy the bound `MyStruct: Foo` + | doesn't satisfy `MyStruct: Foo` ... LL | println!("{}", MyStruct.foo_one()); | ^^^^^^^ method not found in `MyStruct` | + = note: the method `foo_one` exists but the following trait bounds were not satisfied: + `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index c0d99c56cc038..2051ea3339193 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -14,11 +14,13 @@ LL | union U5 { | ----------- method `clone` not found for this ... LL | struct CloneNoCopy; - | ------------------- the method `clone` exists but this type doesn't satisfy the bound `CloneNoCopy: std::marker::Copy` + | ------------------- doesn't satisfy `CloneNoCopy: std::marker::Copy` ... LL | let w = u.clone(); | ^^^^^ method not found in `U5` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `CloneNoCopy: std::marker::Copy` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index b786a3d6d86fc..f230d0d14d25a 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -4,12 +4,15 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box LL | trait Foo { | --------- | | - | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::clone::Clone` - | the method `clone` exists but this trait doesn't satisfy the bound `dyn Foo: std::marker::Sized` + | doesn't satisfy `dyn Foo: std::clone::Clone` + | doesn't satisfy `dyn Foo: std::marker::Sized` ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `dyn Foo: std::clone::Clone` + `dyn Foo: std::marker::Sized` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 26b82ecda48e9..12d719a102796 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -2,11 +2,13 @@ error[E0599]: no method named `clone` found for struct `std::boxed::Box` in t --> $DIR/unique-pinned-nocopy.rs:12:16 | LL | struct R { - | -------- the method `clone` exists but this type doesn't satisfy the bound `R: std::clone::Clone` + | -------- doesn't satisfy `R: std::clone::Clone` ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` | + = note: the method `clone` exists but the following trait bounds were not satisfied: + `R: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 9a7345bc471112a5b877c6e476e9b13248786c16 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 17:53:25 -0800 Subject: [PATCH 11/31] Show information of chain of bound obligations When the obligation that couldn't be fulfilled is specific to a nested obligation, maintain both the nested and parent obligations around for more accurate and detailed error reporting. --- src/librustc_typeck/check/method/mod.rs | 4 +- src/librustc_typeck/check/method/probe.rs | 31 ++++--- src/librustc_typeck/check/method/suggest.rs | 82 +++++++++++-------- .../derives/derive-assoc-type-not-impl.stderr | 7 +- src/test/ui/issues/issue-21596.stderr | 2 +- src/test/ui/issues/issue-31173.stderr | 7 +- .../ui/methods/method-call-err-msg.stderr | 2 +- .../ui/mismatched_types/issue-36053-2.stderr | 6 +- .../mut-borrow-needed-by-trait.stderr | 7 +- src/test/ui/union/union-derive-clone.stderr | 7 +- src/test/ui/unique-object-noncopyable.stderr | 9 +- src/test/ui/unique-pinned-nocopy.stderr | 7 +- 12 files changed, 111 insertions(+), 60 deletions(-) diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index fd85397760af7..b09522bbd33da 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -67,7 +67,7 @@ pub enum MethodError<'tcx> { // could lead to matches if satisfied, and a list of not-in-scope traits which may work. pub struct NoMatchData<'tcx> { pub static_candidates: Vec, - pub unsatisfied_predicates: Vec>, + pub unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, pub out_of_scope_traits: Vec, pub lev_candidate: Option, pub mode: probe::Mode, @@ -76,7 +76,7 @@ pub struct NoMatchData<'tcx> { impl<'tcx> NoMatchData<'tcx> { pub fn new( static_candidates: Vec, - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, out_of_scope_traits: Vec, lev_candidate: Option, mode: probe::Mode, diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs index 4f729c593cba4..3e2826907b880 100644 --- a/src/librustc_typeck/check/method/probe.rs +++ b/src/librustc_typeck/check/method/probe.rs @@ -77,7 +77,7 @@ struct ProbeContext<'a, 'tcx> { /// Collects near misses when trait bounds for type parameters are unsatisfied and is only used /// for error reporting - unsatisfied_predicates: Vec>, + unsatisfied_predicates: Vec<(ty::Predicate<'tcx>, Option>)>, is_suggestion: IsSuggestion, } @@ -1223,7 +1223,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probes: ProbesIter, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec<( + ty::Predicate<'tcx>, + Option>, + )>, unstable_candidates: Option<&mut Vec<(&'b Candidate<'tcx>, Symbol)>>, ) -> Option> where @@ -1342,7 +1345,10 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { &self, self_ty: Ty<'tcx>, probe: &Candidate<'tcx>, - possibly_unsatisfied_predicates: &mut Vec>, + possibly_unsatisfied_predicates: &mut Vec<( + ty::Predicate<'tcx>, + Option>, + )>, ) -> ProbeResult { debug!("consider_probe: self_ty={:?} probe={:?}", self_ty, probe); @@ -1409,20 +1415,25 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { if !self.predicate_may_hold(&obligation) { result = ProbeResult::NoMatch; let o = self.resolve_vars_if_possible(obligation); - possibly_unsatisfied_predicates.push(o.predicate); + let predicate = + self.resolve_vars_if_possible(&predicate); + let p = if predicate == o.predicate { + // Avoid "`MyStruct: Foo` which is required by + // `MyStruct: Foo`" in E0599. + None + } else { + Some(predicate) + }; + possibly_unsatisfied_predicates.push((o.predicate, p)); } } } _ => { // Some nested subobligation of this predicate // failed. - // - // FIXME: try to find the exact nested subobligation - // and point at it rather than reporting the entire - // trait-ref? result = ProbeResult::NoMatch; let predicate = self.resolve_vars_if_possible(&predicate); - possibly_unsatisfied_predicates.push(predicate); + possibly_unsatisfied_predicates.push((predicate, None)); } } false @@ -1447,7 +1458,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let o = self.resolve_vars_if_possible(&o); if !self.predicate_may_hold(&o) { result = ProbeResult::NoMatch; - possibly_unsatisfied_predicates.push(o.predicate); + possibly_unsatisfied_predicates.push((o.predicate, None)); } } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 6edceeb15b3de..973f8208f16f6 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -538,9 +538,33 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; - let mut bound_list = unsatisfied_predicates - .iter() - .filter_map(|pred| match pred { + let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str| { + match &self_ty.kind { + ty::Adt(def, _) => { + // Point at the type that couldn't satisfy the bound. + bound_spans.push(( + def_span(def.did), + format!("doesn't satisfy {}", obligation), + )); + } + ty::Dynamic(preds, _) => { + // Point at the trait object that couldn't satisfy the bound. + for pred in *preds.skip_binder() { + match pred { + ty::ExistentialPredicate::Trait(tr) => bound_spans.push(( + def_span(tr.def_id), + format!("doesn't satisfy {}", obligation), + )), + ty::ExistentialPredicate::Projection(_) + | ty::ExistentialPredicate::AutoTrait(_) => {} + } + } + } + _ => {} + } + }; + let mut format_pred = |pred| { + match pred { ty::Predicate::Projection(pred) => { // `::Item = String`. let trait_ref = @@ -549,44 +573,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - Some(format!("`{}::{} = {}`", trait_ref, assoc.ident, ty)) + let obligation = + format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + bound_span_label(trait_ref.self_ty(), &obligation); + Some(obligation) } ty::Predicate::Trait(poly_trait_ref, _) => { let p = poly_trait_ref.skip_binder().trait_ref; let self_ty = p.self_ty(); let path = p.print_only_trait_path(); - match &self_ty.kind { - ty::Adt(def, _) => { - // Point at the type that couldn't satisfy the bound. - bound_spans.push(( - def_span(def.did), - format!("doesn't satisfy `{}: {}`", self_ty, path), - )); - } - ty::Dynamic(preds, _) => { - // Point at the trait object that couldn't satisfy the bound. - for pred in *preds.skip_binder() { - match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans - .push(( - def_span(tr.def_id), - format!( - "doesn't satisfy `{}: {}`", - self_ty, path - ), - )), - ty::ExistentialPredicate::Projection(_) - | ty::ExistentialPredicate::AutoTrait(_) => {} - } - } - } - _ => {} - } - Some(format!("`{}: {}`", self_ty, path)) + let obligation = format!("`{}: {}`", self_ty, path); + bound_span_label(self_ty, &obligation); + Some(obligation) } _ => None, + } + }; + let mut bound_list = unsatisfied_predicates + .iter() + .filter_map(|(pred, parent_pred)| { + format_pred(*pred).map(|pred| match parent_pred { + None => pred, + Some(parent_pred) => match format_pred(*parent_pred) { + None => pred, + Some(parent_pred) => { + format!("{} which is required by {}", pred, parent_pred) + } + }, + }) }) - .collect::>(); + .collect::>(); bound_list.sort(); bound_list.dedup(); // #35677 bound_spans.sort(); diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index 3ed726dea35b6..e837c7721afe3 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -2,7 +2,10 @@ error[E0599]: no method named `clone` found for struct `Bar` in the cu --> $DIR/derive-assoc-type-not-impl.rs:18:30 | LL | struct Bar { - | ------------------ method `clone` not found for this + | ------------------ + | | + | method `clone` not found for this + | doesn't satisfy `Bar: std::clone::Clone` ... LL | struct NotClone; | ---------------- doesn't satisfy `NotClone: std::clone::Clone` @@ -11,7 +14,7 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `NotClone: std::clone::Clone` + `NotClone: std::clone::Clone` which is required by `Bar: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index 10b634b460309..bbd166180499a 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -7,7 +7,7 @@ LL | println!("{}", z.to_string()); = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: - `*const u8: std::fmt::Display` + `*const u8: std::fmt::Display` which is required by `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index d5e3cf48f38eb..9100f2c3a938d 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -17,10 +17,13 @@ LL | .collect(); | LL | pub struct Cloned { | -------------------- doesn't satisfy `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` +... +LL | pub struct TakeWhile { + | -------------------------- doesn't satisfy `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` which is required by `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index b0d747d201d3f..b4e54ab77838f 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -44,7 +44,7 @@ LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `Foo: std::iter::Iterator` + `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 5f3353c89ccbe..5899dfffa41de 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -10,9 +10,9 @@ LL | pub struct Filter { | ----------------------- doesn't satisfy `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` which is required by `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 3a9fddc474a9f..5d297728eca6d 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -30,9 +30,14 @@ error[E0599]: no method named `write_fmt` found for struct `std::io::BufWriter<& | LL | writeln!(fp, "hello world").unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ method not found in `std::io::BufWriter<&dyn std::io::Write>` + | + ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL + | +LL | pub struct BufWriter { + | ------------------------------ doesn't satisfy `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `&dyn std::io::Write: std::io::Write` + `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 2051ea3339193..456e1cd83ef4e 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -11,7 +11,10 @@ error[E0599]: no method named `clone` found for union `U5` in the c --> $DIR/union-derive-clone.rs:37:15 | LL | union U5 { - | ----------- method `clone` not found for this + | ----------- + | | + | method `clone` not found for this + | doesn't satisfy `U5: std::clone::Clone` ... LL | struct CloneNoCopy; | ------------------- doesn't satisfy `CloneNoCopy: std::marker::Copy` @@ -20,7 +23,7 @@ LL | let w = u.clone(); | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `CloneNoCopy: std::marker::Copy` + `CloneNoCopy: std::marker::Copy` which is required by `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index f230d0d14d25a..c3be38e1cf15d 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -9,10 +9,15 @@ LL | trait Foo { ... LL | let _z = y.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` - `dyn Foo: std::marker::Sized` + `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index 12d719a102796..fb2f4c01b63b8 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -6,9 +6,14 @@ LL | struct R { ... LL | let _j = i.clone(); | ^^^^^ method not found in `std::boxed::Box` + | + ::: $SRC_DIR/liballoc/boxed.rs:LL:COL + | +LL | pub struct Box(Unique); + | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `R: std::clone::Clone` + `R: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 615542aa2a1a4c548291f4a95e9a9db30afbb28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 18:06:03 -0800 Subject: [PATCH 12/31] Point at closure definitions --- src/librustc_typeck/check/method/suggest.rs | 41 +++++++++++-------- src/test/ui/issues/issue-31173.stderr | 4 +- .../ui/mismatched_types/issue-36053-2.stderr | 7 +++- .../mut-borrow-needed-by-trait.stderr | 2 +- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 973f8208f16f6..5d4a143598fb9 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -538,28 +538,29 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); let mut bound_spans = vec![]; - let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str| { + let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { + let msg = format!( + "doesn't satisfy {}", + if obligation.len() > 50 { quiet } else { obligation } + ); match &self_ty.kind { - ty::Adt(def, _) => { - // Point at the type that couldn't satisfy the bound. - bound_spans.push(( - def_span(def.did), - format!("doesn't satisfy {}", obligation), - )); - } + // Point at the type that couldn't satisfy the bound. + ty::Adt(def, _) => bound_spans.push((def_span(def.did), msg)), + // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { - // Point at the trait object that couldn't satisfy the bound. for pred in *preds.skip_binder() { match pred { - ty::ExistentialPredicate::Trait(tr) => bound_spans.push(( - def_span(tr.def_id), - format!("doesn't satisfy {}", obligation), - )), + ty::ExistentialPredicate::Trait(tr) => { + bound_spans.push((def_span(tr.def_id), msg.clone())) + } ty::ExistentialPredicate::Projection(_) | ty::ExistentialPredicate::AutoTrait(_) => {} } } } + // Point at the closure that couldn't satisfy the bound. + ty::Closure(def_id, _) => bound_spans + .push((def_span(*def_id), format!("doesn't satisfy {}", quiet))), _ => {} } }; @@ -573,9 +574,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - let obligation = - format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); - bound_span_label(trait_ref.self_ty(), &obligation); + let msg = format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + let quiet = format!( + "`<_ as {}>::{} = {}`", + trait_ref.print_only_trait_path(), + assoc.ident, + ty + ); + bound_span_label(trait_ref.self_ty(), &msg, &quiet); Some(obligation) } ty::Predicate::Trait(poly_trait_ref, _) => { @@ -583,7 +589,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let self_ty = p.self_ty(); let path = p.print_only_trait_path(); let obligation = format!("`{}: {}`", self_ty, path); - bound_span_label(self_ty, &obligation); + let quiet = format!("`_: {}`", path); + bound_span_label(self_ty, &obligation, &quiet); Some(obligation) } _ => None, diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index 9100f2c3a938d..ca8e63550d602 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -16,10 +16,10 @@ LL | .collect(); ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Cloned { - | -------------------- doesn't satisfy `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + | -------------------- doesn't satisfy `_: std::iter::Iterator` ... LL | pub struct TakeWhile { - | -------------------------- doesn't satisfy `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + | -------------------------- doesn't satisfy `<_ as std::iter::Iterator>::Item = &_` | = note: the method `collect` exists but the following trait bounds were not satisfied: `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 5899dfffa41de..49e61cd23277b 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -2,12 +2,15 @@ error[E0599]: no method named `count` found for struct `std::iter::Filter $DIR/issue-36053-2.rs:11:55 | LL | once::<&str>("str").fuse().filter(|a: &str| true).count(); - | ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` + | -------------- ^^^^^ method not found in `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>` + | | + | doesn't satisfy `<_ as std::ops::FnOnce<(&&str,)>>::Output = bool` + | doesn't satisfy `_: std::ops::FnMut<(&&str,)>` | ::: $SRC_DIR/libcore/iter/adapters/mod.rs:LL:COL | LL | pub struct Filter { - | ----------------------- doesn't satisfy `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + | ----------------------- doesn't satisfy `_: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 5d297728eca6d..16a03c42a4d73 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -34,7 +34,7 @@ LL | writeln!(fp, "hello world").unwrap(); ::: $SRC_DIR/libstd/io/buffered.rs:LL:COL | LL | pub struct BufWriter { - | ------------------------------ doesn't satisfy `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` + | ------------------------------ doesn't satisfy `_: std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` From 92454150da1e3644e9b6adeece498b0a7f030818 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 18:20:23 -0800 Subject: [PATCH 13/31] Mention the full path of the implementing trait --- src/librustc_typeck/check/method/suggest.rs | 11 ++++++++--- .../associated-const/associated-const-no-item.stderr | 2 +- src/test/ui/auto-ref-slice-plus-ref.stderr | 8 ++++---- .../issue-21659-show-relevant-trait-impls-3.stderr | 2 +- .../ui/impl-trait/no-method-suggested-traits.stderr | 12 ++++++------ src/test/ui/issues/issue-5153.stderr | 2 +- src/test/ui/issues/issue-57362-1.stderr | 2 +- src/test/ui/issues/issue-57362-2.stderr | 2 +- src/test/ui/never_type/issue-2149.stderr | 2 +- src/test/ui/object-pointer-types.stderr | 4 ++-- .../point-at-arbitrary-self-type-trait-method.stderr | 2 +- .../specialization-trait-not-implemented.stderr | 2 +- src/test/ui/traits/trait-item-privacy.stderr | 6 +++--- .../ui/trivial-bounds/trivial-bounds-leak.stderr | 2 +- 14 files changed, 32 insertions(+), 27 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5d4a143598fb9..af7f63772c336 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -574,14 +574,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - let msg = format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + let obligation = + format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); let quiet = format!( "`<_ as {}>::{} = {}`", trait_ref.print_only_trait_path(), assoc.ident, ty ); - bound_span_label(trait_ref.self_ty(), &msg, &quiet); + bound_span_label(trait_ref.self_ty(), &obligation, &quiet); Some(obligation) } ty::Predicate::Trait(poly_trait_ref, _) => { @@ -994,7 +995,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { err.span_label( self.tcx.sess.source_map().def_span(span), - &format!("this trait defines an item `{}`", item_name), + &format!( + "`{}` defines an item `{}`", + self.tcx.def_path_str(trait_info.def_id), + item_name + ), ); use_note = false } diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index e6765bc3dd65e..02d4866e3f52b 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -2,7 +2,7 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current --> $DIR/associated-const-no-item.rs:5:23 | LL | trait Foo { - | --------- this trait defines an item `ID` + | --------- `Foo` defines an item `ID` ... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 3e14dc801221c..26b2c44fdd9e4 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -5,7 +5,7 @@ LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` ... LL | trait MyIter { - | ------------ this trait defines an item `test_mut` + | ------------ `MyIter` defines an item `test_mut` | = help: items from traits can only be used if the trait is implemented and in scope @@ -16,7 +16,7 @@ LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` ... LL | trait MyIter { - | ------------ this trait defines an item `test` + | ------------ `MyIter` defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope @@ -27,7 +27,7 @@ LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` ... LL | trait MyIter { - | ------------ this trait defines an item `test` + | ------------ `MyIter` defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope @@ -38,7 +38,7 @@ LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` ... LL | trait MyIter { - | ------------ this trait defines an item `test` + | ------------ `MyIter` defines an item `test` | = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 32a677a7d7fc1..cdcf84a706357 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | LL | trait Foo { - | ------------ this trait defines an item `foo` + | ------------ `Foo` defines an item `foo` ... LL | struct Bar; | ----------- method `foo` not found for this diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index 8025c12047fef..b3da4a6ead664 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -123,7 +123,7 @@ error[E0599]: no method named `method2` found for type `u64` in the current scop --> $DIR/no-method-suggested-traits.rs:45:10 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` @@ -134,7 +134,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:47:44 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` @@ -145,7 +145,7 @@ error[E0599]: no method named `method2` found for struct `no_method_suggested_tr --> $DIR/no-method-suggested-traits.rs:50:37 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` @@ -156,7 +156,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:52:71 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` @@ -167,7 +167,7 @@ error[E0599]: no method named `method2` found for enum `no_method_suggested_trai --> $DIR/no-method-suggested-traits.rs:54:40 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` @@ -178,7 +178,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:56:74 | LL | pub trait Bar { - | ------------- this trait defines an item `method2` + | ------------- `foo::Bar` defines an item `method2` ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 730da21ddf5fe..bf48c662383fe 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the curren --> $DIR/issue-5153.rs:10:27 | LL | trait Foo { - | --------- this trait defines an item `foo` + | --------- `Foo` defines an item `foo` ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 3a5189b132da2..4eaa5adbea4e6 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current --> $DIR/issue-57362-1.rs:20:7 | LL | trait Trait { - | ----------- this trait defines an item `f` + | ----------- `Trait` defines an item `f` ... LL | a.f(); | ^ method not found in `fn(&u8)` diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index e2d80b3b4df73..ce689334cc13d 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer --> $DIR/issue-57362-2.rs:22:25 | LL | trait X { - | ------- this trait defines an item `make_g` + | ------- `X` defines an item `make_g` ... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index 4fadf49bd6d28..b92ab5dde2766 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -10,7 +10,7 @@ error[E0599]: no method named `bind` found for array `[&str; 1]` in the current --> $DIR/issue-2149.rs:13:12 | LL | trait VecMonad { - | ----------------- this trait defines an item `bind` + | ----------------- `VecMonad` defines an item `bind` ... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 5ca326bca31c5..7364ead97f6d9 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the curr --> $DIR/object-pointer-types.rs:11:7 | LL | trait Foo { - | --------- this trait defines an item `owned` + | --------- `Foo` defines an item `owned` ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` @@ -13,7 +13,7 @@ error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` --> $DIR/object-pointer-types.rs:17:7 | LL | trait Foo { - | --------- this trait defines an item `owned` + | --------- `Foo` defines an item `owned` ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 8ed2b8b5c9521..fefa6dab15acc 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope LL | trait B { fn foo(self: Box); } | ------- --- the method is available for `std::boxed::Box` here | | - | this trait defines an item `foo` + | `B` defines an item `foo` LL | struct A; | --------- method `foo` not found for this ... diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 14f37150c8070..93a5f3051fe33 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | trait Foo { - | --------- this trait defines an item `foo_one` + | --------- `Foo` defines an item `foo_one` ... LL | struct MyStruct; | ---------------- diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 5b7f0a8ce5ff1..23f08f37826f8 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -5,7 +5,7 @@ LL | struct S; | --------- method `a` not found for this ... LL | trait A { - | ------- this trait defines an item `a` + | ------- `method::A` defines an item `a` ... LL | S.a(); | ^ method not found in `S` @@ -47,7 +47,7 @@ LL | struct S; | --------- function or associated item `a` not found for this ... LL | trait A { - | ------- this trait defines an item `a` + | ------- `method::A` defines an item `a` ... LL | S::a(&S); | ^ function or associated item not found in `S` @@ -82,7 +82,7 @@ LL | struct S; | --------- associated item `A` not found for this ... LL | trait A { - | ------- this trait defines an item `A` + | ------- `assoc_const::A` defines an item `A` ... LL | S::A; | ^ associated item not found in `S` diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 7ed24591e66ab..0bd18763ac977 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -12,7 +12,7 @@ error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | LL | pub trait Foo { - | ------------- this trait defines an item `test` + | ------------- `Foo` defines an item `test` ... LL | 3i32.test(); | ^^^^ method not found in `i32` From cfbb7464e0fc1e92be296f6cd66a936bf7f71ca5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 18 Feb 2020 18:36:56 -0800 Subject: [PATCH 14/31] Tweak wording --- src/librustc_typeck/check/method/suggest.rs | 6 ++++-- .../associated-const/associated-const-no-item.stderr | 2 +- src/test/ui/auto-ref-slice-plus-ref.stderr | 8 ++++---- .../issue-21659-show-relevant-trait-impls-3.stderr | 2 +- .../ui/impl-trait/no-method-suggested-traits.stderr | 12 ++++++------ src/test/ui/issues/issue-5153.stderr | 2 +- src/test/ui/issues/issue-57362-1.stderr | 2 +- src/test/ui/issues/issue-57362-2.stderr | 2 +- src/test/ui/never_type/issue-2149.stderr | 2 +- src/test/ui/object-pointer-types.stderr | 4 ++-- .../point-at-arbitrary-self-type-trait-method.stderr | 2 +- .../specialization-trait-not-implemented.stderr | 2 +- src/test/ui/traits/trait-item-privacy.stderr | 6 +++--- .../ui/trivial-bounds/trivial-bounds-leak.stderr | 2 +- 14 files changed, 28 insertions(+), 26 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index af7f63772c336..7e98797d0c2c9 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -988,6 +988,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let action = if let Some(param) = param_type { format!("restrict type parameter `{}` with", param) } else { + // FIXME: it might only need to be imported into scope, not implemented. "implement".to_string() }; let mut use_note = true; @@ -996,9 +997,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label( self.tcx.sess.source_map().def_span(span), &format!( - "`{}` defines an item `{}`", + "`{}` defines an item `{}`, perhaps you need to {} it", self.tcx.def_path_str(trait_info.def_id), - item_name + item_name, + action ), ); use_note = false diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index 02d4866e3f52b..c3339e453e81e 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -2,7 +2,7 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current --> $DIR/associated-const-no-item.rs:5:23 | LL | trait Foo { - | --------- `Foo` defines an item `ID` + | --------- `Foo` defines an item `ID`, perhaps you need to implement it ... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 26b2c44fdd9e4..3500cef6c39bd 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -5,7 +5,7 @@ LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test_mut` + | ------------ `MyIter` defines an item `test_mut`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope @@ -16,7 +16,7 @@ LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test` + | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope @@ -27,7 +27,7 @@ LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test` + | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope @@ -38,7 +38,7 @@ LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` ... LL | trait MyIter { - | ------------ `MyIter` defines an item `test` + | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index cdcf84a706357..75a2e9a99a994 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | LL | trait Foo { - | ------------ `Foo` defines an item `foo` + | ------------ `Foo` defines an item `foo`, perhaps you need to implement it ... LL | struct Bar; | ----------- method `foo` not found for this diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index b3da4a6ead664..c6017a5fea182 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -123,7 +123,7 @@ error[E0599]: no method named `method2` found for type `u64` in the current scop --> $DIR/no-method-suggested-traits.rs:45:10 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` @@ -134,7 +134,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:47:44 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` @@ -145,7 +145,7 @@ error[E0599]: no method named `method2` found for struct `no_method_suggested_tr --> $DIR/no-method-suggested-traits.rs:50:37 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` @@ -156,7 +156,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:52:71 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` @@ -167,7 +167,7 @@ error[E0599]: no method named `method2` found for enum `no_method_suggested_trai --> $DIR/no-method-suggested-traits.rs:54:40 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` @@ -178,7 +178,7 @@ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std:: --> $DIR/no-method-suggested-traits.rs:56:74 | LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2` + | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it ... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index bf48c662383fe..44ef73550f8a4 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the curren --> $DIR/issue-5153.rs:10:27 | LL | trait Foo { - | --------- `Foo` defines an item `foo` + | --------- `Foo` defines an item `foo`, perhaps you need to implement it ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index 4eaa5adbea4e6..c48f51e2b2a20 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current --> $DIR/issue-57362-1.rs:20:7 | LL | trait Trait { - | ----------- `Trait` defines an item `f` + | ----------- `Trait` defines an item `f`, perhaps you need to implement it ... LL | a.f(); | ^ method not found in `fn(&u8)` diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index ce689334cc13d..b3b30dbd1c889 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -2,7 +2,7 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer --> $DIR/issue-57362-2.rs:22:25 | LL | trait X { - | ------- `X` defines an item `make_g` + | ------- `X` defines an item `make_g`, perhaps you need to implement it ... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index b92ab5dde2766..745126199663d 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -10,7 +10,7 @@ error[E0599]: no method named `bind` found for array `[&str; 1]` in the current --> $DIR/issue-2149.rs:13:12 | LL | trait VecMonad { - | ----------------- `VecMonad` defines an item `bind` + | ----------------- `VecMonad` defines an item `bind`, perhaps you need to implement it ... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 7364ead97f6d9..07b7da94097b5 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the curr --> $DIR/object-pointer-types.rs:11:7 | LL | trait Foo { - | --------- `Foo` defines an item `owned` + | --------- `Foo` defines an item `owned`, perhaps you need to implement it ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` @@ -13,7 +13,7 @@ error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` --> $DIR/object-pointer-types.rs:17:7 | LL | trait Foo { - | --------- `Foo` defines an item `owned` + | --------- `Foo` defines an item `owned`, perhaps you need to implement it ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index fefa6dab15acc..999bbcca6bcb9 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -4,7 +4,7 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope LL | trait B { fn foo(self: Box); } | ------- --- the method is available for `std::boxed::Box` here | | - | `B` defines an item `foo` + | `B` defines an item `foo`, perhaps you need to implement it LL | struct A; | --------- method `foo` not found for this ... diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index 93a5f3051fe33..f4d29e61cc17e 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -2,7 +2,7 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the curre --> $DIR/specialization-trait-not-implemented.rs:22:29 | LL | trait Foo { - | --------- `Foo` defines an item `foo_one` + | --------- `Foo` defines an item `foo_one`, perhaps you need to implement it ... LL | struct MyStruct; | ---------------- diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index 23f08f37826f8..f893456a17cc0 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -5,7 +5,7 @@ LL | struct S; | --------- method `a` not found for this ... LL | trait A { - | ------- `method::A` defines an item `a` + | ------- `method::A` defines an item `a`, perhaps you need to implement it ... LL | S.a(); | ^ method not found in `S` @@ -47,7 +47,7 @@ LL | struct S; | --------- function or associated item `a` not found for this ... LL | trait A { - | ------- `method::A` defines an item `a` + | ------- `method::A` defines an item `a`, perhaps you need to implement it ... LL | S::a(&S); | ^ function or associated item not found in `S` @@ -82,7 +82,7 @@ LL | struct S; | --------- associated item `A` not found for this ... LL | trait A { - | ------- `assoc_const::A` defines an item `A` + | ------- `assoc_const::A` defines an item `A`, perhaps you need to implement it ... LL | S::A; | ^ associated item not found in `S` diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index 0bd18763ac977..ef41c0e5fa01d 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -12,7 +12,7 @@ error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | LL | pub trait Foo { - | ------------- `Foo` defines an item `test` + | ------------- `Foo` defines an item `test`, perhaps you need to implement it ... LL | 3i32.test(); | ^^^^ method not found in `i32` From 7818a1d841b9a7d3f6008aa914b770c16e0f3113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 19 Feb 2020 14:26:46 -0800 Subject: [PATCH 15/31] Suggest constraining type parameters --- src/librustc_parse/parser/generics.rs | 6 +- src/librustc_typeck/check/method/suggest.rs | 80 +++++++++++++++---- .../missing-trait-bounds-for-method-call.rs | 31 +++++++ ...issing-trait-bounds-for-method-call.stderr | 44 ++++++++++ 4 files changed, 144 insertions(+), 17 deletions(-) create mode 100644 src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs create mode 100644 src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr diff --git a/src/librustc_parse/parser/generics.rs b/src/librustc_parse/parser/generics.rs index 0984263bb283e..4d9a3266567f3 100644 --- a/src/librustc_parse/parser/generics.rs +++ b/src/librustc_parse/parser/generics.rs @@ -1,7 +1,6 @@ use super::Parser; use rustc_errors::PResult; -use rustc_span::source_map::DUMMY_SP; use rustc_span::symbol::{kw, sym}; use syntax::ast::{self, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause}; use syntax::token; @@ -160,7 +159,10 @@ impl<'a> Parser<'a> { }; Ok(ast::Generics { params, - where_clause: WhereClause { predicates: Vec::new(), span: DUMMY_SP }, + where_clause: WhereClause { + predicates: Vec::new(), + span: self.prev_span.shrink_to_hi(), + }, span, }) } diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 7e98797d0c2c9..410b8883a29d9 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -7,7 +7,7 @@ use rustc::hir::map as hir_map; use rustc::hir::map::Map; use rustc::ty::print::with_crate_prefix; use rustc::ty::{self, ToPolyTraitRef, ToPredicate, Ty, TyCtxt, TypeFoldable, WithConstness}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Namespace, Res}; @@ -537,10 +537,43 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !unsatisfied_predicates.is_empty() { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); + let mut type_params = FxHashMap::default(); let mut bound_spans = vec![]; + let mut collect_type_param_suggestions = + |self_ty: Ty<'_>, parent_pred: &ty::Predicate<'_>, obligation: &str| { + if let (ty::Param(_), ty::Predicate::Trait(p, _)) = + (&self_ty.kind, parent_pred) + { + if let ty::Adt(def, _) = p.skip_binder().trait_ref.self_ty().kind { + let id = self.tcx.hir().as_local_hir_id(def.did).unwrap(); + let node = self.tcx.hir().get(id); + match node { + hir::Node::Item(hir::Item { kind, .. }) => { + if let Some(g) = kind.generics() { + let key = match &g.where_clause.predicates[..] { + [.., pred] => { + (pred.span().shrink_to_hi(), false) + } + [] => ( + g.where_clause + .span_for_predicates_or_empty_place(), + true, + ), + }; + type_params + .entry(key) + .or_insert_with(FxHashSet::default) + .insert(obligation.to_owned()); + } + } + _ => {} + } + } + } + }; let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!( - "doesn't satisfy {}", + "doesn't satisfy `{}`", if obligation.len() > 50 { quiet } else { obligation } ); match &self_ty.kind { @@ -560,7 +593,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => bound_spans - .push((def_span(*def_id), format!("doesn't satisfy {}", quiet))), + .push((def_span(*def_id), format!("doesn't satisfy `{}`", quiet))), _ => {} } }; @@ -574,25 +607,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .tcx .associated_item(pred.skip_binder().projection_ty.item_def_id); let ty = pred.skip_binder().ty; - let obligation = - format!("`{}::{} = {}`", trait_ref, assoc.ident, ty); + let obligation = format!("{}::{} = {}", trait_ref, assoc.ident, ty); let quiet = format!( - "`<_ as {}>::{} = {}`", + "<_ as {}>::{} = {}", trait_ref.print_only_trait_path(), assoc.ident, ty ); bound_span_label(trait_ref.self_ty(), &obligation, &quiet); - Some(obligation) + Some((obligation, trait_ref.self_ty())) } ty::Predicate::Trait(poly_trait_ref, _) => { let p = poly_trait_ref.skip_binder().trait_ref; let self_ty = p.self_ty(); let path = p.print_only_trait_path(); - let obligation = format!("`{}: {}`", self_ty, path); - let quiet = format!("`_: {}`", path); + let obligation = format!("{}: {}", self_ty, path); + let quiet = format!("_: {}", path); bound_span_label(self_ty, &obligation, &quiet); - Some(obligation) + Some((obligation, self_ty)) } _ => None, } @@ -600,17 +632,35 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut bound_list = unsatisfied_predicates .iter() .filter_map(|(pred, parent_pred)| { - format_pred(*pred).map(|pred| match parent_pred { - None => pred, + format_pred(*pred).map(|(p, self_ty)| match parent_pred { + None => format!("`{}`", p), Some(parent_pred) => match format_pred(*parent_pred) { - None => pred, - Some(parent_pred) => { - format!("{} which is required by {}", pred, parent_pred) + None => format!("`{}`", p), + Some((parent_p, _)) => { + collect_type_param_suggestions(self_ty, parent_pred, &p); + format!("`{}` which is required by `{}`", p, parent_p) } }, }) }) .collect::>(); + for ((span, empty_where), obligations) in type_params.into_iter() { + err.span_suggestion_verbose( + span, + &format!( + "consider restricting the type parameter{s} to satisfy the \ + obligation{s}", + s = pluralize!(obligations.len()) + ), + format!( + "{} {}", + if empty_where { " where" } else { "," }, + obligations.into_iter().collect::>().join(", ") + ), + Applicability::MaybeIncorrect, + ); + } + bound_list.sort(); bound_list.dedup(); // #35677 bound_spans.sort(); diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs new file mode 100644 index 0000000000000..fefdf149f556c --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.rs @@ -0,0 +1,31 @@ +#[derive(Default, PartialEq)] +struct Foo { + bar: Box<[T]>, +} + +trait Bar { + fn foo(&self) {} +} + +impl Bar for Foo {} + +impl Foo { + fn bar(&self) { + self.foo(); + //~^ ERROR no method named `foo` found for reference `&Foo` in the current scope + } +} + +struct Fin where T: Bar { + bar: Box<[T]>, +} + +impl Bar for Fin {} + +impl Fin { + fn bar(&self) { + self.foo(); + //~^ ERROR no method named `foo` found for reference `&Fin` in the current scope + } +} +fn main() {} diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr new file mode 100644 index 0000000000000..b1b31a67650b6 --- /dev/null +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -0,0 +1,44 @@ +error[E0599]: no method named `foo` found for reference `&Foo` in the current scope + --> $DIR/missing-trait-bounds-for-method-call.rs:14:14 + | +LL | struct Foo { + | ------------- doesn't satisfy `Foo: Bar` +... +LL | trait Bar { + | --------- `Bar` defines an item `foo`, perhaps you need to implement it +... +LL | self.foo(); + | ^^^ method not found in `&Foo` + | + = note: the method `foo` exists but the following trait bounds were not satisfied: + `T: Bar` which is required by `Foo: Bar` + `T: std::default::Default` which is required by `Foo: Bar` + = help: items from traits can only be used if the trait is implemented and in scope +help: consider restricting the type parameters to satisfy the obligations + | +LL | struct Foo where T: Bar, T: std::default::Default { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0599]: no method named `foo` found for reference `&Fin` in the current scope + --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 + | +LL | trait Bar { + | --------- `Bar` defines an item `foo`, perhaps you need to implement it +... +LL | struct Fin where T: Bar { + | -------------------------- doesn't satisfy `Fin: Bar` +... +LL | self.foo(); + | ^^^ method not found in `&Fin` + | + = note: the method `foo` exists but the following trait bounds were not satisfied: + `T: std::default::Default` which is required by `Fin: Bar` + = help: items from traits can only be used if the trait is implemented and in scope +help: consider restricting the type parameter to satisfy the obligation + | +LL | struct Fin where T: Bar, T: std::default::Default { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0599`. From 3a58953bdb453ea28daf433aa0f88786113565cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 19 Feb 2020 15:57:21 -0800 Subject: [PATCH 16/31] Account for arbitrary self types in E0599 --- src/librustc_typeck/check/method/suggest.rs | 51 +++++++++++++++++++ src/test/ui/issues/issue-5153.stderr | 6 +-- src/test/ui/object-pointer-types.stderr | 12 ++--- ...at-arbitrary-self-type-trait-method.stderr | 8 ++- 4 files changed, 60 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 410b8883a29d9..cfd6356b0a157 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -16,6 +16,7 @@ use rustc_hir::intravisit; use rustc_hir::{ExprKind, Node, QPath}; use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind}; use rustc_infer::traits::Obligation; +use rustc_span::symbol::kw; use rustc_span::{source_map, FileName, Span}; use syntax::ast; use syntax::util::lev_distance; @@ -893,6 +894,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let type_is_local = self.type_derefs_to_local(span, rcvr_ty, source); + let mut arbitrary_rcvr = vec![]; // There are no traits implemented, so lets suggest some traits to // implement, by finding ones that have the item name, and are // legal to implement. @@ -909,12 +911,61 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && self .associated_item(info.def_id, item_name, Namespace::ValueNS) .filter(|item| { + if let ty::AssocKind::Method = item.kind { + let id = self.tcx.hir().as_local_hir_id(item.def_id); + if let Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Method(fn_sig, method), + .. + })) = id.map(|id| self.tcx.hir().get(id)) + { + let self_first_arg = match method { + hir::TraitMethod::Required([ident, ..]) => { + ident.name == kw::SelfLower + } + hir::TraitMethod::Provided(body_id) => { + match &self.tcx.hir().body(*body_id).params[..] { + [hir::Param { + pat: + hir::Pat { + kind: + hir::PatKind::Binding( + _, + _, + ident, + .., + ), + .. + }, + .. + }, ..] => ident.name == kw::SelfLower, + _ => false, + } + } + _ => false, + }; + + if !fn_sig.decl.implicit_self.has_implicit_self() + && self_first_arg + { + if let Some(ty) = fn_sig.decl.inputs.get(0) { + arbitrary_rcvr.push(ty.span); + } + return false; + } + } + } // We only want to suggest public or local traits (#45781). item.vis == ty::Visibility::Public || info.def_id.is_local() }) .is_some() }) .collect::>(); + for span in &arbitrary_rcvr { + err.span_label( + *span, + "the method might not be found because of this arbitrary self type", + ); + } if !candidates.is_empty() { // Sort from most relevant to least relevant. diff --git a/src/test/ui/issues/issue-5153.stderr b/src/test/ui/issues/issue-5153.stderr index 44ef73550f8a4..93aaf4b9d8237 100644 --- a/src/test/ui/issues/issue-5153.stderr +++ b/src/test/ui/issues/issue-5153.stderr @@ -1,13 +1,11 @@ error[E0599]: no method named `foo` found for reference `&dyn Foo` in the current scope --> $DIR/issue-5153.rs:10:27 | -LL | trait Foo { - | --------- `Foo` defines an item `foo`, perhaps you need to implement it +LL | fn foo(self: Box); + | --------- the method might not be found because of this arbitrary self type ... LL | (&5isize as &dyn Foo).foo(); | ^^^ method not found in `&dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error diff --git a/src/test/ui/object-pointer-types.stderr b/src/test/ui/object-pointer-types.stderr index 07b7da94097b5..021aa8670f78f 100644 --- a/src/test/ui/object-pointer-types.stderr +++ b/src/test/ui/object-pointer-types.stderr @@ -1,24 +1,20 @@ error[E0599]: no method named `owned` found for reference `&dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:11:7 | -LL | trait Foo { - | --------- `Foo` defines an item `owned`, perhaps you need to implement it +LL | fn owned(self: Box); + | --------- the method might not be found because of this arbitrary self type ... LL | x.owned(); | ^^^^^ method not found in `&dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error[E0599]: no method named `owned` found for mutable reference `&mut dyn Foo` in the current scope --> $DIR/object-pointer-types.rs:17:7 | -LL | trait Foo { - | --------- `Foo` defines an item `owned`, perhaps you need to implement it +LL | fn owned(self: Box); + | --------- the method might not be found because of this arbitrary self type ... LL | x.owned(); | ^^^^^ method not found in `&mut dyn Foo` - | - = help: items from traits can only be used if the trait is implemented and in scope error[E0599]: no method named `managed` found for struct `std::boxed::Box<(dyn Foo + 'static)>` in the current scope --> $DIR/object-pointer-types.rs:23:7 diff --git a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr index 999bbcca6bcb9..37873031da3e9 100644 --- a/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr +++ b/src/test/ui/self/point-at-arbitrary-self-type-trait-method.stderr @@ -2,16 +2,14 @@ error[E0599]: no method named `foo` found for struct `A` in the current scope --> $DIR/point-at-arbitrary-self-type-trait-method.rs:9:7 | LL | trait B { fn foo(self: Box); } - | ------- --- the method is available for `std::boxed::Box` here - | | - | `B` defines an item `foo`, perhaps you need to implement it + | --- --------- the method might not be found because of this arbitrary self type + | | + | the method is available for `std::boxed::Box` here LL | struct A; | --------- method `foo` not found for this ... LL | A.foo() | ^^^ method not found in `A` - | - = help: items from traits can only be used if the trait is implemented and in scope error: aborting due to previous error From 529b89191ac4740aefccf6bc00d77cd5b65480fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 21 Feb 2020 13:39:47 -0800 Subject: [PATCH 17/31] Review comments: split requirement text to multiple lines for readability --- src/librustc_typeck/check/method/suggest.rs | 2 +- src/test/ui/derives/derive-assoc-type-not-impl.stderr | 3 ++- src/test/ui/issues/issue-21596.stderr | 3 ++- src/test/ui/issues/issue-31173.stderr | 6 ++++-- src/test/ui/methods/method-call-err-msg.stderr | 3 ++- src/test/ui/mismatched_types/issue-36053-2.stderr | 9 ++++++--- .../missing-trait-bounds-for-method-call.stderr | 9 ++++++--- .../ui/suggestions/mut-borrow-needed-by-trait.stderr | 3 ++- src/test/ui/union/union-derive-clone.stderr | 3 ++- src/test/ui/unique-object-noncopyable.stderr | 6 ++++-- src/test/ui/unique-pinned-nocopy.stderr | 3 ++- 11 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index cfd6356b0a157..9fcb1c75faeaa 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -639,7 +639,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None => format!("`{}`", p), Some((parent_p, _)) => { collect_type_param_suggestions(self_ty, parent_pred, &p); - format!("`{}` which is required by `{}`", p, parent_p) + format!("`{}`\nwhich is required by `{}`", p, parent_p) } }, }) diff --git a/src/test/ui/derives/derive-assoc-type-not-impl.stderr b/src/test/ui/derives/derive-assoc-type-not-impl.stderr index e837c7721afe3..c4c85773fbc1d 100644 --- a/src/test/ui/derives/derive-assoc-type-not-impl.stderr +++ b/src/test/ui/derives/derive-assoc-type-not-impl.stderr @@ -14,7 +14,8 @@ LL | Bar:: { x: 1 }.clone(); | ^^^^^ method not found in `Bar` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `NotClone: std::clone::Clone` which is required by `Bar: std::clone::Clone` + `NotClone: std::clone::Clone` + which is required by `Bar: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/issues/issue-21596.stderr b/src/test/ui/issues/issue-21596.stderr index bbd166180499a..3e0a532b2b8f3 100644 --- a/src/test/ui/issues/issue-21596.stderr +++ b/src/test/ui/issues/issue-21596.stderr @@ -7,7 +7,8 @@ LL | println!("{}", z.to_string()); = note: try using `<*const T>::as_ref()` to get a reference to the type behind the pointer: https://doc.rust-lang.org/std/primitive.pointer.html#method.as_ref = note: using `<*const T>::as_ref()` on a pointer which is unaligned or points to invalid or uninitialized memory is undefined behavior = note: the method `to_string` exists but the following trait bounds were not satisfied: - `*const u8: std::fmt::Display` which is required by `*const u8: std::string::ToString` + `*const u8: std::fmt::Display` + which is required by `*const u8: std::string::ToString` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr index ca8e63550d602..20bfdeea4b1fa 100644 --- a/src/test/ui/issues/issue-31173.stderr +++ b/src/test/ui/issues/issue-31173.stderr @@ -22,8 +22,10 @@ LL | pub struct TakeWhile { | -------------------------- doesn't satisfy `<_ as std::iter::Iterator>::Item = &_` | = note: the method `collect` exists but the following trait bounds were not satisfied: - `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` - `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` which is required by `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]> as std::iter::Iterator>::Item = &_` + which is required by `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + `std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` + which is required by `&mut std::iter::Cloned, [closure@$DIR/issue-31173.rs:10:39: 13:6 found_e:_]>>: std::iter::Iterator` error: aborting due to 2 previous errors diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index b4e54ab77838f..ecb6950615748 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -44,7 +44,8 @@ LL | .take() | ^^^^ method not found in `Foo` | = note: the method `take` exists but the following trait bounds were not satisfied: - `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator` + `Foo: std::iter::Iterator` + which is required by `&mut Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope = note: the following traits define an item `take`, perhaps you need to implement one of them: candidate #1: `std::io::Read` diff --git a/src/test/ui/mismatched_types/issue-36053-2.stderr b/src/test/ui/mismatched_types/issue-36053-2.stderr index 49e61cd23277b..f8c0470172d19 100644 --- a/src/test/ui/mismatched_types/issue-36053-2.stderr +++ b/src/test/ui/mismatched_types/issue-36053-2.stderr @@ -13,9 +13,12 @@ LL | pub struct Filter { | ----------------------- doesn't satisfy `_: std::iter::Iterator` | = note: the method `count` exists but the following trait bounds were not satisfied: - `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` - `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` - `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` which is required by `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `<[closure@$DIR/issue-36053-2.rs:11:39: 11:53] as std::ops::FnOnce<(&&str,)>>::Output = bool` + which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `[closure@$DIR/issue-36053-2.rs:11:39: 11:53]: std::ops::FnMut<(&&str,)>` + which is required by `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + `std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` + which is required by `&mut std::iter::Filter>, [closure@$DIR/issue-36053-2.rs:11:39: 11:53]>: std::iter::Iterator` error[E0631]: type mismatch in closure arguments --> $DIR/issue-36053-2.rs:11:32 diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index b1b31a67650b6..4f6620b47c268 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -11,8 +11,10 @@ LL | self.foo(); | ^^^ method not found in `&Foo` | = note: the method `foo` exists but the following trait bounds were not satisfied: - `T: Bar` which is required by `Foo: Bar` - `T: std::default::Default` which is required by `Foo: Bar` + `T: Bar` + which is required by `Foo: Bar` + `T: std::default::Default` + which is required by `Foo: Bar` = help: items from traits can only be used if the trait is implemented and in scope help: consider restricting the type parameters to satisfy the obligations | @@ -32,7 +34,8 @@ LL | self.foo(); | ^^^ method not found in `&Fin` | = note: the method `foo` exists but the following trait bounds were not satisfied: - `T: std::default::Default` which is required by `Fin: Bar` + `T: std::default::Default` + which is required by `Fin: Bar` = help: items from traits can only be used if the trait is implemented and in scope help: consider restricting the type parameter to satisfy the obligation | diff --git a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr index 16a03c42a4d73..57a389cbb49b5 100644 --- a/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr +++ b/src/test/ui/suggestions/mut-borrow-needed-by-trait.stderr @@ -37,7 +37,8 @@ LL | pub struct BufWriter { | ------------------------------ doesn't satisfy `_: std::io::Write` | = note: the method `write_fmt` exists but the following trait bounds were not satisfied: - `&dyn std::io::Write: std::io::Write` which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` + `&dyn std::io::Write: std::io::Write` + which is required by `std::io::BufWriter<&dyn std::io::Write>: std::io::Write` = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index 456e1cd83ef4e..fdf2393656e12 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -23,7 +23,8 @@ LL | let w = u.clone(); | ^^^^^ method not found in `U5` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `CloneNoCopy: std::marker::Copy` which is required by `U5: std::clone::Clone` + `CloneNoCopy: std::marker::Copy` + which is required by `U5: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index c3be38e1cf15d..6a0a6c87079f3 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -16,8 +16,10 @@ LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` - `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::clone::Clone` + which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::marker::Sized` + which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` diff --git a/src/test/ui/unique-pinned-nocopy.stderr b/src/test/ui/unique-pinned-nocopy.stderr index fb2f4c01b63b8..32f751fbcf7c3 100644 --- a/src/test/ui/unique-pinned-nocopy.stderr +++ b/src/test/ui/unique-pinned-nocopy.stderr @@ -13,7 +13,8 @@ LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `R: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` + `R: std::clone::Clone` + which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From 5da393970df87f13881fd1f8cebd9b2a42659759 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2020 17:04:34 +0100 Subject: [PATCH 18/31] miri/machine: add canonical_alloc_id hook to replace find_foreign_static --- src/librustc_mir/const_eval/machine.rs | 10 +---- src/librustc_mir/interpret/machine.rs | 44 +++++++++++-------- src/librustc_mir/interpret/memory.rs | 56 +++++++++++++----------- src/librustc_mir/transform/const_prop.rs | 12 ----- 4 files changed, 57 insertions(+), 65 deletions(-) diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs index e40436ccf0b4b..25727b75faf14 100644 --- a/src/librustc_mir/const_eval/machine.rs +++ b/src/librustc_mir/const_eval/machine.rs @@ -1,7 +1,6 @@ use rustc::mir; use rustc::ty::layout::HasTyCtxt; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc::ty::{self, Ty}; use std::borrow::{Borrow, Cow}; use std::collections::hash_map::Entry; use std::hash::Hash; @@ -320,13 +319,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir, Err(ConstEvalErrKind::NeedsRfc("pointer arithmetic or comparison".to_string()).into()) } - fn find_foreign_static( - _tcx: TyCtxt<'tcx>, - _def_id: DefId, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { - throw_unsup!(ReadForeignStatic) - } - #[inline(always)] fn init_allocation_extra<'b>( _memory_extra: &MemoryExtra, diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 5291000d10b3f..98a305ec2d92c 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -6,8 +6,7 @@ use std::borrow::{Borrow, Cow}; use std::hash::Hash; use rustc::mir; -use rustc::ty::{self, Ty, TyCtxt}; -use rustc_hir::def_id::DefId; +use rustc::ty::{self, Ty}; use rustc_span::Span; use super::{ @@ -123,10 +122,6 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Whether to enforce the validity invariant fn enforce_validity(ecx: &InterpCx<'mir, 'tcx, Self>) -> bool; - /// Called before a basic block terminator is executed. - /// You can use this to detect endlessly running programs. - fn before_terminator(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>; - /// Entry point to all function calls. /// /// Returns either the mir to use for the call, or `None` if execution should @@ -175,18 +170,6 @@ pub trait Machine<'mir, 'tcx>: Sized { unwind: Option, ) -> InterpResult<'tcx>; - /// Called for read access to a foreign static item. - /// - /// This will only be called once per static and machine; the result is cached in - /// the machine memory. (This relies on `AllocMap::get_or` being able to add the - /// owned allocation to the map even when the map is shared.) - /// - /// This allocation will then be fed to `tag_allocation` to initialize the "extra" state. - fn find_foreign_static( - tcx: TyCtxt<'tcx>, - def_id: DefId, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>>; - /// Called for all binary operations where the LHS has pointer type. /// /// Returns a (value, overflowed) pair if the operation succeeded @@ -204,6 +187,7 @@ pub trait Machine<'mir, 'tcx>: Sized { ) -> InterpResult<'tcx>; /// Called to read the specified `local` from the `frame`. + #[inline] fn access_local( _ecx: &InterpCx<'mir, 'tcx, Self>, frame: &Frame<'mir, 'tcx, Self::PointerTag, Self::FrameExtra>, @@ -212,7 +196,15 @@ pub trait Machine<'mir, 'tcx>: Sized { frame.locals[local].access() } + /// Called before a basic block terminator is executed. + /// You can use this to detect endlessly running programs. + #[inline] + fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { + Ok(()) + } + /// Called before a `Static` value is accessed. + #[inline] fn before_access_static( _memory_extra: &Self::MemoryExtra, _allocation: &Allocation, @@ -220,6 +212,20 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } + /// Called for *every* memory access to determine the real ID of the given allocation. + /// This provides a way for the machine to "redirect" certain allocations as it sees fit. + /// + /// This is used by Miri to redirect extern statics to real allocations. + /// + /// This function must be idempotent. + #[inline] + fn canonical_alloc_id( + _mem: &Memory<'mir, 'tcx, Self>, + id: AllocId, + ) -> AllocId { + id + } + /// Called to initialize the "extra" state of an allocation and make the pointers /// it contains (in relocations) tagged. The way we construct allocations is /// to always first construct it without extra and then add the extra. @@ -259,7 +265,7 @@ pub trait Machine<'mir, 'tcx>: Sized { Ok(()) } - /// Called immediately before a new stack frame got pushed + /// Called immediately before a new stack frame got pushed. fn stack_push(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx, Self::FrameExtra>; /// Called immediately after a stack frame gets popped diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 1df389d9c8bee..048c5d7b15956 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -421,6 +421,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// The `GlobalAlloc::Memory` branch here is still reachable though; when a static /// contains a reference to memory that was created during its evaluation (i.e., not to /// another static), those inner references only exist in "resolved" form. + /// + /// Assumes `id` is already canonical. fn get_static_alloc( memory_extra: &M::MemoryExtra, tcx: TyCtxtAt<'tcx>, @@ -434,31 +436,30 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { Some(GlobalAlloc::Static(def_id)) => { // We got a "lazy" static that has not been computed yet. if tcx.is_foreign_item(def_id) { - trace!("static_alloc: foreign item {:?}", def_id); - M::find_foreign_static(tcx.tcx, def_id)? - } else { - trace!("static_alloc: Need to compute {:?}", def_id); - let instance = Instance::mono(tcx.tcx, def_id); - let gid = GlobalId { instance, promoted: None }; - // use the raw query here to break validation cycles. Later uses of the static - // will call the full query anyway - let raw_const = - tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { - // no need to report anything, the const_eval call takes care of that - // for statics - assert!(tcx.is_static(def_id)); - match err { - ErrorHandled::Reported => err_inval!(ReferencedConstant), - ErrorHandled::TooGeneric => err_inval!(TooGeneric), - } - })?; - // Make sure we use the ID of the resolved memory, not the lazy one! - let id = raw_const.alloc_id; - let allocation = tcx.alloc_map.lock().unwrap_memory(id); - - M::before_access_static(memory_extra, allocation)?; - Cow::Borrowed(allocation) + trace!("get_static_alloc: foreign item {:?}", def_id); + throw_unsup!(ReadForeignStatic) } + trace!("get_static_alloc: Need to compute {:?}", def_id); + let instance = Instance::mono(tcx.tcx, def_id); + let gid = GlobalId { instance, promoted: None }; + // use the raw query here to break validation cycles. Later uses of the static + // will call the full query anyway + let raw_const = + tcx.const_eval_raw(ty::ParamEnv::reveal_all().and(gid)).map_err(|err| { + // no need to report anything, the const_eval call takes care of that + // for statics + assert!(tcx.is_static(def_id)); + match err { + ErrorHandled::Reported => err_inval!(ReferencedConstant), + ErrorHandled::TooGeneric => err_inval!(TooGeneric), + } + })?; + // Make sure we use the ID of the resolved memory, not the lazy one! + let id = raw_const.alloc_id; + let allocation = tcx.alloc_map.lock().unwrap_memory(id); + + M::before_access_static(memory_extra, allocation)?; + Cow::Borrowed(allocation) } }; // We got tcx memory. Let the machine initialize its "extra" stuff. @@ -478,6 +479,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { &self, id: AllocId, ) -> InterpResult<'tcx, &Allocation> { + let id = M::canonical_alloc_id(self, id); // The error type of the inner closure here is somewhat funny. We have two // ways of "erroring": An actual error, or because we got a reference from // `get_static_alloc` that we can actually use directly without inserting anything anywhere. @@ -513,6 +515,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { &mut self, id: AllocId, ) -> InterpResult<'tcx, &mut Allocation> { + let id = M::canonical_alloc_id(self, id); let tcx = self.tcx; let memory_extra = &self.extra; let a = self.alloc_map.get_mut_or(id, || { @@ -550,6 +553,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { id: AllocId, liveness: AllocCheck, ) -> InterpResult<'static, (Size, Align)> { + let id = M::canonical_alloc_id(self, id); // # Regular allocations // Don't use `self.get_raw` here as that will // a) cause cycles in case `id` refers to a static @@ -602,6 +606,7 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { } } + /// Assumes `id` is already canonical. fn get_fn_alloc(&self, id: AllocId) -> Option> { trace!("reading fn ptr: {}", id); if let Some(extra) = self.extra_fn_ptr_map.get(&id) { @@ -622,7 +627,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { if ptr.offset.bytes() != 0 { throw_unsup!(InvalidFunctionPointer) } - self.get_fn_alloc(ptr.alloc_id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) + let id = M::canonical_alloc_id(self, ptr.alloc_id); + self.get_fn_alloc(id).ok_or_else(|| err_unsup!(ExecuteMemory).into()) } pub fn mark_immutable(&mut self, id: AllocId) -> InterpResult<'tcx> { diff --git a/src/librustc_mir/transform/const_prop.rs b/src/librustc_mir/transform/const_prop.rs index 9e05133132e05..ccfe765f2bb3c 100644 --- a/src/librustc_mir/transform/const_prop.rs +++ b/src/librustc_mir/transform/const_prop.rs @@ -22,7 +22,6 @@ use rustc::ty::subst::{InternalSubsts, Subst}; use rustc::ty::{self, ConstKind, Instance, ParamEnv, Ty, TyCtxt, TypeFoldable}; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::DefKind; -use rustc_hir::def_id::DefId; use rustc_hir::HirId; use rustc_index::vec::IndexVec; use rustc_infer::traits; @@ -222,13 +221,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { )); } - fn find_foreign_static( - _tcx: TyCtxt<'tcx>, - _def_id: DefId, - ) -> InterpResult<'tcx, Cow<'tcx, Allocation>> { - throw_unsup!(ReadForeignStatic) - } - #[inline(always)] fn init_allocation_extra<'b>( _memory_extra: &(), @@ -279,10 +271,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine { Ok(()) } - fn before_terminator(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { - Ok(()) - } - #[inline(always)] fn stack_push(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> { Ok(()) From e7a344fb745a0a663e21be947b2619df05df6d31 Mon Sep 17 00:00:00 2001 From: XAMPPRocky <4464295+XAMPPRocky@users.noreply.github.com> Date: Sun, 23 Feb 2020 18:04:48 +0100 Subject: [PATCH 19/31] Update RELEASES.md Co-Authored-By: Jonas Schievink Co-Authored-By: Mazdak Farrokhzad --- RELEASES.md | 36 +++++++++++++++++++++++++----------- 1 file changed, 25 insertions(+), 11 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index 5d10e658f9015..2a2bcfb0ea247 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -3,9 +3,6 @@ Version 1.42.0 (2020-03-12) Language -------- -- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning - that you can create an enum that has the exact layout and ABI of the type - it contains. - [You can now use the slice pattern syntax with subslices.][67712] e.g. ```rust fn foo(words: &[&str]) { @@ -16,18 +13,34 @@ Language } } ``` - -- [Merge `TraitItem` & `ImplItem into `AssocItem`][67131] +- [You can now use `#[repr(transparent)]` on univariant `enum`s.][68122] Meaning + that you can create an enum that has the exact layout and ABI of the type + it contains. +- [There are some *syntax-only* changes:][67131] + - `default` is syntactically allowed before items in `trait` definitions. + - Items in `impl`s (i.e. `const`s, `type`s, and `fn`s) may syntactically + leave out their bodies in favor of `;`. + - Bounds on associated types in `impl`s are now syntactically allowed + (e.g. `type Foo: Ord;`). + - `...` (the C-variadic type) may occur syntactically directly as the type of + any function parameter. + + These are still rejected *semantically*, so you will likely receive an error + but these changes can be seen and parsed by procedural macros and + conditional compilation. Compiler -------- -- [Added tier 3\* support for `armv7a-none-eabi`.][68253] -- [Added tier 3 support for `riscv64gc-unknown-linux-gnu`.][68037] +- [Added tier 2\* support for `armv7a-none-eabi`.][68253] +- [Added tier 2 support for `riscv64gc-unknown-linux-gnu`.][68339] - [`Option::{expect,unwrap}` and `Result::{expect, expect_err, unwrap, unwrap_err}` now produce panic messages pointing to the location where they were called, rather than `core`'s internals. ][67887] +\* Refer to Rust's [platform support page][forge-platform-support] for more +information on Rust's tiered platform support. + Libraries --------- - [`iter::Empty` now implements `Send` and `Sync` for any `T`.][68348] @@ -40,14 +53,14 @@ Libraries Stabilized APIs --------------- +- [`CondVar::wait_while`] +- [`CondVar::wait_timeout_while`] - [`DebugMap::key`] - [`DebugMap::value`] - [`ManuallyDrop::take`] - [`matches!`] - [`ptr::slice_from_raw_parts_mut`] - [`ptr::slice_from_raw_parts`] -- [`wait_timeout_while`] -- [`wait_while`] Cargo ----- @@ -62,7 +75,7 @@ Compatibility Notes [68253]: https://github.com/rust-lang/rust/pull/68253/ [68348]: https://github.com/rust-lang/rust/pull/68348/ [67935]: https://github.com/rust-lang/rust/pull/67935/ -[68037]: https://github.com/rust-lang/rust/pull/68037/ +[68339]: https://github.com/rust-lang/rust/pull/68339/ [68122]: https://github.com/rust-lang/rust/pull/68122/ [67712]: https://github.com/rust-lang/rust/pull/67712/ [67887]: https://github.com/rust-lang/rust/pull/67887/ @@ -78,7 +91,8 @@ Compatibility Notes [`matches!`]: https://doc.rust-lang.org/stable/std/macro.matches.html [`ptr::slice_from_raw_parts_mut`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts_mut.html [`ptr::slice_from_raw_parts`]: https://doc.rust-lang.org/stable/std/ptr/fn.slice_from_raw_parts.html -[`wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while +[`CondVar::wait_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_while +[`CondVar::wait_timeout_while`]: https://doc.rust-lang.org/stable/std/sync/struct.Condvar.html#method.wait_timeout_while Version 1.41.0 (2020-01-30) From 01d932934748ef5c412c11a2ace18a504a7cb949 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2020 19:50:34 +0100 Subject: [PATCH 20/31] canonicalize alloc ID before calling tag_static_base_pointer --- src/librustc_mir/interpret/machine.rs | 2 ++ src/librustc_mir/interpret/memory.rs | 3 ++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 98a305ec2d92c..11d28ec582a88 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -253,6 +253,8 @@ pub trait Machine<'mir, 'tcx>: Sized { /// Return the "base" tag for the given *static* allocation: the one that is used for direct /// accesses to this static/const/fn allocation. If `id` is not a static allocation, /// this will return an unusable tag (i.e., accesses will be UB)! + /// + /// Expects `id` to be already canonical, if needed. fn tag_static_base_pointer(memory_extra: &Self::MemoryExtra, id: AllocId) -> Self::PointerTag; /// Executes a retagging operation diff --git a/src/librustc_mir/interpret/memory.rs b/src/librustc_mir/interpret/memory.rs index 048c5d7b15956..f60307e468bd2 100644 --- a/src/librustc_mir/interpret/memory.rs +++ b/src/librustc_mir/interpret/memory.rs @@ -150,7 +150,8 @@ impl<'mir, 'tcx, M: Machine<'mir, 'tcx>> Memory<'mir, 'tcx, M> { /// through a pointer that was created by the program. #[inline] pub fn tag_static_base_pointer(&self, ptr: Pointer) -> Pointer { - ptr.with_tag(M::tag_static_base_pointer(&self.extra, ptr.alloc_id)) + let id = M::canonical_alloc_id(self, ptr.alloc_id); + ptr.with_tag(M::tag_static_base_pointer(&self.extra, id)) } pub fn create_fn_alloc( From 9b62d60db18415caf3460b894e4f43f51da4f645 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 23 Feb 2020 22:39:57 +0100 Subject: [PATCH 21/31] fmt --- src/librustc_mir/interpret/machine.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/librustc_mir/interpret/machine.rs b/src/librustc_mir/interpret/machine.rs index 11d28ec582a88..69c9664b35156 100644 --- a/src/librustc_mir/interpret/machine.rs +++ b/src/librustc_mir/interpret/machine.rs @@ -219,10 +219,7 @@ pub trait Machine<'mir, 'tcx>: Sized { /// /// This function must be idempotent. #[inline] - fn canonical_alloc_id( - _mem: &Memory<'mir, 'tcx, Self>, - id: AllocId, - ) -> AllocId { + fn canonical_alloc_id(_mem: &Memory<'mir, 'tcx, Self>, id: AllocId) -> AllocId { id } From 162d72727ecfad4d75c2564f84abc73212aa7f27 Mon Sep 17 00:00:00 2001 From: Ana-Maria Date: Mon, 24 Feb 2020 15:51:08 +0000 Subject: [PATCH 22/31] Also blacklist powerpc-unknown-linux-musl. --- src/librustc/ty/layout.rs | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 753808bc25492..950234cc19b54 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -2541,14 +2541,15 @@ where }; let target = &cx.tcx().sess.target.target; + let target_env_gnu_like = matches!(&target.target_env[..], "gnu" | "musl"); let win_x64_gnu = target.target_os == "windows" && target.arch == "x86_64" && target.target_env == "gnu"; - let linux_s390x = - target.target_os == "linux" && target.arch == "s390x" && target.target_env == "gnu"; - let linux_sparc64 = - target.target_os == "linux" && target.arch == "sparc64" && target.target_env == "gnu"; - let linux_powerpc = - target.target_os == "linux" && target.arch == "powerpc" && target.target_env == "gnu"; + let linux_s390x_gnu_like = + target.target_os == "linux" && target.arch == "s390x" && target_env_gnu_like; + let linux_sparc64_gnu_like = + target.target_os == "linux" && target.arch == "sparc64" && target_env_gnu_like; + let linux_powerpc_gnu_like = + target.target_os == "linux" && target.arch == "powerpc" && target_env_gnu_like; let rust_abi = match sig.abi { RustIntrinsic | PlatformIntrinsic | Rust | RustCall => true, _ => false, @@ -2619,11 +2620,13 @@ where if arg.layout.is_zst() { // For some forsaken reason, x86_64-pc-windows-gnu // doesn't ignore zero-sized struct arguments. - // The same is true for s390x-unknown-linux-gnu, - // sparc64-unknown-linux-gnu and powerpc-unknown-linux-gnu. + // The same is true for {s390x,sparc64,powerpc}-unknown-linux-{gnu,musl}. if is_return || rust_abi - || (!win_x64_gnu && !linux_s390x && !linux_sparc64 && !linux_powerpc) + || (!win_x64_gnu + && !linux_s390x_gnu_like + && !linux_sparc64_gnu_like + && !linux_powerpc_gnu_like) { arg.mode = PassMode::Ignore; } From a66599f3a0d69478c5bb985caa42d054b5844d0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 24 Feb 2020 18:55:51 -0800 Subject: [PATCH 23/31] keep predicate order and tweak output --- src/librustc_typeck/check/method/suggest.rs | 16 +++++-- .../associated-const-no-item.stderr | 8 ++-- src/test/ui/auto-ref-slice-plus-ref.stderr | 32 ++++++++----- ...e-21659-show-relevant-trait-impls-3.stderr | 8 ++-- .../no-method-suggested-traits.stderr | 48 ++++++++++++------- .../option-as_deref.stderr | 2 +- .../option-as_deref_mut.stderr | 2 +- .../result-as_deref.stderr | 2 +- .../result-as_deref_err.stderr | 2 +- .../result-as_deref_mut.stderr | 2 +- .../result-as_deref_mut_err.stderr | 2 +- src/test/ui/issues/issue-57362-1.stderr | 8 ++-- src/test/ui/issues/issue-57362-2.stderr | 8 ++-- src/test/ui/never_type/issue-2149.stderr | 8 ++-- ...pecialization-trait-not-implemented.stderr | 8 ++-- ...issing-trait-bounds-for-method-call.stderr | 16 ++++--- src/test/ui/traits/trait-item-privacy.stderr | 24 ++++++---- .../trivial-bounds/trivial-bounds-leak.stderr | 8 ++-- src/test/ui/unique-object-noncopyable.stderr | 4 +- 19 files changed, 129 insertions(+), 79 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 9fcb1c75faeaa..f9b5ff8e2ab22 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -644,7 +644,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, }) }) - .collect::>(); + .enumerate() + .collect::>(); for ((span, empty_where), obligations) in type_params.into_iter() { err.span_suggestion_verbose( span, @@ -662,15 +663,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - bound_list.sort(); - bound_list.dedup(); // #35677 + bound_list.sort_by(|(_, a), (_, b)| a.cmp(&b)); // Sort alphabetically. + bound_list.dedup_by(|(_, a), (_, b)| a == b); // #35677 + bound_list.sort_by_key(|(pos, _)| *pos); // Keep the original predicate order. bound_spans.sort(); bound_spans.dedup(); for (span, msg) in bound_spans.into_iter() { err.span_label(span, &msg); } if !bound_list.is_empty() { - let bound_list = bound_list.join("\n"); + let bound_list = bound_list + .into_iter() + .map(|(_, path)| path) + .collect::>() + .join("\n"); err.note(&format!( "the method `{}` exists but the following trait bounds were not \ satisfied:\n{}", @@ -1095,7 +1101,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut use_note = true; if let [trait_info] = &candidates[..] { if let Some(span) = self.tcx.hir().span_if_local(trait_info.def_id) { - err.span_label( + err.span_note( self.tcx.sess.source_map().def_span(span), &format!( "`{}` defines an item `{}`, perhaps you need to {} it", diff --git a/src/test/ui/associated-const/associated-const-no-item.stderr b/src/test/ui/associated-const/associated-const-no-item.stderr index c3339e453e81e..fe27da5ac645f 100644 --- a/src/test/ui/associated-const/associated-const-no-item.stderr +++ b/src/test/ui/associated-const/associated-const-no-item.stderr @@ -1,13 +1,15 @@ error[E0599]: no associated item named `ID` found for type `i32` in the current scope --> $DIR/associated-const-no-item.rs:5:23 | -LL | trait Foo { - | --------- `Foo` defines an item `ID`, perhaps you need to implement it -... LL | const X: i32 = ::ID; | ^^ associated item not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `ID`, perhaps you need to implement it + --> $DIR/associated-const-no-item.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/auto-ref-slice-plus-ref.stderr b/src/test/ui/auto-ref-slice-plus-ref.stderr index 3500cef6c39bd..50ca5cad4bc68 100644 --- a/src/test/ui/auto-ref-slice-plus-ref.stderr +++ b/src/test/ui/auto-ref-slice-plus-ref.stderr @@ -3,44 +3,52 @@ error[E0599]: no method named `test_mut` found for struct `std::vec::Vec<{intege | LL | a.test_mut(); | ^^^^^^^^ help: there is a method with a similar name: `get_mut` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test_mut`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test_mut`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error[E0599]: no method named `test` found for struct `std::vec::Vec<{integer}>` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:8:7 | LL | a.test(); | ^^^^ method not found in `std::vec::Vec<{integer}>` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error[E0599]: no method named `test` found for array `[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:10:11 | LL | ([1]).test(); | ^^^^ method not found in `[{integer}; 1]` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error[E0599]: no method named `test` found for reference `&[{integer}; 1]` in the current scope --> $DIR/auto-ref-slice-plus-ref.rs:11:12 | LL | (&[1]).test(); | ^^^^ method not found in `&[{integer}; 1]` -... -LL | trait MyIter { - | ------------ `MyIter` defines an item `test`, perhaps you need to implement it | = help: items from traits can only be used if the trait is implemented and in scope +note: `MyIter` defines an item `test`, perhaps you need to implement it + --> $DIR/auto-ref-slice-plus-ref.rs:14:1 + | +LL | trait MyIter { + | ^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr index 75a2e9a99a994..64cce056a2688 100644 --- a/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr +++ b/src/test/ui/impl-trait/issues/issue-21659-show-relevant-trait-impls-3.stderr @@ -1,9 +1,6 @@ error[E0599]: no method named `foo` found for struct `Bar` in the current scope --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:20:8 | -LL | trait Foo { - | ------------ `Foo` defines an item `foo`, perhaps you need to implement it -... LL | struct Bar; | ----------- method `foo` not found for this ... @@ -11,6 +8,11 @@ LL | f1.foo(1usize); | ^^^ method not found in `Bar` | = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo`, perhaps you need to implement it + --> $DIR/issue-21659-show-relevant-trait-impls-3.rs:1:1 + | +LL | trait Foo { + | ^^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/impl-trait/no-method-suggested-traits.stderr b/src/test/ui/impl-trait/no-method-suggested-traits.stderr index c6017a5fea182..c0ca341385df5 100644 --- a/src/test/ui/impl-trait/no-method-suggested-traits.stderr +++ b/src/test/ui/impl-trait/no-method-suggested-traits.stderr @@ -122,68 +122,80 @@ LL | std::rc::Rc::new(&mut Box::new(&Foo)).method(); error[E0599]: no method named `method2` found for type `u64` in the current scope --> $DIR/no-method-suggested-traits.rs:45:10 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | 1u64.method2(); | ^^^^^^^ method not found in `u64` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&u64>>` in the current scope --> $DIR/no-method-suggested-traits.rs:47:44 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | std::rc::Rc::new(&mut Box::new(&1u64)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&u64>>` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `no_method_suggested_traits::Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:50:37 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | no_method_suggested_traits::Foo.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Foo` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` in the current scope --> $DIR/no-method-suggested-traits.rs:52:71 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Foo)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Foo>>` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for enum `no_method_suggested_traits::Bar` in the current scope --> $DIR/no-method-suggested-traits.rs:54:40 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | no_method_suggested_traits::Bar::X.method2(); | ^^^^^^^ method not found in `no_method_suggested_traits::Bar` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method2` found for struct `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` in the current scope --> $DIR/no-method-suggested-traits.rs:56:74 | -LL | pub trait Bar { - | ------------- `foo::Bar` defines an item `method2`, perhaps you need to implement it -... LL | std::rc::Rc::new(&mut Box::new(&no_method_suggested_traits::Bar::X)).method2(); | ^^^^^^^ method not found in `std::rc::Rc<&mut std::boxed::Box<&no_method_suggested_traits::Bar>>` | = help: items from traits can only be used if the trait is implemented and in scope +note: `foo::Bar` defines an item `method2`, perhaps you need to implement it + --> $DIR/no-method-suggested-traits.rs:8:5 + | +LL | pub trait Bar { + | ^^^^^^^^^^^^^ error[E0599]: no method named `method3` found for struct `Foo` in the current scope --> $DIR/no-method-suggested-traits.rs:59:9 diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr index 63359be56bf41..5db521536a804 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref.stderr @@ -5,8 +5,8 @@ LL | let _result = &Some(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr index b01b3448e17fd..f2133c8c84d21 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/option-as_deref_mut.stderr @@ -5,8 +5,8 @@ LL | let _result = &mut Some(42).as_deref_mut(); | ^^^^^^^^^^^^ method not found in `std::option::Option<{integer}>` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr index 754828419872b..2dfc6d53750e7 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref.stderr @@ -5,8 +5,8 @@ LL | let _result = &Ok(42).as_deref(); | ^^^^^^^^ help: there is a method with a similar name: `as_ref` | = note: the method `as_deref` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr index cf31bc4b56bf8..1d65c57e5e9ec 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_err.stderr @@ -5,8 +5,8 @@ LL | let _result = &Err(41).as_deref_err(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_err` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::Deref` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr index 586b35554553e..2f4bf0c94b5cb 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut.stderr @@ -5,8 +5,8 @@ LL | let _result = &mut Ok(42).as_deref_mut(); | ^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_err` | = note: the method `as_deref_mut` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr index fd0e43d7dbc15..b76d36c804e5f 100644 --- a/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr +++ b/src/test/ui/issues/issue-50264-inner-deref-trait/result-as_deref_mut_err.stderr @@ -5,8 +5,8 @@ LL | let _result = &mut Err(41).as_deref_mut_err(); | ^^^^^^^^^^^^^^^^ help: there is a method with a similar name: `as_deref_mut` | = note: the method `as_deref_mut_err` exists but the following trait bounds were not satisfied: - `<{integer} as std::ops::Deref>::Target = _` `{integer}: std::ops::DerefMut` + `<{integer} as std::ops::Deref>::Target = _` error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-1.stderr b/src/test/ui/issues/issue-57362-1.stderr index c48f51e2b2a20..5c611cd43d3cc 100644 --- a/src/test/ui/issues/issue-57362-1.stderr +++ b/src/test/ui/issues/issue-57362-1.stderr @@ -1,14 +1,16 @@ error[E0599]: no method named `f` found for fn pointer `fn(&u8)` in the current scope --> $DIR/issue-57362-1.rs:20:7 | -LL | trait Trait { - | ----------- `Trait` defines an item `f`, perhaps you need to implement it -... LL | a.f(); | ^ method not found in `fn(&u8)` | = note: `a` is a function, perhaps you wish to call it = help: items from traits can only be used if the trait is implemented and in scope +note: `Trait` defines an item `f`, perhaps you need to implement it + --> $DIR/issue-57362-1.rs:8:1 + | +LL | trait Trait { + | ^^^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/issues/issue-57362-2.stderr b/src/test/ui/issues/issue-57362-2.stderr index b3b30dbd1c889..2edc009746455 100644 --- a/src/test/ui/issues/issue-57362-2.stderr +++ b/src/test/ui/issues/issue-57362-2.stderr @@ -1,13 +1,15 @@ error[E0599]: no function or associated item named `make_g` found for fn pointer `for<'r> fn(&'r ())` in the current scope --> $DIR/issue-57362-2.rs:22:25 | -LL | trait X { - | ------- `X` defines an item `make_g`, perhaps you need to implement it -... LL | let x = ::make_g(); | ^^^^^^ function or associated item not found in `for<'r> fn(&'r ())` | = help: items from traits can only be used if the trait is implemented and in scope +note: `X` defines an item `make_g`, perhaps you need to implement it + --> $DIR/issue-57362-2.rs:8:1 + | +LL | trait X { + | ^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/never_type/issue-2149.stderr b/src/test/ui/never_type/issue-2149.stderr index 745126199663d..3cdd6372ec18c 100644 --- a/src/test/ui/never_type/issue-2149.stderr +++ b/src/test/ui/never_type/issue-2149.stderr @@ -9,13 +9,15 @@ LL | for elt in self { r = r + f(*elt); } error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope --> $DIR/issue-2149.rs:13:12 | -LL | trait VecMonad { - | ----------------- `VecMonad` defines an item `bind`, perhaps you need to implement it -... LL | ["hi"].bind(|x| [x] ); | ^^^^ method not found in `[&str; 1]` | = help: items from traits can only be used if the trait is implemented and in scope +note: `VecMonad` defines an item `bind`, perhaps you need to implement it + --> $DIR/issue-2149.rs:1:1 + | +LL | trait VecMonad { + | ^^^^^^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr index f4d29e61cc17e..a55d79ee03534 100644 --- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr +++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr @@ -1,9 +1,6 @@ error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope --> $DIR/specialization-trait-not-implemented.rs:22:29 | -LL | trait Foo { - | --------- `Foo` defines an item `foo_one`, perhaps you need to implement it -... LL | struct MyStruct; | ---------------- | | @@ -16,6 +13,11 @@ LL | println!("{}", MyStruct.foo_one()); = note: the method `foo_one` exists but the following trait bounds were not satisfied: `MyStruct: Foo` = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `foo_one`, perhaps you need to implement it + --> $DIR/specialization-trait-not-implemented.rs:7:1 + | +LL | trait Foo { + | ^^^^^^^^^ error: aborting due to previous error diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index 4f6620b47c268..1692af351f93c 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -4,9 +4,6 @@ error[E0599]: no method named `foo` found for reference `&Foo` in the current LL | struct Foo { | ------------- doesn't satisfy `Foo: Bar` ... -LL | trait Bar { - | --------- `Bar` defines an item `foo`, perhaps you need to implement it -... LL | self.foo(); | ^^^ method not found in `&Foo` | @@ -16,6 +13,11 @@ LL | self.foo(); `T: std::default::Default` which is required by `Foo: Bar` = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `foo`, perhaps you need to implement it + --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 + | +LL | trait Bar { + | ^^^^^^^^^ help: consider restricting the type parameters to satisfy the obligations | LL | struct Foo where T: Bar, T: std::default::Default { @@ -24,9 +26,6 @@ LL | struct Foo where T: Bar, T: std::default::Default { error[E0599]: no method named `foo` found for reference `&Fin` in the current scope --> $DIR/missing-trait-bounds-for-method-call.rs:27:14 | -LL | trait Bar { - | --------- `Bar` defines an item `foo`, perhaps you need to implement it -... LL | struct Fin where T: Bar { | -------------------------- doesn't satisfy `Fin: Bar` ... @@ -37,6 +36,11 @@ LL | self.foo(); `T: std::default::Default` which is required by `Fin: Bar` = help: items from traits can only be used if the trait is implemented and in scope +note: `Bar` defines an item `foo`, perhaps you need to implement it + --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 + | +LL | trait Bar { + | ^^^^^^^^^ help: consider restricting the type parameter to satisfy the obligation | LL | struct Fin where T: Bar, T: std::default::Default { diff --git a/src/test/ui/traits/trait-item-privacy.stderr b/src/test/ui/traits/trait-item-privacy.stderr index f893456a17cc0..2c0591c95f690 100644 --- a/src/test/ui/traits/trait-item-privacy.stderr +++ b/src/test/ui/traits/trait-item-privacy.stderr @@ -4,13 +4,15 @@ error[E0599]: no method named `a` found for struct `S` in the current scope LL | struct S; | --------- method `a` not found for this ... -LL | trait A { - | ------- `method::A` defines an item `a`, perhaps you need to implement it -... LL | S.a(); | ^ method not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/trait-item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ error[E0599]: no method named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:68:7 @@ -46,13 +48,15 @@ error[E0599]: no function or associated item named `a` found for struct `S` in t LL | struct S; | --------- function or associated item `a` not found for this ... -LL | trait A { - | ------- `method::A` defines an item `a`, perhaps you need to implement it -... LL | S::a(&S); | ^ function or associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope +note: `method::A` defines an item `a`, perhaps you need to implement it + --> $DIR/trait-item-privacy.rs:6:5 + | +LL | trait A { + | ^^^^^^^ error[E0599]: no function or associated item named `b` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:80:8 @@ -81,13 +85,15 @@ error[E0599]: no associated item named `A` found for struct `S` in the current s LL | struct S; | --------- associated item `A` not found for this ... -LL | trait A { - | ------- `assoc_const::A` defines an item `A`, perhaps you need to implement it -... LL | S::A; | ^ associated item not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope +note: `assoc_const::A` defines an item `A`, perhaps you need to implement it + --> $DIR/trait-item-privacy.rs:24:5 + | +LL | trait A { + | ^^^^^^^ error[E0599]: no associated item named `B` found for struct `S` in the current scope --> $DIR/trait-item-privacy.rs:98:8 diff --git a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr index ef41c0e5fa01d..4e153081d9fe9 100644 --- a/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr +++ b/src/test/ui/trivial-bounds/trivial-bounds-leak.stderr @@ -11,13 +11,15 @@ LL | fn cant_return_str() -> str { error[E0599]: no method named `test` found for type `i32` in the current scope --> $DIR/trivial-bounds-leak.rs:24:10 | -LL | pub trait Foo { - | ------------- `Foo` defines an item `test`, perhaps you need to implement it -... LL | 3i32.test(); | ^^^^ method not found in `i32` | = help: items from traits can only be used if the trait is implemented and in scope +note: `Foo` defines an item `test`, perhaps you need to implement it + --> $DIR/trivial-bounds-leak.rs:4:1 + | +LL | pub trait Foo { + | ^^^^^^^^^^^^^ error[E0277]: the trait bound `i32: Foo` is not satisfied --> $DIR/trivial-bounds-leak.rs:25:15 diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 6a0a6c87079f3..1c5fed2c33b4d 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -16,10 +16,10 @@ LL | pub struct Box(Unique); | ------------------------------------- doesn't satisfy `std::boxed::Box: std::clone::Clone` | = note: the method `clone` exists but the following trait bounds were not satisfied: - `dyn Foo: std::clone::Clone` - which is required by `std::boxed::Box: std::clone::Clone` `dyn Foo: std::marker::Sized` which is required by `std::boxed::Box: std::clone::Clone` + `dyn Foo: std::clone::Clone` + which is required by `std::boxed::Box: std::clone::Clone` = help: items from traits can only be used if the trait is implemented and in scope = note: the following trait defines an item `clone`, perhaps you need to implement it: candidate #1: `std::clone::Clone` From c02de78ca03219713eb8979f712b2e3252df8c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 24 Feb 2020 23:25:54 -0800 Subject: [PATCH 24/31] Reduce verbosity when suggesting restricting type params --- src/librustc_typeck/check/method/suggest.rs | 4 +++- .../missing-trait-bounds-for-method-call.stderr | 12 ------------ 2 files changed, 3 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index f9b5ff8e2ab22..55b15925bf756 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -535,6 +535,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { report_candidates(span, &mut err, static_sources, sugg_span); } + let mut restrict_type_params = false; if !unsatisfied_predicates.is_empty() { let def_span = |def_id| self.tcx.sess.source_map().def_span(self.tcx.def_span(def_id)); @@ -647,6 +648,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .enumerate() .collect::>(); for ((span, empty_where), obligations) in type_params.into_iter() { + restrict_type_params = true; err.span_suggestion_verbose( span, &format!( @@ -685,7 +687,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - if actual.is_numeric() && actual.is_fresh() { + if actual.is_numeric() && actual.is_fresh() || restrict_type_params { } else { self.suggest_traits_to_import( &mut err, diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index 1692af351f93c..a9b57cfc0bd2d 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -12,12 +12,6 @@ LL | self.foo(); which is required by `Foo: Bar` `T: std::default::Default` which is required by `Foo: Bar` - = help: items from traits can only be used if the trait is implemented and in scope -note: `Bar` defines an item `foo`, perhaps you need to implement it - --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 - | -LL | trait Bar { - | ^^^^^^^^^ help: consider restricting the type parameters to satisfy the obligations | LL | struct Foo where T: Bar, T: std::default::Default { @@ -35,12 +29,6 @@ LL | self.foo(); = note: the method `foo` exists but the following trait bounds were not satisfied: `T: std::default::Default` which is required by `Fin: Bar` - = help: items from traits can only be used if the trait is implemented and in scope -note: `Bar` defines an item `foo`, perhaps you need to implement it - --> $DIR/missing-trait-bounds-for-method-call.rs:6:1 - | -LL | trait Bar { - | ^^^^^^^^^ help: consider restricting the type parameter to satisfy the obligation | LL | struct Fin where T: Bar, T: std::default::Default { From 01734905f8989951d13c16362ce54598906d4759 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Feb 2020 12:08:22 -0800 Subject: [PATCH 25/31] Reword message --- src/librustc_typeck/check/method/suggest.rs | 4 ++-- .../suggestions/missing-trait-bounds-for-method-call.stderr | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 55b15925bf756..5528895ad0389 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -497,7 +497,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if !static_sources.is_empty() { err.note( "found the following associated functions; to be used as methods, \ - functions must have a `self` parameter", + functions must have a `self` parameter", ); err.span_label(span, "this is an associated function, not a method"); } @@ -653,7 +653,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, &format!( "consider restricting the type parameter{s} to satisfy the \ - obligation{s}", + trait bound{s}", s = pluralize!(obligations.len()) ), format!( diff --git a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr index a9b57cfc0bd2d..c6d94826c0c86 100644 --- a/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr +++ b/src/test/ui/suggestions/missing-trait-bounds-for-method-call.stderr @@ -12,7 +12,7 @@ LL | self.foo(); which is required by `Foo: Bar` `T: std::default::Default` which is required by `Foo: Bar` -help: consider restricting the type parameters to satisfy the obligations +help: consider restricting the type parameters to satisfy the trait bounds | LL | struct Foo where T: Bar, T: std::default::Default { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | self.foo(); = note: the method `foo` exists but the following trait bounds were not satisfied: `T: std::default::Default` which is required by `Fin: Bar` -help: consider restricting the type parameter to satisfy the obligation +help: consider restricting the type parameter to satisfy the trait bound | LL | struct Fin where T: Bar, T: std::default::Default { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ From c02e56a9003624e87bad8b4a93703be030e03aed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 25 Feb 2020 12:10:48 -0800 Subject: [PATCH 26/31] Do not suggest implementing traits if present in predicates --- src/librustc_typeck/check/method/suggest.rs | 10 +++++++++- src/test/ui/methods/method-call-err-msg.stderr | 5 ++--- src/test/ui/union/union-derive-clone.stderr | 3 --- src/test/ui/unique-object-noncopyable.stderr | 3 --- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs index 5528895ad0389..44f87319ebf4f 100644 --- a/src/librustc_typeck/check/method/suggest.rs +++ b/src/librustc_typeck/check/method/suggest.rs @@ -696,6 +696,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name, source, out_of_scope_traits, + &unsatisfied_predicates, ); } @@ -895,6 +896,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { item_name: ast::Ident, source: SelfSource<'b>, valid_out_of_scope_traits: Vec, + unsatisfied_predicates: &[(ty::Predicate<'tcx>, Option>)], ) { if self.suggest_valid_traits(err, valid_out_of_scope_traits) { return; @@ -915,7 +917,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // this isn't perfect (that is, there are cases when // implementing a trait would be legal but is rejected // here). - (type_is_local || info.def_id.is_local()) + !unsatisfied_predicates.iter().any(|(p, _)| match p { + // Hide traits if they are present in predicates as they can be fixed without + // having to implement them. + ty::Predicate::Trait(t, _) => t.def_id() != info.def_id, + ty::Predicate::Projection(p) => p.item_def_id() != info.def_id, + _ => true, + }) && (type_is_local || info.def_id.is_local()) && self .associated_item(info.def_id, item_name, Namespace::ValueNS) .filter(|item| { diff --git a/src/test/ui/methods/method-call-err-msg.stderr b/src/test/ui/methods/method-call-err-msg.stderr index ecb6950615748..4678642dd6d0c 100644 --- a/src/test/ui/methods/method-call-err-msg.stderr +++ b/src/test/ui/methods/method-call-err-msg.stderr @@ -47,9 +47,8 @@ LL | .take() `Foo: std::iter::Iterator` which is required by `&mut Foo: std::iter::Iterator` = help: items from traits can only be used if the trait is implemented and in scope - = note: the following traits define an item `take`, perhaps you need to implement one of them: - candidate #1: `std::io::Read` - candidate #2: `std::iter::Iterator` + = note: the following trait defines an item `take`, perhaps you need to implement it: + candidate #1: `std::iter::Iterator` error[E0061]: this function takes 3 arguments but 0 arguments were supplied --> $DIR/method-call-err-msg.rs:21:7 diff --git a/src/test/ui/union/union-derive-clone.stderr b/src/test/ui/union/union-derive-clone.stderr index fdf2393656e12..01c8e8471aac2 100644 --- a/src/test/ui/union/union-derive-clone.stderr +++ b/src/test/ui/union/union-derive-clone.stderr @@ -25,9 +25,6 @@ LL | let w = u.clone(); = note: the method `clone` exists but the following trait bounds were not satisfied: `CloneNoCopy: std::marker::Copy` which is required by `U5: std::clone::Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `std::clone::Clone` error: aborting due to 2 previous errors diff --git a/src/test/ui/unique-object-noncopyable.stderr b/src/test/ui/unique-object-noncopyable.stderr index 1c5fed2c33b4d..286008188fceb 100644 --- a/src/test/ui/unique-object-noncopyable.stderr +++ b/src/test/ui/unique-object-noncopyable.stderr @@ -20,9 +20,6 @@ LL | pub struct Box(Unique); which is required by `std::boxed::Box: std::clone::Clone` `dyn Foo: std::clone::Clone` which is required by `std::boxed::Box: std::clone::Clone` - = help: items from traits can only be used if the trait is implemented and in scope - = note: the following trait defines an item `clone`, perhaps you need to implement it: - candidate #1: `std::clone::Clone` error: aborting due to previous error From e6c85960d164c5f1e30ae9d18002c3e9d435fc46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 27 Feb 2020 15:59:08 -0800 Subject: [PATCH 27/31] Revert "Backport only: avoid ICE on bad placeholder type" This reverts commit 1cb555a1dc809a8d310354678ef9c43f01e41ad4. --- src/librustc_typeck/collect.rs | 2 +- src/test/ui/did_you_mean/bad-assoc-ty.rs | 1 - src/test/ui/did_you_mean/bad-assoc-ty.stderr | 26 +- src/test/ui/self/self-infer.rs | 2 - src/test/ui/self/self-infer.stderr | 16 +- .../ui/typeck/typeck_type_placeholder_item.rs | 34 -- .../typeck_type_placeholder_item.stderr | 316 +++--------------- 7 files changed, 68 insertions(+), 329 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 1fade1b5ca65e..6c4e9ecee1c39 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -320,7 +320,7 @@ impl AstConv<'tcx> for ItemCtxt<'tcx> { } fn ty_infer(&self, _: Option<&ty::GenericParamDef>, span: Span) -> Ty<'tcx> { - placeholder_type_error(self.tcx(), span, &[], vec![span], false); + self.tcx().sess.delay_span_bug(span, "bad placeholder type"); self.tcx().types.err } diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index f02931eeb6fc3..fccfb7911cecf 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -17,7 +17,6 @@ type D = (u8, u8)::AssocTy; type E = _::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures type F = &'static (u8)::AssocTy; //~^ ERROR missing angle brackets in associated item path diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index d5b2abf2f8b50..64e49934d8762 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -29,25 +29,25 @@ LL | type E = _::AssocTy; | ^^^^^^^^^^ help: try: `<_>::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:22:19 + --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ help: try: `<(u8)>::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:28:10 + --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:45:10 + --> $DIR/bad-assoc-ty.rs:44:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: try: `::AssocTy` error: missing angle brackets in associated item path - --> $DIR/bad-assoc-ty.rs:38:19 + --> $DIR/bad-assoc-ty.rs:37:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ help: try: `<$ty>::AssocTy` @@ -87,32 +87,26 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa LL | type E = _::AssocTy; | ^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/bad-assoc-ty.rs:17:10 - | -LL | type E = _::AssocTy; - | ^ not allowed in type signatures - error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:22:19 + --> $DIR/bad-assoc-ty.rs:21:19 | LL | type F = &'static (u8)::AssocTy; | ^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:28:10 + --> $DIR/bad-assoc-ty.rs:27:10 | LL | type G = dyn 'static + (Send)::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::marker::Send + 'static) as Trait>::AssocTy` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:34:10 + --> $DIR/bad-assoc-ty.rs:33:10 | LL | type H = Fn(u8) -> (u8)::Output; | ^^^^^^^^^^^^^^^^^^^^^^ help: use fully-qualified syntax: `<(dyn std::ops::Fn(u8) -> u8 + 'static) as Trait>::Output` error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:38:19 + --> $DIR/bad-assoc-ty.rs:37:19 | LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` @@ -123,12 +117,12 @@ LL | type J = ty!(u8); = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info) error[E0223]: ambiguous associated type - --> $DIR/bad-assoc-ty.rs:45:10 + --> $DIR/bad-assoc-ty.rs:44:10 | LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error: aborting due to 20 previous errors +error: aborting due to 19 previous errors Some errors have detailed explanations: E0121, E0223. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/self/self-infer.rs b/src/test/ui/self/self-infer.rs index 77c80521236a0..0956f2a56918c 100644 --- a/src/test/ui/self/self-infer.rs +++ b/src/test/ui/self/self-infer.rs @@ -2,9 +2,7 @@ struct S; impl S { fn f(self: _) {} //~ERROR the type placeholder `_` is not allowed within types on item sig - //~^ ERROR the type placeholder `_` is not allowed within types on item sig fn g(self: &_) {} //~ERROR the type placeholder `_` is not allowed within types on item sig - //~^ ERROR the type placeholder `_` is not allowed within types on item sig } fn main() {} diff --git a/src/test/ui/self/self-infer.stderr b/src/test/ui/self/self-infer.stderr index d6bf8b44d6099..1475b212b56a6 100644 --- a/src/test/ui/self/self-infer.stderr +++ b/src/test/ui/self/self-infer.stderr @@ -1,9 +1,3 @@ -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:4:16 - | -LL | fn f(self: _) {} - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/self-infer.rs:4:16 | @@ -16,13 +10,7 @@ LL | fn f(self: T) {} | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:6:17 - | -LL | fn g(self: &_) {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/self-infer.rs:6:17 + --> $DIR/self-infer.rs:5:17 | LL | fn g(self: &_) {} | ^ not allowed in type signatures @@ -32,6 +20,6 @@ help: use type parameters instead LL | fn g(self: &T) {} | ^^^ ^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index eb6cc832fb417..86c7c52b27166 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -19,24 +19,19 @@ static TEST5: (_, _) = (1, 2); fn test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test6_b(_: _, _: T) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test6_c(_: _, _: (T, K, L, A, B)) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Test9; @@ -46,7 +41,6 @@ impl Test9 { fn test10(&self, _x : _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn test11(x: &usize) -> &_ { @@ -65,16 +59,12 @@ impl Clone for Test9 { fn clone_from(&mut self, other: _) { *self = Test9; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct Test10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } pub fn main() { @@ -102,16 +92,13 @@ pub fn main() { fn fn_test6(_: _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test7(x: _) { let _x: usize = x; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn fn_test8(_f: fn() -> _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures //~| ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures struct FnTest9; @@ -121,7 +108,6 @@ pub fn main() { fn fn_test10(&self, _x : _) { } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } impl Clone for FnTest9 { @@ -130,16 +116,12 @@ pub fn main() { fn clone_from(&mut self, other: _) { *self = FnTest9; } //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct FnTest10 { a: _, //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures b: (_, _), - //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } fn fn_test11(_: _) -> (_, _) { panic!() } @@ -156,40 +138,28 @@ pub fn main() { trait T { fn method_test1(&self, x: _); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn method_test2(&self, x: _) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn method_test3(&self) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test1(x: _); //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test2(x: _) -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures fn assoc_fn_test3() -> _; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures - //~| ERROR the type placeholder `_` is not allowed within types on item signatures } struct BadStruct<_>(_); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -198,22 +168,18 @@ struct BadStruct1<_, _>(_); //~| ERROR expected identifier, found reserved identifier `_` //~| ERROR the name `_` is already used //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct BadStruct2<_, T>(_, T); //~^ ERROR expected identifier, found reserved identifier `_` //~| ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures -//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index a8fdd66ee3753..95e8f94c6f3e7 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -1,35 +1,35 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:179:18 + --> $DIR/typeck_type_placeholder_item.rs:153:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:183:16 + --> $DIR/typeck_type_placeholder_item.rs:156:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:196:19 + --> $DIR/typeck_type_placeholder_item.rs:166:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:196:22 + --> $DIR/typeck_type_placeholder_item.rs:166:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:202:19 + --> $DIR/typeck_type_placeholder_item.rs:171:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:196:22 + --> $DIR/typeck_type_placeholder_item.rs:166:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -79,12 +79,6 @@ error[E0121]: the type placeholder `_` is not allowed within types on item signa LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:20:13 - | -LL | fn test6(_: _) { } - | ^ not allowed in type signatures - error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:20:13 | @@ -97,13 +91,7 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:24:18 - | -LL | fn test6_b(_: _, _: T) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:24:18 + --> $DIR/typeck_type_placeholder_item.rs:23:18 | LL | fn test6_b(_: _, _: T) { } | ^ not allowed in type signatures @@ -114,13 +102,7 @@ LL | fn test6_b(_: K, _: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:28:30 - | -LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:28:30 + --> $DIR/typeck_type_placeholder_item.rs:26:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } | ^ not allowed in type signatures @@ -131,13 +113,7 @@ LL | fn test6_c(_: C, _: (T, K, L, A, B)) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:13 - | -LL | fn test7(x: _) { let _x: usize = x; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:13 + --> $DIR/typeck_type_placeholder_item.rs:29:13 | LL | fn test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -148,19 +124,13 @@ LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:22 + --> $DIR/typeck_type_placeholder_item.rs:32:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:22 - | -LL | fn test8(_f: fn() -> _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:36:22 + --> $DIR/typeck_type_placeholder_item.rs:32:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -171,61 +141,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:72:8 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:9 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:12 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:137:12 - | -LL | a: _, - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:140:13 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:140:16 - | -LL | b: (_, _), - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:21 - | -LL | struct BadStruct<_>(_); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:196:25 - | -LL | struct BadStruct1<_, _>(_); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:202:25 - | -LL | struct BadStruct2<_, T>(_, T); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:52:26 + --> $DIR/typeck_type_placeholder_item.rs:46:26 | LL | fn test11(x: &usize) -> &_ { | -^ @@ -234,7 +150,7 @@ LL | fn test11(x: &usize) -> &_ { | help: replace with the correct return type: `&&usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:57:52 + --> $DIR/typeck_type_placeholder_item.rs:51:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { | --------------^ @@ -243,11 +159,11 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | help: replace with the correct return type: `*const *const usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:72:8 + --> $DIR/typeck_type_placeholder_item.rs:65:8 | LL | a: _, | ^ not allowed in type signatures -... +LL | LL | b: (_, _), | ^ ^ not allowed in type signatures | | @@ -258,18 +174,17 @@ help: use type parameters instead LL | struct Test10 { LL | a: T, LL | -LL | LL | b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:81:12 + --> $DIR/typeck_type_placeholder_item.rs:71:12 | LL | static A = 42; | ^ help: provide a type for the item: `A: i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:83:15 + --> $DIR/typeck_type_placeholder_item.rs:73:15 | LL | static B: _ = 42; | ^ @@ -278,13 +193,13 @@ LL | static B: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:85:15 + --> $DIR/typeck_type_placeholder_item.rs:75:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:88:21 + --> $DIR/typeck_type_placeholder_item.rs:78:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -293,7 +208,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:91:23 + --> $DIR/typeck_type_placeholder_item.rs:81:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -303,7 +218,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:94:22 + --> $DIR/typeck_type_placeholder_item.rs:84:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -312,7 +227,7 @@ LL | static FN_TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:97:22 + --> $DIR/typeck_type_placeholder_item.rs:87:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -321,19 +236,13 @@ LL | static FN_TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:100:22 + --> $DIR/typeck_type_placeholder_item.rs:90:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:103:20 - | -LL | fn fn_test6(_: _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:103:20 + --> $DIR/typeck_type_placeholder_item.rs:93:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -344,13 +253,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:107:20 - | -LL | fn fn_test7(x: _) { let _x: usize = x; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:107:20 + --> $DIR/typeck_type_placeholder_item.rs:96:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -361,19 +264,13 @@ LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 - | -LL | fn fn_test8(_f: fn() -> _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 + --> $DIR/typeck_type_placeholder_item.rs:99:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:111:29 + --> $DIR/typeck_type_placeholder_item.rs:99:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -384,11 +281,11 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:137:12 + --> $DIR/typeck_type_placeholder_item.rs:122:12 | LL | a: _, | ^ not allowed in type signatures -... +LL | LL | b: (_, _), | ^ ^ not allowed in type signatures | | @@ -399,18 +296,17 @@ help: use type parameters instead LL | struct FnTest10 { LL | a: T, LL | -LL | LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:145:18 + --> $DIR/typeck_type_placeholder_item.rs:127:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:145:28 + --> $DIR/typeck_type_placeholder_item.rs:127:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures @@ -418,7 +314,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:149:30 + --> $DIR/typeck_type_placeholder_item.rs:131:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -428,7 +324,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:152:33 + --> $DIR/typeck_type_placeholder_item.rs:134:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -437,7 +333,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:179:21 + --> $DIR/typeck_type_placeholder_item.rs:153:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -448,19 +344,7 @@ LL | struct BadStruct(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:32 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:15 - | -LL | impl BadTrait<_> for BadStruct<_> {} - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:15 + --> $DIR/typeck_type_placeholder_item.rs:158:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -473,13 +357,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:190:34 + --> $DIR/typeck_type_placeholder_item.rs:161:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:196:25 + --> $DIR/typeck_type_placeholder_item.rs:166:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -490,7 +374,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:202:25 + --> $DIR/typeck_type_placeholder_item.rs:171:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -501,25 +385,13 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:207:14 + --> $DIR/typeck_type_placeholder_item.rs:175:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:207:14 - | -LL | type X = Box<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:47:27 - | -LL | fn test10(&self, _x : _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:47:27 + --> $DIR/typeck_type_placeholder_item.rs:42:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -530,13 +402,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:157:31 - | -LL | fn method_test1(&self, x: _); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:157:31 + --> $DIR/typeck_type_placeholder_item.rs:139:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -547,19 +413,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:160:37 - | -LL | fn method_test2(&self, x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:160:31 - | -LL | fn method_test2(&self, x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:160:31 + --> $DIR/typeck_type_placeholder_item.rs:141:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -572,13 +426,7 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:31 - | -LL | fn method_test3(&self) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:164:31 + --> $DIR/typeck_type_placeholder_item.rs:143:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -589,13 +437,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:167:26 - | -LL | fn assoc_fn_test1(x: _); - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:167:26 + --> $DIR/typeck_type_placeholder_item.rs:145:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -606,19 +448,7 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:32 - | -LL | fn assoc_fn_test2(x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:26 - | -LL | fn assoc_fn_test2(x: _) -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:170:26 + --> $DIR/typeck_type_placeholder_item.rs:147:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -631,13 +461,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:174:28 - | -LL | fn assoc_fn_test3() -> _; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:174:28 + --> $DIR/typeck_type_placeholder_item.rs:149:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -648,13 +472,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:66:37 - | -LL | fn clone_from(&mut self, other: _) { *self = Test9; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:66:37 + --> $DIR/typeck_type_placeholder_item.rs:60:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -665,13 +483,7 @@ LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:34 - | -LL | fn fn_test10(&self, _x : _) { } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:34 + --> $DIR/typeck_type_placeholder_item.rs:109:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -682,13 +494,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:41 - | -LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:41 + --> $DIR/typeck_type_placeholder_item.rs:117:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -699,25 +505,13 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:190:34 - | -LL | fn impl_trait() -> impl BadTrait<_> { - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:214:21 - | -LL | type Y = impl Trait<_>; - | ^ not allowed in type signatures - -error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:214:21 + --> $DIR/typeck_type_placeholder_item.rs:181:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:44:24 + --> $DIR/typeck_type_placeholder_item.rs:39:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -726,7 +520,7 @@ LL | fn test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:63:24 + --> $DIR/typeck_type_placeholder_item.rs:57:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -735,7 +529,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace with the correct return type: `Test9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:119:31 + --> $DIR/typeck_type_placeholder_item.rs:106:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -744,7 +538,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:128:28 + --> $DIR/typeck_type_placeholder_item.rs:114:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -752,7 +546,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 92 previous errors +error: aborting due to 58 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From a7b727dab3aff466fc88c3ce0916817dc2d093bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Feb 2020 13:34:00 -0800 Subject: [PATCH 28/31] Account for bounds when denying `_` in type parameters --- src/librustc_typeck/astconv.rs | 22 +++++++- src/test/ui/did_you_mean/bad-assoc-ty.rs | 4 ++ src/test/ui/did_you_mean/bad-assoc-ty.stderr | 10 +++- .../ui/typeck/typeck_type_placeholder_item.rs | 5 ++ .../typeck_type_placeholder_item.stderr | 50 +++++++++++++++---- 5 files changed, 78 insertions(+), 13 deletions(-) diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 49f38d86d9161..d1a6163df2d0e 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -514,7 +514,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self_ty: Option>, arg_count_correct: bool, args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool), - provided_kind: impl Fn(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, + mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>, mut inferred_kind: impl FnMut( Option<&[subst::GenericArg<'tcx>]>, &GenericParamDef, @@ -751,6 +751,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { }; let mut missing_type_params = vec![]; + let mut inferred_params = vec![]; let substs = Self::create_substs_for_generic_args( tcx, def_id, @@ -773,7 +774,12 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { self.ast_region_to_region(<, Some(param)).into() } (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { - self.ast_ty_to_ty(&ty).into() + if let (hir::TyKind::Infer, false) = (&ty.kind, self.allow_ty_infer()) { + inferred_params.push(ty.span); + tcx.types.err.into() + } else { + self.ast_ty_to_ty(&ty).into() + } } (GenericParamDefKind::Const, GenericArg::Const(ct)) => { self.ast_const_to_const(&ct.value, tcx.type_of(param.def_id)).into() @@ -832,6 +838,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o { } }, ); + if !inferred_params.is_empty() { + // We always collect the spans for placeholder types when evaluating `fn`s, but we + // only want to emit an error complaining about them if infer types (`_`) are not + // allowed. `allow_ty_infer` gates this behavior. + crate::collect::placeholder_type_error( + tcx, + inferred_params[0], + &[], + inferred_params, + false, + ); + } self.complain_about_missing_type_params( missing_type_params, diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.rs b/src/test/ui/did_you_mean/bad-assoc-ty.rs index fccfb7911cecf..00845a17b116b 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.rs +++ b/src/test/ui/did_you_mean/bad-assoc-ty.rs @@ -45,4 +45,8 @@ type I = ty!()::AssocTy; //~^ ERROR missing angle brackets in associated item path //~| ERROR ambiguous associated type +trait K {} +fn foo>(x: X) {} +//~^ ERROR the type placeholder `_` is not allowed within types on item signatures + fn main() {} diff --git a/src/test/ui/did_you_mean/bad-assoc-ty.stderr b/src/test/ui/did_you_mean/bad-assoc-ty.stderr index 64e49934d8762..6d5f3d9f14348 100644 --- a/src/test/ui/did_you_mean/bad-assoc-ty.stderr +++ b/src/test/ui/did_you_mean/bad-assoc-ty.stderr @@ -122,7 +122,15 @@ error[E0223]: ambiguous associated type LL | type I = ty!()::AssocTy; | ^^^^^^^^^^^^^^ help: use fully-qualified syntax: `::AssocTy` -error: aborting due to 19 previous errors +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/bad-assoc-ty.rs:49:13 + | +LL | fn foo>(x: X) {} + | ^ ^ not allowed in type signatures + | | + | not allowed in type signatures + +error: aborting due to 20 previous errors Some errors have detailed explanations: E0121, E0223. For more information about an error, try `rustc --explain E0121`. diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 86c7c52b27166..8ee46343d2d5f 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -157,9 +157,12 @@ trait BadTrait<_> {} //~^ ERROR expected identifier, found reserved identifier `_` impl BadTrait<_> for BadStruct<_> {} //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn impl_trait() -> impl BadTrait<_> { //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures unimplemented!() } @@ -174,12 +177,14 @@ struct BadStruct2<_, T>(_, T); type X = Box<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures struct Struct; trait Trait {} impl Trait for Struct {} type Y = impl Trait<_>; //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +//~| ERROR the type placeholder `_` is not allowed within types on item signatures fn foo() -> Y { Struct } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 95e8f94c6f3e7..18317d2b9748a 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -11,25 +11,25 @@ LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:19 + --> $DIR/typeck_type_placeholder_item.rs:169:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:169:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:171:19 + --> $DIR/typeck_type_placeholder_item.rs:174:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:166:22 + --> $DIR/typeck_type_placeholder_item.rs:169:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -343,6 +343,18 @@ help: use type parameters instead LL | struct BadStruct(T); | ^ ^ +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:158:32 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:158:15 + | +LL | impl BadTrait<_> for BadStruct<_> {} + | ^ not allowed in type signatures + error[E0121]: the type placeholder `_` is not allowed within types on item signatures --> $DIR/typeck_type_placeholder_item.rs:158:15 | @@ -357,13 +369,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:161:34 + --> $DIR/typeck_type_placeholder_item.rs:163:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:166:25 + --> $DIR/typeck_type_placeholder_item.rs:169:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -374,7 +386,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:171:25 + --> $DIR/typeck_type_placeholder_item.rs:174:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -385,7 +397,13 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:175:14 + --> $DIR/typeck_type_placeholder_item.rs:178:14 + | +LL | type X = Box<_>; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:178:14 | LL | type X = Box<_>; | ^ not allowed in type signatures @@ -505,7 +523,19 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:181:21 + --> $DIR/typeck_type_placeholder_item.rs:163:34 + | +LL | fn impl_trait() -> impl BadTrait<_> { + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:185:21 + | +LL | type Y = impl Trait<_>; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:185:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures @@ -546,7 +576,7 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 58 previous errors +error: aborting due to 63 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From c6cfcf999a53e5656f412c64f5e97e7a4840e072 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 17 Feb 2020 12:07:50 -0800 Subject: [PATCH 29/31] Account for associated items when denying `_` --- src/librustc_typeck/collect.rs | 34 +++- .../ui/typeck/typeck_type_placeholder_item.rs | 25 ++- .../typeck_type_placeholder_item.stderr | 184 ++++++++++++------ 3 files changed, 170 insertions(+), 73 deletions(-) diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 6c4e9ecee1c39..f257fc5442cc1 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -715,13 +715,21 @@ fn convert_trait_item(tcx: TyCtxt<'_>, trait_item_id: hir::HirId) { tcx.generics_of(def_id); match trait_item.kind { - hir::TraitItemKind::Const(..) - | hir::TraitItemKind::Type(_, Some(_)) - | hir::TraitItemKind::Method(..) => { + hir::TraitItemKind::Method(..) => { tcx.type_of(def_id); - if let hir::TraitItemKind::Method(..) = trait_item.kind { - tcx.fn_sig(def_id); - } + tcx.fn_sig(def_id); + } + + hir::TraitItemKind::Const(.., Some(_)) => { + tcx.type_of(def_id); + } + + hir::TraitItemKind::Const(..) | hir::TraitItemKind::Type(_, Some(_)) => { + tcx.type_of(def_id); + // Account for `const C: _;` and `type T = _;`. + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_trait_item(trait_item); + placeholder_type_error(tcx, DUMMY_SP, &[], visitor.0, false); } hir::TraitItemKind::Type(_, None) => {} @@ -735,8 +743,18 @@ fn convert_impl_item(tcx: TyCtxt<'_>, impl_item_id: hir::HirId) { tcx.generics_of(def_id); tcx.type_of(def_id); tcx.predicates_of(def_id); - if let hir::ImplItemKind::Method(..) = tcx.hir().expect_impl_item(impl_item_id).kind { - tcx.fn_sig(def_id); + let impl_item = tcx.hir().expect_impl_item(impl_item_id); + match impl_item.kind { + hir::ImplItemKind::Method(..) => { + tcx.fn_sig(def_id); + } + hir::ImplItemKind::TyAlias(_) | hir::ImplItemKind::OpaqueTy(_) => { + // Account for `type T = _;` + let mut visitor = PlaceholderHirTyCollector::default(); + visitor.visit_impl_item(impl_item); + placeholder_type_error(tcx, DUMMY_SP, &[], visitor.0, false); + } + hir::ImplItemKind::Const(..) => {} } } diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.rs b/src/test/ui/typeck/typeck_type_placeholder_item.rs index 8ee46343d2d5f..6cd2b8c75b639 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.rs +++ b/src/test/ui/typeck/typeck_type_placeholder_item.rs @@ -1,4 +1,5 @@ -#![feature(type_alias_impl_trait)] // Needed for single test `type Y = impl Trait<_>` +// Needed for `type Y = impl Trait<_>` and `type B = _;` +#![feature(type_alias_impl_trait, associated_type_defaults)] // This test checks that it is not possible to enable global type // inference by using the `_` type placeholder. @@ -188,3 +189,25 @@ type Y = impl Trait<_>; fn foo() -> Y { Struct } + +trait Qux { + type A; + type B = _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + const C: _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + const D: _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + // type E: _; // FIXME: make the parser propagate the existence of `B` +} +impl Qux for Struct { + type A = _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + type B = _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + const C: _; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures + //~| ERROR associated constant in `impl` without body + const D: _ = 42; + //~^ ERROR the type placeholder `_` is not allowed within types on item signatures +} diff --git a/src/test/ui/typeck/typeck_type_placeholder_item.stderr b/src/test/ui/typeck/typeck_type_placeholder_item.stderr index 18317d2b9748a..f2d02f70f4a66 100644 --- a/src/test/ui/typeck/typeck_type_placeholder_item.stderr +++ b/src/test/ui/typeck/typeck_type_placeholder_item.stderr @@ -1,35 +1,43 @@ error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:153:18 + --> $DIR/typeck_type_placeholder_item.rs:154:18 | LL | struct BadStruct<_>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:156:16 + --> $DIR/typeck_type_placeholder_item.rs:157:16 | LL | trait BadTrait<_> {} | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:169:19 + --> $DIR/typeck_type_placeholder_item.rs:170:19 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:169:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | ^ expected identifier, found reserved identifier error: expected identifier, found reserved identifier `_` - --> $DIR/typeck_type_placeholder_item.rs:174:19 + --> $DIR/typeck_type_placeholder_item.rs:175:19 | LL | struct BadStruct2<_, T>(_, T); | ^ expected identifier, found reserved identifier +error: associated constant in `impl` without body + --> $DIR/typeck_type_placeholder_item.rs:208:5 + | +LL | const C: _; + | ^^^^^^^^^^- + | | + | help: provide a definition for the constant: `= ;` + error[E0403]: the name `_` is already used for a generic parameter in this item's generic parameters - --> $DIR/typeck_type_placeholder_item.rs:169:22 + --> $DIR/typeck_type_placeholder_item.rs:170:22 | LL | struct BadStruct1<_, _>(_); | - ^ already used @@ -37,7 +45,7 @@ LL | struct BadStruct1<_, _>(_); | first use of `_` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:5:14 + --> $DIR/typeck_type_placeholder_item.rs:6:14 | LL | fn test() -> _ { 5 } | ^ @@ -46,7 +54,7 @@ LL | fn test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:8:16 + --> $DIR/typeck_type_placeholder_item.rs:9:16 | LL | fn test2() -> (_, _) { (5, 5) } | -^--^- @@ -56,7 +64,7 @@ LL | fn test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:11:15 + --> $DIR/typeck_type_placeholder_item.rs:12:15 | LL | static TEST3: _ = "test"; | ^ @@ -65,7 +73,7 @@ LL | static TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:14:15 + --> $DIR/typeck_type_placeholder_item.rs:15:15 | LL | static TEST4: _ = 145; | ^ @@ -74,13 +82,13 @@ LL | static TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:17:15 + --> $DIR/typeck_type_placeholder_item.rs:18:15 | LL | static TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:20:13 + --> $DIR/typeck_type_placeholder_item.rs:21:13 | LL | fn test6(_: _) { } | ^ not allowed in type signatures @@ -91,7 +99,7 @@ LL | fn test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:23:18 + --> $DIR/typeck_type_placeholder_item.rs:24:18 | LL | fn test6_b(_: _, _: T) { } | ^ not allowed in type signatures @@ -102,7 +110,7 @@ LL | fn test6_b(_: K, _: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:26:30 + --> $DIR/typeck_type_placeholder_item.rs:27:30 | LL | fn test6_c(_: _, _: (T, K, L, A, B)) { } | ^ not allowed in type signatures @@ -113,7 +121,7 @@ LL | fn test6_c(_: C, _: (T, K, L, A, B)) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:29:13 + --> $DIR/typeck_type_placeholder_item.rs:30:13 | LL | fn test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -124,13 +132,13 @@ LL | fn test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:22 + --> $DIR/typeck_type_placeholder_item.rs:33:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:32:22 + --> $DIR/typeck_type_placeholder_item.rs:33:22 | LL | fn test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -141,7 +149,7 @@ LL | fn test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:46:26 + --> $DIR/typeck_type_placeholder_item.rs:47:26 | LL | fn test11(x: &usize) -> &_ { | -^ @@ -150,7 +158,7 @@ LL | fn test11(x: &usize) -> &_ { | help: replace with the correct return type: `&&usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:51:52 + --> $DIR/typeck_type_placeholder_item.rs:52:52 | LL | unsafe fn test12(x: *const usize) -> *const *const _ { | --------------^ @@ -159,7 +167,7 @@ LL | unsafe fn test12(x: *const usize) -> *const *const _ { | help: replace with the correct return type: `*const *const usize` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:65:8 + --> $DIR/typeck_type_placeholder_item.rs:66:8 | LL | a: _, | ^ not allowed in type signatures @@ -178,13 +186,13 @@ LL | b: (T, T), | error: missing type for `static` item - --> $DIR/typeck_type_placeholder_item.rs:71:12 + --> $DIR/typeck_type_placeholder_item.rs:72:12 | LL | static A = 42; | ^ help: provide a type for the item: `A: i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:73:15 + --> $DIR/typeck_type_placeholder_item.rs:74:15 | LL | static B: _ = 42; | ^ @@ -193,13 +201,13 @@ LL | static B: _ = 42; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:75:15 + --> $DIR/typeck_type_placeholder_item.rs:76:15 | LL | static C: Option<_> = Some(42); | ^^^^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:78:21 + --> $DIR/typeck_type_placeholder_item.rs:79:21 | LL | fn fn_test() -> _ { 5 } | ^ @@ -208,7 +216,7 @@ LL | fn fn_test() -> _ { 5 } | help: replace with the correct return type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:81:23 + --> $DIR/typeck_type_placeholder_item.rs:82:23 | LL | fn fn_test2() -> (_, _) { (5, 5) } | -^--^- @@ -218,7 +226,7 @@ LL | fn fn_test2() -> (_, _) { (5, 5) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:84:22 + --> $DIR/typeck_type_placeholder_item.rs:85:22 | LL | static FN_TEST3: _ = "test"; | ^ @@ -227,7 +235,7 @@ LL | static FN_TEST3: _ = "test"; | help: replace `_` with the correct type: `&'static str` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:87:22 + --> $DIR/typeck_type_placeholder_item.rs:88:22 | LL | static FN_TEST4: _ = 145; | ^ @@ -236,13 +244,13 @@ LL | static FN_TEST4: _ = 145; | help: replace `_` with the correct type: `i32` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:90:22 + --> $DIR/typeck_type_placeholder_item.rs:91:22 | LL | static FN_TEST5: (_, _) = (1, 2); | ^^^^^^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:93:20 + --> $DIR/typeck_type_placeholder_item.rs:94:20 | LL | fn fn_test6(_: _) { } | ^ not allowed in type signatures @@ -253,7 +261,7 @@ LL | fn fn_test6(_: T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:96:20 + --> $DIR/typeck_type_placeholder_item.rs:97:20 | LL | fn fn_test7(x: _) { let _x: usize = x; } | ^ not allowed in type signatures @@ -264,13 +272,13 @@ LL | fn fn_test7(x: T) { let _x: usize = x; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:99:29 + --> $DIR/typeck_type_placeholder_item.rs:100:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:99:29 + --> $DIR/typeck_type_placeholder_item.rs:100:29 | LL | fn fn_test8(_f: fn() -> _) { } | ^ not allowed in type signatures @@ -281,7 +289,7 @@ LL | fn fn_test8(_f: fn() -> T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:122:12 + --> $DIR/typeck_type_placeholder_item.rs:123:12 | LL | a: _, | ^ not allowed in type signatures @@ -300,13 +308,13 @@ LL | b: (T, T), | error[E0282]: type annotations needed - --> $DIR/typeck_type_placeholder_item.rs:127:18 + --> $DIR/typeck_type_placeholder_item.rs:128:18 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ cannot infer type error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:127:28 + --> $DIR/typeck_type_placeholder_item.rs:128:28 | LL | fn fn_test11(_: _) -> (_, _) { panic!() } | ^ ^ not allowed in type signatures @@ -314,7 +322,7 @@ LL | fn fn_test11(_: _) -> (_, _) { panic!() } | not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:131:30 + --> $DIR/typeck_type_placeholder_item.rs:132:30 | LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | -^--^- @@ -324,7 +332,7 @@ LL | fn fn_test12(x: i32) -> (_, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:134:33 + --> $DIR/typeck_type_placeholder_item.rs:135:33 | LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | ------^- @@ -333,7 +341,7 @@ LL | fn fn_test13(x: _) -> (i32, _) { (x, x) } | help: replace with the correct return type: `(i32, i32)` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:153:21 + --> $DIR/typeck_type_placeholder_item.rs:154:21 | LL | struct BadStruct<_>(_); | ^ not allowed in type signatures @@ -344,19 +352,19 @@ LL | struct BadStruct(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:32 + --> $DIR/typeck_type_placeholder_item.rs:159:32 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:15 + --> $DIR/typeck_type_placeholder_item.rs:159:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:158:15 + --> $DIR/typeck_type_placeholder_item.rs:159:15 | LL | impl BadTrait<_> for BadStruct<_> {} | ^ ^ not allowed in type signatures @@ -369,13 +377,13 @@ LL | impl BadTrait for BadStruct {} | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:163:34 + --> $DIR/typeck_type_placeholder_item.rs:164:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:169:25 + --> $DIR/typeck_type_placeholder_item.rs:170:25 | LL | struct BadStruct1<_, _>(_); | ^ not allowed in type signatures @@ -386,7 +394,7 @@ LL | struct BadStruct1(T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:174:25 + --> $DIR/typeck_type_placeholder_item.rs:175:25 | LL | struct BadStruct2<_, T>(_, T); | ^ not allowed in type signatures @@ -397,19 +405,19 @@ LL | struct BadStruct2(K, T); | ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:178:14 + --> $DIR/typeck_type_placeholder_item.rs:179:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:178:14 + --> $DIR/typeck_type_placeholder_item.rs:179:14 | LL | type X = Box<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:42:27 + --> $DIR/typeck_type_placeholder_item.rs:43:27 | LL | fn test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -420,7 +428,7 @@ LL | fn test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:139:31 + --> $DIR/typeck_type_placeholder_item.rs:140:31 | LL | fn method_test1(&self, x: _); | ^ not allowed in type signatures @@ -431,7 +439,7 @@ LL | fn method_test1(&self, x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:141:31 + --> $DIR/typeck_type_placeholder_item.rs:142:31 | LL | fn method_test2(&self, x: _) -> _; | ^ ^ not allowed in type signatures @@ -444,7 +452,7 @@ LL | fn method_test2(&self, x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:143:31 + --> $DIR/typeck_type_placeholder_item.rs:144:31 | LL | fn method_test3(&self) -> _; | ^ not allowed in type signatures @@ -455,7 +463,7 @@ LL | fn method_test3(&self) -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:145:26 + --> $DIR/typeck_type_placeholder_item.rs:146:26 | LL | fn assoc_fn_test1(x: _); | ^ not allowed in type signatures @@ -466,7 +474,7 @@ LL | fn assoc_fn_test1(x: T); | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:147:26 + --> $DIR/typeck_type_placeholder_item.rs:148:26 | LL | fn assoc_fn_test2(x: _) -> _; | ^ ^ not allowed in type signatures @@ -479,7 +487,7 @@ LL | fn assoc_fn_test2(x: T) -> T; | ^^^ ^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:149:28 + --> $DIR/typeck_type_placeholder_item.rs:150:28 | LL | fn assoc_fn_test3() -> _; | ^ not allowed in type signatures @@ -490,7 +498,7 @@ LL | fn assoc_fn_test3() -> T; | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:60:37 + --> $DIR/typeck_type_placeholder_item.rs:61:37 | LL | fn clone_from(&mut self, other: _) { *self = Test9; } | ^ not allowed in type signatures @@ -501,7 +509,7 @@ LL | fn clone_from(&mut self, other: T) { *self = Test9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:109:34 + --> $DIR/typeck_type_placeholder_item.rs:110:34 | LL | fn fn_test10(&self, _x : _) { } | ^ not allowed in type signatures @@ -512,7 +520,7 @@ LL | fn fn_test10(&self, _x : T) { } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:117:41 + --> $DIR/typeck_type_placeholder_item.rs:118:41 | LL | fn clone_from(&mut self, other: _) { *self = FnTest9; } | ^ not allowed in type signatures @@ -523,25 +531,46 @@ LL | fn clone_from(&mut self, other: T) { *self = FnTest9; } | ^^^ ^ error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:163:34 + --> $DIR/typeck_type_placeholder_item.rs:164:34 | LL | fn impl_trait() -> impl BadTrait<_> { | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:21 + --> $DIR/typeck_type_placeholder_item.rs:186:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:185:21 + --> $DIR/typeck_type_placeholder_item.rs:186:21 | LL | type Y = impl Trait<_>; | ^ not allowed in type signatures error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:39:24 + --> $DIR/typeck_type_placeholder_item.rs:195:14 + | +LL | type B = _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:197:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:199:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace `_` with the correct type: `i32` + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:40:24 | LL | fn test9(&self) -> _ { () } | ^ @@ -550,7 +579,7 @@ LL | fn test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:57:24 + --> $DIR/typeck_type_placeholder_item.rs:58:24 | LL | fn clone(&self) -> _ { Test9 } | ^ @@ -559,7 +588,7 @@ LL | fn clone(&self) -> _ { Test9 } | help: replace with the correct return type: `Test9` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:106:31 + --> $DIR/typeck_type_placeholder_item.rs:107:31 | LL | fn fn_test9(&self) -> _ { () } | ^ @@ -568,7 +597,7 @@ LL | fn fn_test9(&self) -> _ { () } | help: replace with the correct return type: `()` error[E0121]: the type placeholder `_` is not allowed within types on item signatures - --> $DIR/typeck_type_placeholder_item.rs:114:28 + --> $DIR/typeck_type_placeholder_item.rs:115:28 | LL | fn clone(&self) -> _ { FnTest9 } | ^ @@ -576,7 +605,34 @@ LL | fn clone(&self) -> _ { FnTest9 } | not allowed in type signatures | help: replace with the correct return type: `main::FnTest9` -error: aborting due to 63 previous errors +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:204:14 + | +LL | type A = _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:206:14 + | +LL | type B = _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:208:14 + | +LL | const C: _; + | ^ not allowed in type signatures + +error[E0121]: the type placeholder `_` is not allowed within types on item signatures + --> $DIR/typeck_type_placeholder_item.rs:211:14 + | +LL | const D: _ = 42; + | ^ + | | + | not allowed in type signatures + | help: replace `_` with the correct type: `i32` + +error: aborting due to 71 previous errors Some errors have detailed explanations: E0121, E0282, E0403. For more information about an error, try `rustc --explain E0121`. From 4e0bea326e7f3f26ddae920e599597b309530e00 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Fri, 28 Feb 2020 13:28:09 +0900 Subject: [PATCH 30/31] Stabilize `boxed_slice_try_from` --- src/liballoc/boxed.rs | 2 +- src/liballoc/rc.rs | 2 +- src/liballoc/sync.rs | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs index 3ac4bd82a3a10..81b0e9817d261 100644 --- a/src/liballoc/boxed.rs +++ b/src/liballoc/boxed.rs @@ -825,7 +825,7 @@ impl From> for Box<[u8]> { } } -#[unstable(feature = "boxed_slice_try_from", issue = "none")] +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl TryFrom> for Box<[T; N]> where [T; N]: LengthAtMost32, diff --git a/src/liballoc/rc.rs b/src/liballoc/rc.rs index 9dc5447397f09..6ee128f4fa1d2 100644 --- a/src/liballoc/rc.rs +++ b/src/liballoc/rc.rs @@ -1453,7 +1453,7 @@ impl From> for Rc<[T]> { } } -#[unstable(feature = "boxed_slice_try_from", issue = "none")] +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl TryFrom> for Rc<[T; N]> where [T; N]: LengthAtMost32, diff --git a/src/liballoc/sync.rs b/src/liballoc/sync.rs index fd285242d5be4..9bd708c0f595c 100644 --- a/src/liballoc/sync.rs +++ b/src/liballoc/sync.rs @@ -2002,7 +2002,7 @@ impl From> for Arc<[T]> { } } -#[unstable(feature = "boxed_slice_try_from", issue = "none")] +#[stable(feature = "boxed_slice_try_from", since = "1.43.0")] impl TryFrom> for Arc<[T; N]> where [T; N]: LengthAtMost32, From 85b585daaf735deda96c6e087e2a3f203c64d52d Mon Sep 17 00:00:00 2001 From: Mazdak Farrokhzad Date: Fri, 28 Feb 2020 07:58:37 +0100 Subject: [PATCH 31/31] late resolve, visit_fn: bail early if there's no body. --- src/librustc_resolve/late.rs | 5 +++-- .../ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs | 6 ++++++ .../resolve/issue-69401-trait-fn-no-body-ty-local.stderr | 9 +++++++++ 3 files changed, 18 insertions(+), 2 deletions(-) create mode 100644 src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs create mode 100644 src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs index c924fef4dc9d2..48a2f829d1998 100644 --- a/src/librustc_resolve/late.rs +++ b/src/librustc_resolve/late.rs @@ -456,8 +456,9 @@ impl<'a, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> { } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, _: NodeId) { let rib_kind = match fn_kind { - FnKind::Fn(FnCtxt::Foreign, ..) => return visit::walk_fn(self, fn_kind, sp), - FnKind::Fn(FnCtxt::Free, ..) => FnItemRibKind, + // Bail if there's no body. + FnKind::Fn(.., None) => return visit::walk_fn(self, fn_kind, sp), + FnKind::Fn(FnCtxt::Free, ..) | FnKind::Fn(FnCtxt::Foreign, ..) => FnItemRibKind, FnKind::Fn(FnCtxt::Assoc(_), ..) | FnKind::Closure(..) => NormalRibKind, }; let previous_value = replace(&mut self.diagnostic_metadata.current_function, Some(sp)); diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs new file mode 100644 index 0000000000000..4397baea4a940 --- /dev/null +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.rs @@ -0,0 +1,6 @@ +fn main() {} + +trait Foo { + fn fn_with_type_named_same_as_local_in_param(b: b); + //~^ ERROR cannot find type `b` in this scope +} diff --git a/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr new file mode 100644 index 0000000000000..109409d2731c5 --- /dev/null +++ b/src/test/ui/resolve/issue-69401-trait-fn-no-body-ty-local.stderr @@ -0,0 +1,9 @@ +error[E0412]: cannot find type `b` in this scope + --> $DIR/issue-69401-trait-fn-no-body-ty-local.rs:4:53 + | +LL | fn fn_with_type_named_same_as_local_in_param(b: b); + | ^ not found in this scope + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0412`.