Skip to content

Commit f1dee65

Browse files
fitzgenKowasaki
authored andcommitted
Factor the UsedTemplateParameters::constrain method into smaller functions
The method was getting fairly large, and it is a little easier to read if we break it down into smaller parts.
1 parent a1c94c6 commit f1dee65

File tree

1 file changed

+108
-89
lines changed

1 file changed

+108
-89
lines changed

src/ir/named.rs

Lines changed: 108 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@
127127
//! [spa]: https://cs.au.dk/~amoeller/spa/spa.pdf
128128
129129
use super::context::{BindgenContext, ItemId};
130-
use super::item::ItemSet;
131-
use super::template::AsNamed;
130+
use super::item::{Item, ItemSet};
131+
use super::template::{AsNamed, TemplateInstantiation};
132132
use super::traversal::{EdgeKind, Trace};
133133
use super::ty::{TemplateDeclaration, TypeKind};
134134
use std::collections::{HashMap, HashSet};
@@ -307,6 +307,103 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
307307
EdgeKind::Generic => false,
308308
}
309309
}
310+
311+
fn take_this_id_usage_set(&mut self, this_id: ItemId) -> ItemSet {
312+
self.used
313+
.get_mut(&this_id)
314+
.expect("Should have a set of used template params for every item \
315+
id")
316+
.take()
317+
.expect("Should maintain the invariant that all used template param \
318+
sets are `Some` upon entry of `constrain`")
319+
}
320+
321+
/// We say that blacklisted items use all of their template parameters. The
322+
/// blacklisted type is most likely implemented explicitly by the user,
323+
/// since it won't be in the generated bindings, and we don't know exactly
324+
/// what they'll to with template parameters, but we can push the issue down
325+
/// the line to them.
326+
fn constrain_instantiation_of_blacklisted_template(&self,
327+
used_by_this_id: &mut ItemSet,
328+
instantiation: &TemplateInstantiation) {
329+
debug!(" instantiation of blacklisted template, uses all template \
330+
arguments");
331+
332+
let args = instantiation.template_arguments()
333+
.iter()
334+
.filter_map(|a| a.as_named(self.ctx, &()));
335+
used_by_this_id.extend(args);
336+
}
337+
338+
/// A template instantiation's concrete template argument is only used if
339+
/// the template definition uses the corresponding template parameter.
340+
fn constrain_instantiation(&self,
341+
used_by_this_id: &mut ItemSet,
342+
instantiation: &TemplateInstantiation) {
343+
debug!(" template instantiation");
344+
345+
let decl = self.ctx.resolve_type(instantiation.template_definition());
346+
let args = instantiation.template_arguments();
347+
348+
let params = decl.self_template_params(self.ctx)
349+
.unwrap_or(vec![]);
350+
351+
let used_by_def = self.used[&instantiation.template_definition()]
352+
.as_ref()
353+
.unwrap();
354+
355+
for (arg, param) in args.iter().zip(params.iter()) {
356+
debug!(" instantiation's argument {:?} is used if definition's \
357+
parameter {:?} is used",
358+
arg,
359+
param);
360+
361+
if used_by_def.contains(param) {
362+
debug!(" param is used by template definition");
363+
364+
let arg = arg.into_resolver()
365+
.through_type_refs()
366+
.through_type_aliases()
367+
.resolve(self.ctx);
368+
if let Some(named) = arg.as_named(self.ctx, &()) {
369+
debug!(" arg is a type parameter, marking used");
370+
used_by_this_id.insert(named);
371+
}
372+
}
373+
}
374+
}
375+
376+
/// The join operation on our lattice: the set union of all of this id's
377+
/// successors.
378+
fn constrain_join(&self, used_by_this_id: &mut ItemSet, item: &Item) {
379+
debug!(" other item: join with successors' usage");
380+
381+
item.trace(self.ctx, &mut |sub_id, edge_kind| {
382+
// Ignore ourselves, since union with ourself is a
383+
// no-op. Ignore edges that aren't relevant to the
384+
// analysis. Ignore edges to blacklisted items.
385+
if sub_id == item.id() ||
386+
!Self::consider_edge(edge_kind) ||
387+
!self.whitelisted_items.contains(&sub_id) {
388+
return;
389+
}
390+
391+
let used_by_sub_id = self.used[&sub_id]
392+
.as_ref()
393+
.expect("Because sub_id != id, and all used template \
394+
param sets other than id's are `Some`, \
395+
sub_id's used template param set should be \
396+
`Some`")
397+
.iter()
398+
.cloned();
399+
400+
debug!(" union with {:?}'s usage: {:?}",
401+
sub_id,
402+
used_by_sub_id.clone().collect::<Vec<_>>());
403+
404+
used_by_this_id.extend(used_by_sub_id);
405+
}, &());
406+
}
310407
}
311408

312409
impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
@@ -418,13 +515,7 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
418515
// on other hash map entries. We *must* put it back into the hash map at
419516
// the end of this method. This allows us to side-step HashMap's lack of
420517
// an analog to slice::split_at_mut.
421-
let mut used_by_this_id = self.used
422-
.get_mut(&id)
423-
.expect("Should have a set of used template params for every item \
424-
id")
425-
.take()
426-
.expect("Should maintain the invariant that all used template param \
427-
sets are `Some` upon entry of `constrain`");
518+
let mut used_by_this_id = self.take_this_id_usage_set(id);
428519

429520
debug!("constrain {:?}", id);
430521
debug!(" initially, used set is {:?}", used_by_this_id);
@@ -439,91 +530,19 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
439530
debug!(" named type, trivially uses itself");
440531
used_by_this_id.insert(id);
441532
}
442-
443-
// We say that blacklisted items use all of their template
444-
// parameters. The blacklisted type is most likely implemented
445-
// explicitly by the user, since it won't be in the generated
446-
// bindings, and we don't know exactly what they'll to with template
447-
// parameters, but we can push the issue down the line to them.
448-
Some(&TypeKind::TemplateInstantiation(ref inst))
449-
if !self.whitelisted_items.contains(&inst.template_definition()) => {
450-
debug!(" instantiation of blacklisted template, uses all template \
451-
arguments");
452-
453-
let args = inst.template_arguments()
454-
.iter()
455-
.filter_map(|a| a.as_named(self.ctx, &()));
456-
used_by_this_id.extend(args);
457-
}
458-
459-
// A template instantiation's concrete template argument is
460-
// only used if the template declaration uses the
461-
// corresponding template parameter.
533+
// Template instantiations only use their template arguments if the
534+
// template definition uses the corresponding template parameter.
462535
Some(&TypeKind::TemplateInstantiation(ref inst)) => {
463-
debug!(" template instantiation");
464-
465-
let decl = self.ctx.resolve_type(inst.template_definition());
466-
let args = inst.template_arguments();
467-
468-
let params = decl.self_template_params(self.ctx)
469-
.unwrap_or(vec![]);
470-
471-
let used_by_def = self.used[&inst.template_definition()]
472-
.as_ref()
473-
.unwrap();
474-
475-
for (arg, param) in args.iter().zip(params.iter()) {
476-
debug!(" instantiation's argument {:?} is used if definition's \
477-
parameter {:?} is used",
478-
arg,
479-
param);
480-
481-
if used_by_def.contains(param) {
482-
debug!(" param is used by template definition");
483-
484-
let arg = arg.into_resolver()
485-
.through_type_refs()
486-
.through_type_aliases()
487-
.resolve(self.ctx);
488-
if let Some(named) = arg.as_named(self.ctx, &()) {
489-
debug!(" arg is a type parameter, marking used");
490-
used_by_this_id.insert(named);
491-
}
492-
}
536+
if self.whitelisted_items.contains(&inst.template_definition()) {
537+
self.constrain_instantiation(&mut used_by_this_id, inst);
538+
} else {
539+
self.constrain_instantiation_of_blacklisted_template(&mut used_by_this_id,
540+
inst);
493541
}
494542
}
495-
496543
// Otherwise, add the union of each of its referent item's template
497544
// parameter usage.
498-
_ => {
499-
debug!(" other item: join with successors' usage");
500-
501-
item.trace(self.ctx, &mut |sub_id, edge_kind| {
502-
// Ignore ourselves, since union with ourself is a
503-
// no-op. Ignore edges that aren't relevant to the
504-
// analysis. Ignore edges to blacklisted items.
505-
if sub_id == id ||
506-
!Self::consider_edge(edge_kind) ||
507-
!self.whitelisted_items.contains(&sub_id) {
508-
return;
509-
}
510-
511-
let used_by_sub_id = self.used[&sub_id]
512-
.as_ref()
513-
.expect("Because sub_id != id, and all used template \
514-
param sets other than id's are `Some`, \
515-
sub_id's used template param set should be \
516-
`Some`")
517-
.iter()
518-
.cloned();
519-
520-
debug!(" union with {:?}'s usage: {:?}",
521-
sub_id,
522-
used_by_sub_id.clone().collect::<Vec<_>>());
523-
524-
used_by_this_id.extend(used_by_sub_id);
525-
}, &());
526-
}
545+
_ => self.constrain_join(&mut used_by_this_id, item),
527546
}
528547

529548
debug!(" finally, used set is {:?}", used_by_this_id);

0 commit comments

Comments
 (0)