mirror of
https://github.com/rust-lang/rust.git
synced 2026-05-04 01:42:54 +03:00
Do not recurse forever in significant_drop_tightening
Limit the recursion depth, as each level of nesting adds another deeper projection.
This commit is contained in:
@@ -144,7 +144,10 @@ pub(crate) fn new(cx: &'cx LateContext<'tcx>, type_cache: &'others mut FxHashMap
|
||||
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 @@ fn has_sig_drop_attr(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
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 @@ fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
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 @@ fn has_sig_drop_attr_uncached(&mut self, ty: Ty<'tcx>) -> bool {
|
||||
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 @@ fn visit_expr(&mut self, expr: &'tcx hir::Expr<'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)
|
||||
|
||||
@@ -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() {}
|
||||
@@ -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() {}
|
||||
Reference in New Issue
Block a user