about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--clippy_lints/src/significant_drop_tightening.rs17
-rw-r--r--tests/ui/crashes/ice-13544-original.rs45
-rw-r--r--tests/ui/crashes/ice-13544-reduced.rs16
3 files changed, 71 insertions, 7 deletions
diff --git a/clippy_lints/src/significant_drop_tightening.rs b/clippy_lints/src/significant_drop_tightening.rs
index 13d5d4d8d4c..ccb1209c6fc 100644
--- a/clippy_lints/src/significant_drop_tightening.rs
+++ b/clippy_lints/src/significant_drop_tightening.rs
@@ -144,7 +144,10 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
         Self { cx, type_cache }
     }
 
-    fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
+    fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>, depth: usize) -> bool {
+        if !self.cx.tcx.recursion_limit().value_within_limit(depth) {
+            return false;
+        }
         let ty = self
             .cx
             .tcx
@@ -156,12 +159,12 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
                 e.insert(false);
             },
         }
-        let value = self.has_sig_drop_attr_uncached(ty);
+        let value = self.has_sig_drop_attr_uncached(ty, depth + 1);
         self.type_cache.insert(ty, value);
         value
     }
 
-    fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
+    fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>, depth: usize) -> bool {
         if let Some(adt) = ty.ty_adt_def() {
             let mut iter = get_attr(
                 self.cx.sess(),
@@ -176,13 +179,13 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
             rustc_middle::ty::Adt(a, b) => {
                 for f in a.all_fields() {
                     let ty = f.ty(self.cx.tcx, b);
-                    if self.has_sig_drop_attr(ty) {
+                    if self.has_sig_drop_attr(ty, depth) {
                         return true;
                     }
                 }
                 for generic_arg in *b {
                     if let GenericArgKind::Type(ty) = generic_arg.unpack()
-                        && self.has_sig_drop_attr(ty)
+                        && self.has_sig_drop_attr(ty, depth)
                     {
                         return true;
                     }
@@ -192,7 +195,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
             rustc_middle::ty::Array(ty, _)
             | rustc_middle::ty::RawPtr(ty, _)
             | rustc_middle::ty::Ref(_, ty, _)
-            | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty),
+            | rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty, depth),
             _ => false,
         }
     }
@@ -268,7 +271,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
             apa.has_expensive_expr_after_last_attr = false;
         };
         let mut ac = AttrChecker::new(self.cx, self.type_cache);
-        if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
+        if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr), 0) {
             if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
                 && let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
                 && !self.ap.apas.contains_key(&hir_id)
diff --git a/tests/ui/crashes/ice-13544-original.rs b/tests/ui/crashes/ice-13544-original.rs
new file mode 100644
index 00000000000..1709eaeb365
--- /dev/null
+++ b/tests/ui/crashes/ice-13544-original.rs
@@ -0,0 +1,45 @@
+//@ check-pass
+#![warn(clippy::significant_drop_tightening)]
+
+use std::mem::ManuallyDrop;
+use std::ops::{Deref, DerefMut};
+
+trait Scopable: Sized {
+    type SubType: Scopable;
+}
+
+struct Subtree<T: Scopable>(ManuallyDrop<Box<Tree<T::SubType>>>);
+
+impl<T: Scopable> Drop for Subtree<T> {
+    fn drop(&mut self) {
+        // SAFETY: The field cannot be used after we drop
+        unsafe { ManuallyDrop::drop(&mut self.0) }
+    }
+}
+
+impl<T: Scopable> Deref for Subtree<T> {
+    type Target = Tree<T::SubType>;
+    fn deref(&self) -> &Self::Target {
+        &self.0
+    }
+}
+
+impl<T: Scopable> DerefMut for Subtree<T> {
+    fn deref_mut(&mut self) -> &mut Self::Target {
+        &mut self.0
+    }
+}
+
+enum Tree<T: Scopable> {
+    Group(Vec<Tree<T>>),
+    Subtree(Subtree<T>),
+    Leaf(T),
+}
+
+impl<T: Scopable> Tree<T> {
+    fn foo(self) -> Self {
+        self
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/crashes/ice-13544-reduced.rs b/tests/ui/crashes/ice-13544-reduced.rs
new file mode 100644
index 00000000000..9266e71f5d0
--- /dev/null
+++ b/tests/ui/crashes/ice-13544-reduced.rs
@@ -0,0 +1,16 @@
+//@ check-pass
+#![warn(clippy::significant_drop_tightening)]
+#![allow(unused, clippy::no_effect)]
+
+use std::marker::PhantomData;
+
+trait Trait {
+    type Assoc: Trait;
+}
+struct S<T: Trait>(*const S<T::Assoc>, PhantomData<T>);
+
+fn f<T: Trait>(x: &mut S<T>) {
+    &mut x.0;
+}
+
+fn main() {}