Skip to content

Commit 680094a

Browse files
author
bors-servo
authored
Auto merge of #830 - fitzgen:little-analysis-cleanups, r=emilio
A bunch of little analysis cleanups Some of these I'd been meaning to do for a while and just never got around to. Others are my own ultra nitpicks that I could never feel OK actually leaving in a review, but still want to make anyways :-P r? @emilio
2 parents 9dbc2ca + faebc0c commit 680094a

File tree

7 files changed

+303
-236
lines changed

7 files changed

+303
-236
lines changed

src/codegen/mod.rs

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3275,19 +3275,17 @@ impl CodeGenerator for ObjCInterface {
32753275
}
32763276
}
32773277

3278-
3279-
32803278
pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
32813279
context.gen(|context| {
32823280
let counter = Cell::new(0);
32833281
let mut result = CodegenResult::new(&counter);
32843282

32853283
debug!("codegen: {:?}", context.options());
32863284

3287-
let whitelisted_items: ItemSet = context.whitelisted_items().collect();
3285+
let whitelisted_items = context.whitelisted_items();
32883286

32893287
if context.options().emit_ir {
3290-
for &id in whitelisted_items.iter() {
3288+
for &id in whitelisted_items {
32913289
let item = context.resolve_item(id);
32923290
println!("ir: {:?} = {:#?}", id, item);
32933291
}
@@ -3301,7 +3299,7 @@ pub fn codegen(context: &mut BindgenContext) -> Vec<P<ast::Item>> {
33013299
}
33023300

33033301
context.resolve_item(context.root_module())
3304-
.codegen(context, &mut result, &whitelisted_items, &());
3302+
.codegen(context, &mut result, whitelisted_items, &());
33053303

33063304
result.items
33073305
})
Lines changed: 107 additions & 94 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
//! Determining which types for which we can emit `#[derive(Debug)]`.
2-
use super::analysis::MonotoneFramework;
3-
use ir::context::{BindgenContext, ItemId};
4-
use ir::item::ItemSet;
2+
3+
use super::{ConstrainResult, MonotoneFramework};
54
use std::collections::HashSet;
65
use std::collections::HashMap;
6+
use ir::context::{BindgenContext, ItemId};
77
use ir::traversal::EdgeKind;
88
use ir::ty::RUST_DERIVE_IN_ARRAY_LIMIT;
99
use ir::ty::TypeKind;
@@ -16,7 +16,7 @@ use ir::comp::CompKind;
1616

1717
/// An analysis that finds for each IR item whether debug cannot be derived.
1818
///
19-
/// We use the monotone constraint function `cant_derive_debug`, defined as
19+
/// We use the monotone constraint function `cannot_derive_debug`, defined as
2020
/// follows:
2121
///
2222
/// * If T is Opaque and layout of the type is known, get this layout as opaque
@@ -34,17 +34,17 @@ use ir::comp::CompKind;
3434
/// derived debug if any of the template arguments or template definition
3535
/// cannot derive debug.
3636
#[derive(Debug, Clone)]
37-
pub struct CantDeriveDebugAnalysis<'ctx, 'gen>
37+
pub struct CannotDeriveDebug<'ctx, 'gen>
3838
where 'gen: 'ctx
3939
{
4040
ctx: &'ctx BindgenContext<'gen>,
4141

4242
// The incremental result of this analysis's computation. Everything in this
4343
// set cannot derive debug.
44-
cant_derive_debug: HashSet<ItemId>,
44+
cannot_derive_debug: HashSet<ItemId>,
4545

4646
// Dependencies saying that if a key ItemId has been inserted into the
47-
// `cant_derive_debug` set, then each of the ids in Vec<ItemId> need to be
47+
// `cannot_derive_debug` set, then each of the ids in Vec<ItemId> need to be
4848
// considered again.
4949
//
5050
// This is a subset of the natural IR graph with reversed edges, where we
@@ -53,7 +53,7 @@ pub struct CantDeriveDebugAnalysis<'ctx, 'gen>
5353
dependencies: HashMap<ItemId, Vec<ItemId>>,
5454
}
5555

56-
impl<'ctx, 'gen> CantDeriveDebugAnalysis<'ctx, 'gen> {
56+
impl<'ctx, 'gen> CannotDeriveDebug<'ctx, 'gen> {
5757
fn consider_edge(kind: EdgeKind) -> bool {
5858
match kind {
5959
// These are the only edges that can affect whether a type can derive
@@ -77,79 +77,69 @@ impl<'ctx, 'gen> CantDeriveDebugAnalysis<'ctx, 'gen> {
7777
}
7878
}
7979

80-
fn insert(&mut self, id: ItemId) -> bool {
81-
let was_already_in = self.cant_derive_debug.insert(id);
80+
fn insert(&mut self, id: ItemId) -> ConstrainResult {
81+
let was_not_already_in_set = self.cannot_derive_debug.insert(id);
8282
assert!(
83-
was_already_in,
84-
format!("We shouldn't try and insert twice because if it was already in the set, \
85-
`constrain` would have exited early.: {:?}", id)
83+
was_not_already_in_set,
84+
"We shouldn't try and insert {:?} twice because if it was \
85+
already in the set, `constrain` should have exited early.",
86+
id
8687
);
87-
true
88+
ConstrainResult::Changed
8889
}
8990
}
9091

91-
impl<'ctx, 'gen> MonotoneFramework for CantDeriveDebugAnalysis<'ctx, 'gen> {
92+
impl<'ctx, 'gen> MonotoneFramework for CannotDeriveDebug<'ctx, 'gen> {
9293
type Node = ItemId;
9394
type Extra = &'ctx BindgenContext<'gen>;
9495
type Output = HashSet<ItemId>;
9596

96-
fn new(ctx: &'ctx BindgenContext<'gen>) -> CantDeriveDebugAnalysis<'ctx, 'gen> {
97-
let cant_derive_debug = HashSet::new();
97+
fn new(ctx: &'ctx BindgenContext<'gen>) -> CannotDeriveDebug<'ctx, 'gen> {
98+
let cannot_derive_debug = HashSet::new();
9899
let mut dependencies = HashMap::new();
99-
let whitelisted_items: HashSet<_> = ctx.whitelisted_items().collect();
100-
101-
let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items.iter()
102-
.cloned()
103-
.flat_map(|i| {
104-
let mut reachable = vec![i];
105-
i.trace(ctx, &mut |s, _| {
106-
reachable.push(s);
107-
}, &());
108-
reachable
109-
})
110-
.collect();
111100

112-
for item in whitelisted_and_blacklisted_items {
101+
for &item in ctx.whitelisted_items() {
113102
dependencies.entry(item).or_insert(vec![]);
114103

115104
{
116105
// We reverse our natural IR graph edges to find dependencies
117106
// between nodes.
118107
item.trace(ctx, &mut |sub_item: ItemId, edge_kind| {
119-
if Self::consider_edge(edge_kind) {
120-
dependencies.entry(sub_item)
121-
.or_insert(vec![])
122-
.push(item);
108+
if ctx.whitelisted_items().contains(&sub_item) &&
109+
Self::consider_edge(edge_kind) {
110+
dependencies.entry(sub_item)
111+
.or_insert(vec![])
112+
.push(item);
123113
}
124114
}, &());
125115
}
126116
}
127117

128-
CantDeriveDebugAnalysis {
129-
ctx: ctx,
130-
cant_derive_debug: cant_derive_debug,
131-
dependencies: dependencies,
118+
CannotDeriveDebug {
119+
ctx,
120+
cannot_derive_debug,
121+
dependencies,
132122
}
133123
}
134124

135125
fn initial_worklist(&self) -> Vec<ItemId> {
136-
self.ctx.whitelisted_items().collect()
126+
self.ctx.whitelisted_items().iter().cloned().collect()
137127
}
138128

139-
fn constrain(&mut self, id: ItemId) -> bool {
140-
if self.cant_derive_debug.contains(&id) {
141-
return false;
129+
fn constrain(&mut self, id: ItemId) -> ConstrainResult {
130+
if self.cannot_derive_debug.contains(&id) {
131+
return ConstrainResult::Same;
142132
}
143133

144134
let item = self.ctx.resolve_item(id);
145135
let ty = match item.as_type() {
146-
None => return false,
136+
None => return ConstrainResult::Same,
147137
Some(ty) => ty
148138
};
149139

150140
match *ty.kind() {
151-
// handle the simple case
152-
// These can derive debug without further information
141+
// Handle the simple cases. These can derive debug without further
142+
// information.
153143
TypeKind::Void |
154144
TypeKind::NullPtr |
155145
TypeKind::Int(..) |
@@ -164,97 +154,113 @@ impl<'ctx, 'gen> MonotoneFramework for CantDeriveDebugAnalysis<'ctx, 'gen> {
164154
TypeKind::ObjCInterface(..) |
165155
TypeKind::ObjCId |
166156
TypeKind::ObjCSel => {
167-
return false;
157+
ConstrainResult::Same
168158
},
159+
169160
TypeKind::Opaque => {
170161
if ty.layout(self.ctx)
171162
.map_or(true, |l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
172-
return false;
163+
ConstrainResult::Same
173164
} else {
174-
return self.insert(id);
165+
self.insert(id)
175166
}
176167
},
168+
177169
TypeKind::Array(t, len) => {
170+
if self.cannot_derive_debug.contains(&t) {
171+
return self.insert(id);
172+
}
173+
178174
if len <= RUST_DERIVE_IN_ARRAY_LIMIT {
179-
if self.cant_derive_debug.contains(&t) {
180-
return self.insert(id);
181-
}
182-
return false;
175+
ConstrainResult::Same
183176
} else {
184-
return self.insert(id);
177+
self.insert(id)
185178
}
186179
},
180+
187181
TypeKind::ResolvedTypeRef(t) |
188182
TypeKind::TemplateAlias(t, _) |
189183
TypeKind::Alias(t) => {
190-
if self.cant_derive_debug.contains(&t) {
191-
return self.insert(id);
184+
if self.cannot_derive_debug.contains(&t) {
185+
self.insert(id)
186+
} else {
187+
ConstrainResult::Same
192188
}
193-
return false;
194189
},
190+
195191
TypeKind::Comp(ref info) => {
196192
if info.has_non_type_template_params() {
197-
if ty.layout(self.ctx).map_or(true,
198-
|l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
199-
return false;
193+
if ty.layout(self.ctx)
194+
.map_or(true,
195+
|l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
196+
return ConstrainResult::Same;
200197
} else {
201198
return self.insert(id);
202199
}
203200
}
201+
204202
if info.kind() == CompKind::Union {
205203
if self.ctx.options().unstable_rust {
206204
return self.insert(id);
207205
}
208206

209-
if ty.layout(self.ctx).map_or(true,
210-
|l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
211-
return false;
207+
if ty.layout(self.ctx)
208+
.map_or(true,
209+
|l| l.opaque().can_trivially_derive_debug(self.ctx, ())) {
210+
return ConstrainResult::Same;
212211
} else {
213212
return self.insert(id);
214213
}
215214
}
216-
let bases_cant_derive = info.base_members()
215+
216+
let bases_cannot_derive = info.base_members()
217217
.iter()
218-
.any(|base| self.cant_derive_debug.contains(&base.ty));
219-
if bases_cant_derive {
218+
.any(|base| self.cannot_derive_debug.contains(&base.ty));
219+
if bases_cannot_derive {
220220
return self.insert(id);
221221
}
222-
let fields_cant_derive = info.fields()
222+
223+
let fields_cannot_derive = info.fields()
223224
.iter()
224225
.any(|f| {
225-
match f {
226-
&Field::DataMember(ref data) => self.cant_derive_debug.contains(&data.ty()),
227-
&Field::Bitfields(ref bfu) => bfu.bitfields()
228-
.iter().any(|b| {
229-
self.cant_derive_debug.contains(&b.ty())
230-
})
226+
match *f {
227+
Field::DataMember(ref data) => {
228+
self.cannot_derive_debug.contains(&data.ty())
229+
}
230+
Field::Bitfields(ref bfu) => {
231+
bfu.bitfields()
232+
.iter().any(|b| {
233+
self.cannot_derive_debug.contains(&b.ty())
234+
})
235+
}
231236
}
232237
});
233-
if fields_cant_derive {
238+
if fields_cannot_derive {
234239
return self.insert(id);
235240
}
236-
false
241+
242+
ConstrainResult::Same
237243
},
244+
238245
TypeKind::Pointer(inner) => {
239-
let inner_type = self.ctx.resolve_type(inner);
240-
if let TypeKind::Function(ref sig) =
241-
*inner_type.canonical_type(self.ctx).kind() {
242-
if sig.can_trivially_derive_debug(&self.ctx, ()) {
243-
return false;
244-
} else {
245-
return self.insert(id);
246-
}
246+
let inner_type = self.ctx.resolve_type(inner).canonical_type(self.ctx);
247+
if let TypeKind::Function(ref sig) = *inner_type.kind() {
248+
if !sig.can_trivially_derive_debug(&self.ctx, ()) {
249+
return self.insert(id);
247250
}
248-
false
251+
}
252+
ConstrainResult::Same
249253
},
254+
250255
TypeKind::TemplateInstantiation(ref template) => {
251-
let args_cant_derive = template.template_arguments()
256+
let args_cannot_derive = template.template_arguments()
252257
.iter()
253-
.any(|arg| self.cant_derive_debug.contains(&arg));
254-
if args_cant_derive {
258+
.any(|arg| self.cannot_derive_debug.contains(&arg));
259+
if args_cannot_derive {
255260
return self.insert(id);
256261
}
257-
let ty_cant_derive = template.template_definition()
262+
263+
let ty_cannot_derive = template.template_definition()
258264
.into_resolver()
259265
.through_type_refs()
260266
.through_type_aliases()
@@ -268,19 +274,26 @@ impl<'ctx, 'gen> MonotoneFramework for CantDeriveDebugAnalysis<'ctx, 'gen> {
268274
// idea of the layout than the definition does.
269275
if c.has_non_type_template_params() {
270276
let opaque = ty.layout(self.ctx)
271-
.or_else(|| self.ctx.resolve_type(template.template_definition()).layout(self.ctx))
277+
.or_else(|| {
278+
self.ctx
279+
.resolve_type(template.template_definition())
280+
.layout(self.ctx)
281+
})
272282
.unwrap_or(Layout::zero())
273283
.opaque();
274284
Some(!opaque.can_trivially_derive_debug(&self.ctx, ()))
275285
} else {
276286
None
277287
}
278288
})
279-
.unwrap_or_else(|| self.cant_derive_debug.contains(&template.template_definition()));
280-
if ty_cant_derive {
289+
.unwrap_or_else(|| {
290+
self.cannot_derive_debug.contains(&template.template_definition())
291+
});
292+
if ty_cannot_derive {
281293
return self.insert(id);
282294
}
283-
false
295+
296+
ConstrainResult::Same
284297
},
285298
}
286299
}
@@ -297,8 +310,8 @@ impl<'ctx, 'gen> MonotoneFramework for CantDeriveDebugAnalysis<'ctx, 'gen> {
297310
}
298311
}
299312

300-
impl<'ctx, 'gen> From<CantDeriveDebugAnalysis<'ctx, 'gen>> for HashSet<ItemId> {
301-
fn from(analysis: CantDeriveDebugAnalysis<'ctx, 'gen>) -> Self {
302-
analysis.cant_derive_debug
313+
impl<'ctx, 'gen> From<CannotDeriveDebug<'ctx, 'gen>> for HashSet<ItemId> {
314+
fn from(analysis: CannotDeriveDebug<'ctx, 'gen>) -> Self {
315+
analysis.cannot_derive_debug
303316
}
304317
}

0 commit comments

Comments
 (0)