From 7a378dd0fb2b383be75722666d8a3c761882af15 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bruno=20A=2E=20Muci=C3=B1o?= <mucinoab@gmail.com>
Date: Sun, 27 Nov 2022 20:50:13 -0600
Subject: [PATCH] Avoid ICE if the Clone trait is not found while building
 error suggestions

---
 .../src/diagnostics/conflict_errors.rs        | 16 +++++++-------
 .../missing-clone-for-suggestion.rs           | 20 ++++++++++++++++++
 .../missing-clone-for-suggestion.stderr       | 21 +++++++++++++++++++
 3 files changed, 50 insertions(+), 7 deletions(-)
 create mode 100644 src/test/ui/lang-items/missing-clone-for-suggestion.rs
 create mode 100644 src/test/ui/lang-items/missing-clone-for-suggestion.stderr

diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
index 5ec9c5f5c1b..d221da5c17e 100644
--- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs
@@ -732,13 +732,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
         let tcx = self.infcx.tcx;
         // Try to find predicates on *generic params* that would allow copying `ty`
         let infcx = tcx.infer_ctxt().build();
-        if infcx
-            .type_implements_trait(
-                tcx.lang_items().clone_trait().unwrap(),
-                [tcx.erase_regions(ty)],
-                self.param_env,
-            )
-            .must_apply_modulo_regions()
+
+        if let Some(clone_trait_def) = tcx.lang_items().clone_trait()
+            && infcx
+                .type_implements_trait(
+                    clone_trait_def,
+                    [tcx.erase_regions(ty)],
+                    self.param_env,
+                )
+                .must_apply_modulo_regions()
         {
             err.span_suggestion_verbose(
                 span.shrink_to_hi(),
diff --git a/src/test/ui/lang-items/missing-clone-for-suggestion.rs b/src/test/ui/lang-items/missing-clone-for-suggestion.rs
new file mode 100644
index 00000000000..e8290c0098a
--- /dev/null
+++ b/src/test/ui/lang-items/missing-clone-for-suggestion.rs
@@ -0,0 +1,20 @@
+// Avoid panicking if the Clone trait is not found while building error suggestions
+// See #104870
+
+#![feature(no_core, lang_items)]
+#![no_core]
+
+#[lang = "sized"]
+trait Sized {}
+
+#[lang = "copy"]
+trait Copy {}
+
+fn g<T>(x: T) {}
+
+fn f(x: *mut u8) {
+    g(x);
+    g(x); //~ ERROR use of moved value: `x`
+}
+
+fn main() {}
diff --git a/src/test/ui/lang-items/missing-clone-for-suggestion.stderr b/src/test/ui/lang-items/missing-clone-for-suggestion.stderr
new file mode 100644
index 00000000000..35783a1be78
--- /dev/null
+++ b/src/test/ui/lang-items/missing-clone-for-suggestion.stderr
@@ -0,0 +1,21 @@
+error[E0382]: use of moved value: `x`
+  --> $DIR/missing-clone-for-suggestion.rs:17:7
+   |
+LL | fn f(x: *mut u8) {
+   |      - move occurs because `x` has type `*mut u8`, which does not implement the `Copy` trait
+LL |     g(x);
+   |       - value moved here
+LL |     g(x);
+   |       ^ value used here after move
+   |
+note: consider changing this parameter type in function `g` to borrow instead if owning the value isn't necessary
+  --> $DIR/missing-clone-for-suggestion.rs:13:12
+   |
+LL | fn g<T>(x: T) {}
+   |    -       ^ this parameter takes ownership of the value
+   |    |
+   |    in this function
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0382`.