Skip to content

Commit dd26f17

Browse files
committed
Do not recurse forever in significant_drop_tightening
Limit the recursion depth, as each level of nesting adds another deeper projection.
1 parent 3479fdf commit dd26f17

File tree

3 files changed

+74
-7
lines changed

3 files changed

+74
-7
lines changed

clippy_lints/src/significant_drop_tightening.rs

+13-7
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,10 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
144144
Self { cx, type_cache }
145145
}
146146

147-
fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
147+
fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>, depth: usize) -> bool {
148+
if !self.cx.tcx.recursion_limit().value_within_limit(depth) {
149+
return false;
150+
}
148151
let ty = self
149152
.cx
150153
.tcx
@@ -156,12 +159,15 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
156159
e.insert(false);
157160
},
158161
}
159-
let value = self.has_sig_drop_attr_uncached(ty);
162+
let value = self.has_sig_drop_attr_uncached(ty, depth + 1);
160163
self.type_cache.insert(ty, value);
161164
value
162165
}
163166

164-
fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
167+
fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>, depth: usize) -> bool {
168+
if !self.cx.tcx.recursion_limit().value_within_limit(depth) {
169+
return false;
170+
}
165171
if let Some(adt) = ty.ty_adt_def() {
166172
let mut iter = get_attr(
167173
self.cx.sess(),
@@ -176,13 +182,13 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
176182
rustc_middle::ty::Adt(a, b) => {
177183
for f in a.all_fields() {
178184
let ty = f.ty(self.cx.tcx, b);
179-
if self.has_sig_drop_attr(ty) {
185+
if self.has_sig_drop_attr(ty, depth) {
180186
return true;
181187
}
182188
}
183189
for generic_arg in *b {
184190
if let GenericArgKind::Type(ty) = generic_arg.unpack()
185-
&& self.has_sig_drop_attr(ty)
191+
&& self.has_sig_drop_attr(ty, depth)
186192
{
187193
return true;
188194
}
@@ -192,7 +198,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
192198
rustc_middle::ty::Array(ty, _)
193199
| rustc_middle::ty::RawPtr(ty, _)
194200
| rustc_middle::ty::Ref(_, ty, _)
195-
| rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty),
201+
| rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty, depth),
196202
_ => false,
197203
}
198204
}
@@ -268,7 +274,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
268274
apa.has_expensive_expr_after_last_attr = false;
269275
};
270276
let mut ac = AttrChecker::new(self.cx, self.type_cache);
271-
if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
277+
if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr), 0) {
272278
if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
273279
&& let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
274280
&& !self.ap.apas.contains_key(&hir_id)
+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//@ check-pass
2+
#![warn(clippy::significant_drop_tightening)]
3+
4+
use std::mem::ManuallyDrop;
5+
use std::ops::{Deref, DerefMut};
6+
7+
trait Scopable: Sized {
8+
type SubType: Scopable;
9+
}
10+
11+
struct Subtree<T: Scopable>(ManuallyDrop<Box<Tree<T::SubType>>>);
12+
13+
impl<T: Scopable> Drop for Subtree<T> {
14+
fn drop(&mut self) {
15+
// SAFETY: The field cannot be used after we drop
16+
unsafe { ManuallyDrop::drop(&mut self.0) }
17+
}
18+
}
19+
20+
impl<T: Scopable> Deref for Subtree<T> {
21+
type Target = Tree<T::SubType>;
22+
fn deref(&self) -> &Self::Target {
23+
&self.0
24+
}
25+
}
26+
27+
impl<T: Scopable> DerefMut for Subtree<T> {
28+
fn deref_mut(&mut self) -> &mut Self::Target {
29+
&mut self.0
30+
}
31+
}
32+
33+
enum Tree<T: Scopable> {
34+
Group(Vec<Tree<T>>),
35+
Subtree(Subtree<T>),
36+
Leaf(T),
37+
}
38+
39+
impl<T: Scopable> Tree<T> {
40+
fn foo(self) -> Self {
41+
self
42+
}
43+
}
44+
45+
fn main() {}

tests/ui/crashes/ice-13544-reduced.rs

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
//@ check-pass
2+
#![warn(clippy::significant_drop_tightening)]
3+
#![allow(unused, clippy::no_effect)]
4+
5+
use std::marker::PhantomData;
6+
7+
trait Trait {
8+
type Assoc: Trait;
9+
}
10+
struct S<T: Trait>(*const S<T::Assoc>, PhantomData<T>);
11+
12+
fn f<T: Trait>(x: &mut S<T>) {
13+
&mut x.0;
14+
}
15+
16+
fn main() {}

0 commit comments

Comments
 (0)