summaryrefslogtreecommitdiff
path: root/src/ir/analysis/template_params.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/ir/analysis/template_params.rs')
-rw-r--r--src/ir/analysis/template_params.rs272
1 files changed, 156 insertions, 116 deletions
diff --git a/src/ir/analysis/template_params.rs b/src/ir/analysis/template_params.rs
index 44878d9e..caaa8f30 100644
--- a/src/ir/analysis/template_params.rs
+++ b/src/ir/analysis/template_params.rs
@@ -147,7 +147,8 @@ use std::collections::{HashMap, HashSet};
/// documentation for details.
#[derive(Debug, Clone)]
pub struct UsedTemplateParameters<'ctx, 'gen>
- where 'gen: 'ctx,
+where
+ 'gen: 'ctx,
{
ctx: &'ctx BindgenContext<'gen>,
@@ -208,11 +209,15 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
fn take_this_id_usage_set(&mut self, this_id: ItemId) -> ItemSet {
self.used
.get_mut(&this_id)
- .expect("Should have a set of used template params for every item \
- id")
+ .expect(
+ "Should have a set of used template params for every item \
+ id",
+ )
.take()
- .expect("Should maintain the invariant that all used template param \
- sets are `Some` upon entry of `constrain`")
+ .expect(
+ "Should maintain the invariant that all used template param \
+ sets are `Some` upon entry of `constrain`",
+ )
}
/// We say that blacklisted items use all of their template parameters. The
@@ -220,14 +225,19 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
/// since it won't be in the generated bindings, and we don't know exactly
/// what they'll to with template parameters, but we can push the issue down
/// the line to them.
- fn constrain_instantiation_of_blacklisted_template(&self,
- this_id: ItemId,
- used_by_this_id: &mut ItemSet,
- instantiation: &TemplateInstantiation) {
- trace!(" instantiation of blacklisted template, uses all template \
- arguments");
-
- let args = instantiation.template_arguments()
+ fn constrain_instantiation_of_blacklisted_template(
+ &self,
+ this_id: ItemId,
+ used_by_this_id: &mut ItemSet,
+ instantiation: &TemplateInstantiation,
+ ) {
+ trace!(
+ " instantiation of blacklisted template, uses all template \
+ arguments"
+ );
+
+ let args = instantiation
+ .template_arguments()
.into_iter()
.map(|a| {
a.into_resolver()
@@ -238,12 +248,15 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
})
.filter(|a| *a != this_id)
.flat_map(|a| {
- self.used.get(&a)
+ self.used
+ .get(&a)
.expect("Should have a used entry for the template arg")
.as_ref()
- .expect("Because a != this_id, and all used template \
+ .expect(
+ "Because a != this_id, and all used template \
param sets other than this_id's are `Some`, \
- a's used template param set should be `Some`")
+ a's used template param set should be `Some`",
+ )
.iter()
.cloned()
});
@@ -253,17 +266,18 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
/// A template instantiation's concrete template argument is only used if
/// the template definition uses the corresponding template parameter.
- fn constrain_instantiation(&self,
- this_id: ItemId,
- used_by_this_id: &mut ItemSet,
- instantiation: &TemplateInstantiation) {
+ fn constrain_instantiation(
+ &self,
+ this_id: ItemId,
+ used_by_this_id: &mut ItemSet,
+ instantiation: &TemplateInstantiation,
+ ) {
trace!(" template instantiation");
let decl = self.ctx.resolve_type(instantiation.template_definition());
let args = instantiation.template_arguments();
- let params = decl.self_template_params(self.ctx)
- .unwrap_or(vec![]);
+ let params = decl.self_template_params(self.ctx).unwrap_or(vec![]);
debug_assert!(this_id != instantiation.template_definition());
let used_by_def = self.used
@@ -275,10 +289,12 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
instantiation itself");
for (arg, param) in args.iter().zip(params.iter()) {
- trace!(" instantiation's argument {:?} is used if definition's \
+ trace!(
+ " instantiation's argument {:?} is used if definition's \
parameter {:?} is used",
- arg,
- param);
+ arg,
+ param
+ );
if used_by_def.contains(param) {
trace!(" param is used by template definition");
@@ -297,10 +313,12 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
.get(&arg)
.expect("Should have a used entry for the template arg")
.as_ref()
- .expect("Because arg != this_id, and all used template \
+ .expect(
+ "Because arg != this_id, and all used template \
param sets other than this_id's are `Some`, \
arg's used template param set should be \
- `Some`")
+ `Some`",
+ )
.iter()
.cloned();
used_by_this_id.extend(used_by_arg);
@@ -313,31 +331,39 @@ impl<'ctx, 'gen> UsedTemplateParameters<'ctx, 'gen> {
fn constrain_join(&self, used_by_this_id: &mut ItemSet, item: &Item) {
trace!(" other item: join with successors' usage");
- item.trace(self.ctx, &mut |sub_id, edge_kind| {
- // Ignore ourselves, since union with ourself is a
- // no-op. Ignore edges that aren't relevant to the
- // analysis.
- if sub_id == item.id() || !Self::consider_edge(edge_kind) {
- return;
- }
+ item.trace(
+ self.ctx,
+ &mut |sub_id, edge_kind| {
+ // Ignore ourselves, since union with ourself is a
+ // no-op. Ignore edges that aren't relevant to the
+ // analysis.
+ if sub_id == item.id() || !Self::consider_edge(edge_kind) {
+ return;
+ }
- let used_by_sub_id = self.used
- .get(&sub_id)
- .expect("Should have a used set for the sub_id successor")
- .as_ref()
- .expect("Because sub_id != id, and all used template \
+ let used_by_sub_id = self.used
+ .get(&sub_id)
+ .expect("Should have a used set for the sub_id successor")
+ .as_ref()
+ .expect(
+ "Because sub_id != id, and all used template \
param sets other than id's are `Some`, \
sub_id's used template param set should be \
- `Some`")
- .iter()
- .cloned();
+ `Some`",
+ )
+ .iter()
+ .cloned();
- trace!(" union with {:?}'s usage: {:?}",
- sub_id,
- used_by_sub_id.clone().collect::<Vec<_>>());
+ trace!(
+ " union with {:?}'s usage: {:?}",
+ sub_id,
+ used_by_sub_id.clone().collect::<Vec<_>>()
+ );
- used_by_this_id.extend(used_by_sub_id);
- }, &());
+ used_by_this_id.extend(used_by_sub_id);
+ },
+ &(),
+ );
}
}
@@ -346,22 +372,20 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
type Extra = &'ctx BindgenContext<'gen>;
type Output = HashMap<ItemId, ItemSet>;
- fn new(ctx: &'ctx BindgenContext<'gen>)
- -> UsedTemplateParameters<'ctx, 'gen> {
+ fn new(
+ ctx: &'ctx BindgenContext<'gen>,
+ ) -> UsedTemplateParameters<'ctx, 'gen> {
let mut used = HashMap::new();
let mut dependencies = HashMap::new();
- let whitelisted_items: HashSet<_> = ctx.whitelisted_items()
- .iter()
- .cloned()
- .collect();
+ let whitelisted_items: HashSet<_> =
+ ctx.whitelisted_items().iter().cloned().collect();
- let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items.iter()
+ let whitelisted_and_blacklisted_items: ItemSet = whitelisted_items
+ .iter()
.cloned()
.flat_map(|i| {
let mut reachable = vec![i];
- i.trace(ctx, &mut |s, _| {
- reachable.push(s);
- }, &());
+ i.trace(ctx, &mut |s, _| { reachable.push(s); }, &());
reachable
})
.collect();
@@ -373,53 +397,54 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
{
// We reverse our natural IR graph edges to find dependencies
// between nodes.
- item.trace(ctx, &mut |sub_item: ItemId, _| {
- used.entry(sub_item).or_insert(Some(ItemSet::new()));
- dependencies.entry(sub_item)
- .or_insert(vec![])
- .push(item);
- }, &());
+ item.trace(
+ ctx,
+ &mut |sub_item: ItemId, _| {
+ used.entry(sub_item).or_insert(Some(ItemSet::new()));
+ dependencies.entry(sub_item).or_insert(vec![]).push(
+ item,
+ );
+ },
+ &(),
+ );
}
// Additionally, whether a template instantiation's template
// arguments are used depends on whether the template declaration's
// generic template parameters are used.
- ctx.resolve_item(item)
- .as_type()
- .map(|ty| match ty.kind() {
- &TypeKind::TemplateInstantiation(ref inst) => {
- let decl = ctx.resolve_type(inst.template_definition());
- let args = inst.template_arguments();
-
- // Although template definitions should always have
- // template parameters, there is a single exception:
- // opaque templates. Hence the unwrap_or.
- let params = decl.self_template_params(ctx)
- .unwrap_or(vec![]);
-
- for (arg, param) in args.iter().zip(params.iter()) {
- let arg = arg.into_resolver()
- .through_type_aliases()
- .through_type_refs()
- .resolve(ctx)
- .id();
-
- let param = param.into_resolver()
- .through_type_aliases()
- .through_type_refs()
- .resolve(ctx)
- .id();
-
- used.entry(arg).or_insert(Some(ItemSet::new()));
- used.entry(param).or_insert(Some(ItemSet::new()));
-
- dependencies.entry(arg)
- .or_insert(vec![])
- .push(param);
- }
+ ctx.resolve_item(item).as_type().map(|ty| match ty.kind() {
+ &TypeKind::TemplateInstantiation(ref inst) => {
+ let decl = ctx.resolve_type(inst.template_definition());
+ let args = inst.template_arguments();
+
+ // Although template definitions should always have
+ // template parameters, there is a single exception:
+ // opaque templates. Hence the unwrap_or.
+ let params =
+ decl.self_template_params(ctx).unwrap_or(vec![]);
+
+ for (arg, param) in args.iter().zip(params.iter()) {
+ let arg = arg.into_resolver()
+ .through_type_aliases()
+ .through_type_refs()
+ .resolve(ctx)
+ .id();
+
+ let param = param
+ .into_resolver()
+ .through_type_aliases()
+ .through_type_refs()
+ .resolve(ctx)
+ .id();
+
+ used.entry(arg).or_insert(Some(ItemSet::new()));
+ used.entry(param).or_insert(Some(ItemSet::new()));
+
+ dependencies.entry(arg).or_insert(vec![]).push(param);
}
- _ => {}
- });
+ }
+ _ => {}
+ });
}
if cfg!(feature = "testing_only_extra_assertions") {
@@ -436,10 +461,14 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
for item in whitelisted_items.iter() {
extra_assert!(used.contains_key(item));
extra_assert!(dependencies.contains_key(item));
- item.trace(ctx, &mut |sub_item, _| {
- extra_assert!(used.contains_key(&sub_item));
- extra_assert!(dependencies.contains_key(&sub_item));
- }, &())
+ item.trace(
+ ctx,
+ &mut |sub_item, _| {
+ extra_assert!(used.contains_key(&sub_item));
+ extra_assert!(dependencies.contains_key(&sub_item));
+ },
+ &(),
+ )
}
}
@@ -460,9 +489,7 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
.cloned()
.flat_map(|i| {
let mut reachable = vec![i];
- i.trace(self.ctx, &mut |s, _| {
- reachable.push(s);
- }, &());
+ i.trace(self.ctx, &mut |s, _| { reachable.push(s); }, &());
reachable
})
.collect()
@@ -488,19 +515,28 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
let ty_kind = item.as_type().map(|ty| ty.kind());
match ty_kind {
// Named template type parameters trivially use themselves.
- Some(&TypeKind::Named) => {
+ Some(&TypeKind::TypeParam) => {
trace!(" named type, trivially uses itself");
used_by_this_id.insert(id);
}
// Template instantiations only use their template arguments if the
// template definition uses the corresponding template parameter.
Some(&TypeKind::TemplateInstantiation(ref inst)) => {
- if self.whitelisted_items.contains(&inst.template_definition()) {
- self.constrain_instantiation(id, &mut used_by_this_id, inst);
+ if self.whitelisted_items.contains(
+ &inst.template_definition(),
+ )
+ {
+ self.constrain_instantiation(
+ id,
+ &mut used_by_this_id,
+ inst,
+ );
} else {
- self.constrain_instantiation_of_blacklisted_template(id,
- &mut used_by_this_id,
- inst);
+ self.constrain_instantiation_of_blacklisted_template(
+ id,
+ &mut used_by_this_id,
+ inst,
+ );
}
}
// Otherwise, add the union of each of its referent item's template
@@ -511,9 +547,11 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
trace!(" finally, used set is {:?}", used_by_this_id);
let new_len = used_by_this_id.len();
- assert!(new_len >= original_len,
- "This is the property that ensures this function is monotone -- \
- if it doesn't hold, the analysis might never terminate!");
+ assert!(
+ new_len >= original_len,
+ "This is the property that ensures this function is monotone -- \
+ if it doesn't hold, the analysis might never terminate!"
+ );
// Put the set back in the hash map and restore our invariant.
debug_assert!(self.used[&id].is_none());
@@ -528,7 +566,8 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
}
fn each_depending_on<F>(&self, item: ItemId, mut f: F)
- where F: FnMut(ItemId),
+ where
+ F: FnMut(ItemId),
{
if let Some(edges) = self.dependencies.get(&item) {
for item in edges {
@@ -542,7 +581,8 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
impl<'ctx, 'gen> From<UsedTemplateParameters<'ctx, 'gen>>
for HashMap<ItemId, ItemSet> {
fn from(used_templ_params: UsedTemplateParameters<'ctx, 'gen>) -> Self {
- used_templ_params.used
+ used_templ_params
+ .used
.into_iter()
.map(|(k, v)| (k, v.unwrap()))
.collect()