about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMichael Goulet <michael@errs.io>2022-10-09 21:02:12 +0000
committerMichael Goulet <michael@errs.io>2022-10-19 02:06:19 +0000
commit63be7a24242b262ba9924eec89a5cc6512d8b504 (patch)
treedaa1a6aedaae64868b20de04354650066a685957
parenta24a020e6d926dffe6b472fc647978f92269504e (diff)
downloadrust-63be7a24242b262ba9924eec89a5cc6512d8b504.tar.gz
rust-63be7a24242b262ba9924eec89a5cc6512d8b504.zip
Suggest calling ctor when trait is unimplemented
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs19
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-ctor.rs17
-rw-r--r--src/test/ui/suggestions/call-on-unimplemented-ctor.stderr24
3 files changed, 59 insertions, 1 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 4431cf9f443..0b2fcc9b0d1 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -817,7 +817,14 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
 
         let (def_id, output_ty, callable) = match *self_ty.kind() {
             ty::Closure(def_id, substs) => (def_id, substs.as_closure().sig().output(), "closure"),
-            ty::FnDef(def_id, _) => (def_id, self_ty.fn_sig(self.tcx).output(), "function"),
+            ty::FnDef(def_id, _) => (
+                def_id,
+                self_ty.fn_sig(self.tcx).output(),
+                match self.tcx.def_kind(def_id) {
+                    DefKind::Ctor(..) => "constructor",
+                    _ => "function",
+                },
+            ),
             _ => return false,
         };
         let msg = format!("use parentheses to call the {}", callable);
@@ -878,6 +885,16 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                 let sugg = format!("({})", args);
                 (format!("{}{}", ident, sugg), sugg)
             }
+            Some(hir::Node::Ctor(data)) => {
+                let name = self.tcx.def_path_str(def_id);
+                err.span_label(
+                    self.tcx.def_span(def_id),
+                    format!("consider calling the constructor for `{}`", name),
+                );
+                let args = data.fields().iter().map(|_| "_").collect::<Vec<_>>().join(", ");
+                let sugg = format!("({})", args);
+                (format!("{name}{sugg}"), sugg)
+            }
             _ => return false,
         };
         if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.rs b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
new file mode 100644
index 00000000000..28a319382e6
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.rs
@@ -0,0 +1,17 @@
+fn main() {
+    insert_resource(Marker);
+    insert_resource(Time);
+    //~^ ERROR the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
+    //~| HELP use parentheses to call the constructor
+}
+
+trait Resource {}
+
+fn insert_resource<R: Resource>(resource: R) {}
+
+struct Marker;
+impl Resource for Marker {}
+
+struct Time(u32);
+
+impl Resource for Time {}
diff --git a/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
new file mode 100644
index 00000000000..ea8aec3098d
--- /dev/null
+++ b/src/test/ui/suggestions/call-on-unimplemented-ctor.stderr
@@ -0,0 +1,24 @@
+error[E0277]: the trait bound `fn(u32) -> Time {Time}: Resource` is not satisfied
+  --> $DIR/call-on-unimplemented-ctor.rs:3:21
+   |
+LL |     insert_resource(Time);
+   |     --------------- ^^^^ the trait `Resource` is not implemented for fn item `fn(u32) -> Time {Time}`
+   |     |
+   |     required by a bound introduced by this call
+...
+LL | struct Time(u32);
+   | ----------- consider calling the constructor for `Time`
+   |
+note: required by a bound in `insert_resource`
+  --> $DIR/call-on-unimplemented-ctor.rs:10:23
+   |
+LL | fn insert_resource<R: Resource>(resource: R) {}
+   |                       ^^^^^^^^ required by this bound in `insert_resource`
+help: use parentheses to call the constructor
+   |
+LL |     insert_resource(Time(_));
+   |                         +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.