Skip to content

Commit d20646b

Browse files
committed
Address review comments
* Handle arrays with const-generic lengths * Use closure for repeated code.
1 parent d196521 commit d20646b

File tree

2 files changed

+36
-32
lines changed

2 files changed

+36
-32
lines changed

src/librustc/ty/util.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use rustc_hir::def::DefKind;
1818
use rustc_hir::def_id::DefId;
1919
use rustc_macros::HashStable;
2020
use rustc_span::Span;
21+
use rustc_target::abi::TargetDataLayout;
2122
use smallvec::SmallVec;
2223
use std::{cmp, fmt};
2324
use syntax::ast;
@@ -726,7 +727,7 @@ impl<'tcx> ty::TyS<'tcx> {
726727
#[inline]
727728
pub fn needs_drop(&'tcx self, tcx: TyCtxt<'tcx>, param_env: ty::ParamEnv<'tcx>) -> bool {
728729
// Avoid querying in simple cases.
729-
match needs_drop_components(self) {
730+
match needs_drop_components(self, &tcx.data_layout) {
730731
Err(AlwaysRequiresDrop) => true,
731732
Ok(components) => {
732733
let query_ty = match *components {
@@ -736,7 +737,7 @@ impl<'tcx> ty::TyS<'tcx> {
736737
[component_ty] => component_ty,
737738
_ => self,
738739
};
739-
// This doesn't depend on regions, so try to minimize distinct.
740+
// This doesn't depend on regions, so try to minimize distinct
740741
// query keys used.
741742
let erased = tcx.normalize_erasing_regions(param_env, query_ty);
742743
tcx.needs_drop_raw(param_env.and(erased))
@@ -992,7 +993,10 @@ impl<'tcx> ExplicitSelf<'tcx> {
992993
/// Returns a list of types such that the given type needs drop if and only if
993994
/// *any* of the returned types need drop. Returns `Err(AlwaysRequiresDrop)` if
994995
/// this type always needs drop.
995-
pub fn needs_drop_components(ty: Ty<'tcx>) -> Result<SmallVec<[Ty<'tcx>; 4]>, AlwaysRequiresDrop> {
996+
pub fn needs_drop_components(
997+
ty: Ty<'tcx>,
998+
target_layout: &TargetDataLayout,
999+
) -> Result<SmallVec<[Ty<'tcx>; 2]>, AlwaysRequiresDrop> {
9961000
match ty.kind {
9971001
ty::Infer(ty::FreshIntTy(_))
9981002
| ty::Infer(ty::FreshFloatTy(_))
@@ -1017,18 +1021,25 @@ pub fn needs_drop_components(ty: Ty<'tcx>) -> Result<SmallVec<[Ty<'tcx>; 4]>, Al
10171021
// state transformation pass
10181022
ty::Generator(..) | ty::Dynamic(..) | ty::Error => Err(AlwaysRequiresDrop),
10191023

1020-
ty::Slice(ty) => needs_drop_components(ty),
1021-
ty::Array(elem_ty, ..) => {
1022-
match needs_drop_components(elem_ty) {
1024+
ty::Slice(ty) => needs_drop_components(ty, target_layout),
1025+
ty::Array(elem_ty, size) => {
1026+
match needs_drop_components(elem_ty, target_layout) {
10231027
Ok(v) if v.is_empty() => Ok(v),
1024-
// Arrays of size zero don't need drop, even if their element
1025-
// type does.
1026-
_ => Ok(smallvec![ty]),
1028+
res => match size.val.try_to_bits(target_layout.pointer_size) {
1029+
// Arrays of size zero don't need drop, even if their element
1030+
// type does.
1031+
Some(0) => Ok(SmallVec::new()),
1032+
Some(_) => res,
1033+
// We don't know which of the cases above we are in, so
1034+
// return the whole type and let the caller decide what to
1035+
// do.
1036+
None => Ok(smallvec![ty]),
1037+
},
10271038
}
10281039
}
10291040
// If any field needs drop, then the whole tuple does.
1030-
ty::Tuple(..) => ty.tuple_fields().try_fold(SmallVec::new(), |mut acc, elem| {
1031-
acc.extend(needs_drop_components(elem)?);
1041+
ty::Tuple(..) => ty.tuple_fields().try_fold(SmallVec::new(), move |mut acc, elem| {
1042+
acc.extend(needs_drop_components(elem, target_layout)?);
10321043
Ok(acc)
10331044
}),
10341045

src/librustc_ty/needs_drop.rs

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -76,30 +76,25 @@ where
7676
return Some(Err(AlwaysRequiresDrop));
7777
}
7878

79-
let components = match needs_drop_components(ty) {
79+
let components = match needs_drop_components(ty, &tcx.data_layout) {
8080
Err(e) => return Some(Err(e)),
8181
Ok(components) => components,
8282
};
8383
debug!("needs_drop_components({:?}) = {:?}", ty, components);
8484

85+
let queue_type = move |this: &mut Self, component: Ty<'tcx>| {
86+
if this.seen_tys.insert(component) {
87+
this.unchecked_tys.push((component, level + 1));
88+
}
89+
};
90+
8591
for component in components {
8692
match component.kind {
8793
_ if component.is_copy_modulo_regions(tcx, self.param_env, DUMMY_SP) => (),
8894

89-
ty::Array(elem_ty, len) => {
90-
// Zero-length arrays never contain anything to drop.
91-
if len.try_eval_usize(tcx, self.param_env) != Some(0) {
92-
if self.seen_tys.insert(elem_ty) {
93-
self.unchecked_tys.push((elem_ty, level + 1));
94-
}
95-
}
96-
}
97-
9895
ty::Closure(def_id, substs) => {
9996
for upvar_ty in substs.as_closure().upvar_tys(def_id, tcx) {
100-
if self.seen_tys.insert(upvar_ty) {
101-
self.unchecked_tys.push((upvar_ty, level + 1));
102-
}
97+
queue_type(self, upvar_ty);
10398
}
10499
}
105100

@@ -116,21 +111,19 @@ where
116111
self.param_env,
117112
required_ty.subst(tcx, substs),
118113
);
119-
if self.seen_tys.insert(subst_ty) {
120-
self.unchecked_tys.push((subst_ty, level + 1));
121-
}
114+
queue_type(self, subst_ty);
122115
}
123116
}
124-
ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
117+
ty::Array(..) | ty::Opaque(..) | ty::Projection(..) | ty::Param(_) => {
125118
if ty == component {
126-
// Return the type to the caller so they can decide
127-
// what to do with it.
119+
// Return the type to the caller: they may be able
120+
// to normalize further than we can.
128121
return Some(Ok(component));
129-
} else if self.seen_tys.insert(component) {
122+
} else {
130123
// Store the type for later. We can't return here
131124
// because we would then lose any other components
132125
// of the type.
133-
self.unchecked_tys.push((component, level + 1));
126+
queue_type(self, component);
134127
}
135128
}
136129
_ => return Some(Err(AlwaysRequiresDrop)),

0 commit comments

Comments
 (0)