about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs1
-rw-r--r--compiler/rustc_mir_build/src/lints.rs11
-rw-r--r--tests/ui/drop/recursion-check-on-erroneous-impl.rs11
-rw-r--r--tests/ui/drop/recursion-check-on-erroneous-impl.stderr11
4 files changed, 28 insertions, 6 deletions
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 8c734fca9b6..d6e3385c600 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1313,6 +1313,7 @@ impl<'tcx> PolyFnSig<'tcx> {
         self.map_bound_ref_unchecked(|fn_sig| fn_sig.inputs())
     }
     #[inline]
+    #[track_caller]
     pub fn input(&self, index: usize) -> ty::Binder<'tcx, Ty<'tcx>> {
         self.map_bound_ref(|fn_sig| fn_sig.inputs()[index])
     }
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 337493d15de..508936be29d 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -72,15 +72,14 @@ pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
             tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id))
         && let Some(drop_trait) = tcx.lang_items().drop_trait()
         && drop_trait == trait_ref.instantiate_identity().def_id
+        // avoid erroneous `Drop` impls from causing ICEs below
+        && let sig = tcx.fn_sig(def_id).instantiate_identity()
+        && sig.inputs().skip_binder().len() == 1
     {
         // It was. Now figure out for what type `Drop` is implemented and then
         // check for recursion.
-        if let ty::Ref(_, dropped_ty, _) = tcx
-            .liberate_late_bound_regions(
-                def_id.to_def_id(),
-                tcx.fn_sig(def_id).instantiate_identity().input(0),
-            )
-            .kind()
+        if let ty::Ref(_, dropped_ty, _) =
+            tcx.liberate_late_bound_regions(def_id.to_def_id(), sig.input(0)).kind()
         {
             check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty });
         }
diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.rs b/tests/ui/drop/recursion-check-on-erroneous-impl.rs
new file mode 100644
index 00000000000..733c8b0b085
--- /dev/null
+++ b/tests/ui/drop/recursion-check-on-erroneous-impl.rs
@@ -0,0 +1,11 @@
+// can't use build-fail, because this also fails check-fail, but
+// the ICE from #120787 only reproduces on build-fail.
+// compile-flags: --emit=mir
+
+struct PrintOnDrop<'a>(&'a str);
+
+impl Drop for PrintOnDrop<'_> {
+    fn drop() {} //~ ERROR method `drop` has a `&mut self` declaration in the trait
+}
+
+fn main() {}
diff --git a/tests/ui/drop/recursion-check-on-erroneous-impl.stderr b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr
new file mode 100644
index 00000000000..831adb88cef
--- /dev/null
+++ b/tests/ui/drop/recursion-check-on-erroneous-impl.stderr
@@ -0,0 +1,11 @@
+error[E0186]: method `drop` has a `&mut self` declaration in the trait, but not in the impl
+  --> $DIR/recursion-check-on-erroneous-impl.rs:8:5
+   |
+LL |     fn drop() {}
+   |     ^^^^^^^^^ expected `&mut self` in impl
+   |
+   = note: `drop` from trait: `fn(&mut Self)`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0186`.