From ac3d4cccea3225468a3c8ff8ea18b60166c84fb8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 30 Dec 2019 21:15:40 -0800 Subject: [PATCH 1/2] Explain that associated types and consts can't be accessed directly on the trait's path --- src/librustc/traits/error_reporting.rs | 25 ++++++++++++++++++- .../ui/associated-const/issue-63496.stderr | 12 +++++++-- .../ui/associated-item/issue-48027.stderr | 6 ++++- src/test/ui/issues/issue-58022.stderr | 6 ++++- 4 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index 00251d55706d7..a856d2fd960c8 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2075,7 +2075,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { } let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283); err.note(&format!("cannot resolve `{}`", predicate)); - if let (Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _)) = + if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { + if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { + if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind { + err.note(&format!( + "{}s cannot be accessed directly on a `trait`, they can only be \ + accessed through a specific `impl`", + assoc_item.kind.suggestion_descr(), + )); + err.span_suggestion( + span, + "use the fully qualified path to an implementation", + format!( + "::{}", + self.tcx.def_path_str(trait_ref.def_id()), + assoc_item.ident + ), + Applicability::HasPlaceholders, + ); + } + } + } else if let ( + Ok(ref snippet), + ObligationCauseCode::BindingObligation(ref def_id, _), + ) = (self.tcx.sess.source_map().span_to_snippet(span), &obligation.cause.code) { let generics = self.tcx.generics_of(*def_id); diff --git a/src/test/ui/associated-const/issue-63496.stderr b/src/test/ui/associated-const/issue-63496.stderr index 23916a3ba440c..3a70e7d43c25e 100644 --- a/src/test/ui/associated-const/issue-63496.stderr +++ b/src/test/ui/associated-const/issue-63496.stderr @@ -5,9 +5,13 @@ LL | const C: usize; | --------------- required by `A::C` LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ cannot infer type + | ^^^^ + | | + | cannot infer type + | help: use the fully qualified path to an implementation: `::C` | = note: cannot resolve `_: A` + = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` error[E0283]: type annotations needed --> $DIR/issue-63496.rs:4:33 @@ -16,9 +20,13 @@ LL | const C: usize; | --------------- required by `A::C` LL | LL | fn f() -> ([u8; A::C], [u8; A::C]); - | ^^^^ cannot infer type + | ^^^^ + | | + | cannot infer type + | help: use the fully qualified path to an implementation: `::C` | = note: cannot resolve `_: A` + = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` error: aborting due to 2 previous errors diff --git a/src/test/ui/associated-item/issue-48027.stderr b/src/test/ui/associated-item/issue-48027.stderr index 9c825d593d3e4..ddabd552897a8 100644 --- a/src/test/ui/associated-item/issue-48027.stderr +++ b/src/test/ui/associated-item/issue-48027.stderr @@ -13,9 +13,13 @@ error[E0283]: type annotations needed LL | const X: usize; | --------------- required by `Bar::X` LL | fn return_n(&self) -> [u8; Bar::X]; - | ^^^^^^ cannot infer type + | ^^^^^^ + | | + | cannot infer type + | help: use the fully qualified path to an implementation: `::X` | = note: cannot resolve `_: Bar` + = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` error: aborting due to 2 previous errors diff --git a/src/test/ui/issues/issue-58022.stderr b/src/test/ui/issues/issue-58022.stderr index ef0d66d7ad6d1..70a7c38b83425 100644 --- a/src/test/ui/issues/issue-58022.stderr +++ b/src/test/ui/issues/issue-58022.stderr @@ -11,9 +11,13 @@ LL | const SIZE: usize; | ------------------ required by `Foo::SIZE` LL | LL | fn new(slice: &[u8; Foo::SIZE]) -> Self; - | ^^^^^^^^^ cannot infer type + | ^^^^^^^^^ + | | + | cannot infer type + | help: use the fully qualified path to an implementation: `::SIZE` | = note: cannot resolve `_: Foo` + = note: associated constants cannot be accessed directly on a `trait`, they can only be accessed through a specific `impl` error: aborting due to 2 previous errors From b3b206f6bdb62216bc03ec000e0a285691014703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 8 Jan 2020 10:10:51 -0800 Subject: [PATCH 2/2] move code to method outside of happy path --- src/librustc/traits/error_reporting.rs | 44 +++++++++++++++----------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs index a856d2fd960c8..5b8eb34ead1b3 100644 --- a/src/librustc/traits/error_reporting.rs +++ b/src/librustc/traits/error_reporting.rs @@ -2076,25 +2076,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { let mut err = self.need_type_info_err(body_id, span, self_ty, ErrorCode::E0283); err.note(&format!("cannot resolve `{}`", predicate)); if let ObligationCauseCode::ItemObligation(def_id) = obligation.cause.code { - if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { - if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind { - err.note(&format!( - "{}s cannot be accessed directly on a `trait`, they can only be \ - accessed through a specific `impl`", - assoc_item.kind.suggestion_descr(), - )); - err.span_suggestion( - span, - "use the fully qualified path to an implementation", - format!( - "::{}", - self.tcx.def_path_str(trait_ref.def_id()), - assoc_item.ident - ), - Applicability::HasPlaceholders, - ); - } - } + self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id()); } else if let ( Ok(ref snippet), ObligationCauseCode::BindingObligation(ref def_id, _), @@ -2196,6 +2178,30 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> { err.emit(); } + fn suggest_fully_qualified_path( + &self, + err: &mut DiagnosticBuilder<'_>, + def_id: DefId, + span: Span, + trait_ref: DefId, + ) { + if let Some(assoc_item) = self.tcx.opt_associated_item(def_id) { + if let ty::AssocKind::Const | ty::AssocKind::Type = assoc_item.kind { + err.note(&format!( + "{}s cannot be accessed directly on a `trait`, they can only be \ + accessed through a specific `impl`", + assoc_item.kind.suggestion_descr(), + )); + err.span_suggestion( + span, + "use the fully qualified path to an implementation", + format!("::{}", self.tcx.def_path_str(trait_ref), assoc_item.ident), + Applicability::HasPlaceholders, + ); + } + } + } + /// Returns `true` if the trait predicate may apply for *some* assignment /// to the type parameters. fn predicate_can_apply(