Skip to content

Commit 30e9cd5

Browse files
authored
Do not recurse forever in significant_drop_tightening (#14641)
Limit the recursion depth, as each level of nesting adds another deeper projection. There might be a more complex way of handling the problem, but infinite recursions are bad, and don't allow Clippy to terminate properly. changelog: [`significant_drop_tightening`]: do not recurse forever when checking for attribute on type or its constituent Fixes #13544 @rustbot label +L-nursery
2 parents 3479fdf + cc6a3d8 commit 30e9cd5

File tree

3 files changed

+71
-7
lines changed

3 files changed

+71
-7
lines changed

clippy_lints/src/significant_drop_tightening.rs

+10-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,12 @@ 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 {
165168
if let Some(adt) = ty.ty_adt_def() {
166169
let mut iter = get_attr(
167170
self.cx.sess(),
@@ -176,13 +179,13 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
176179
rustc_middle::ty::Adt(a, b) => {
177180
for f in a.all_fields() {
178181
let ty = f.ty(self.cx.tcx, b);
179-
if self.has_sig_drop_attr(ty) {
182+
if self.has_sig_drop_attr(ty, depth) {
180183
return true;
181184
}
182185
}
183186
for generic_arg in *b {
184187
if let GenericArgKind::Type(ty) = generic_arg.unpack()
185-
&& self.has_sig_drop_attr(ty)
188+
&& self.has_sig_drop_attr(ty, depth)
186189
{
187190
return true;
188191
}
@@ -192,7 +195,7 @@ impl<'cx, 'others, 'tcx> AttrChecker<'cx, 'others, 'tcx> {
192195
rustc_middle::ty::Array(ty, _)
193196
| rustc_middle::ty::RawPtr(ty, _)
194197
| rustc_middle::ty::Ref(_, ty, _)
195-
| rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty),
198+
| rustc_middle::ty::Slice(ty) => self.has_sig_drop_attr(*ty, depth),
196199
_ => false,
197200
}
198201
}
@@ -268,7 +271,7 @@ impl<'tcx> Visitor<'tcx> for StmtsChecker<'_, '_, '_, '_, 'tcx> {
268271
apa.has_expensive_expr_after_last_attr = false;
269272
};
270273
let mut ac = AttrChecker::new(self.cx, self.type_cache);
271-
if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr)) {
274+
if ac.has_sig_drop_attr(self.cx.typeck_results().expr_ty(expr), 0) {
272275
if let hir::StmtKind::Let(local) = self.ap.curr_stmt.kind
273276
&& let hir::PatKind::Binding(_, hir_id, ident, _) = local.pat.kind
274277
&& !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)