Skip to content

Commit 568b011

Browse files
committed
Ensure that every item we constrain has a set of used template parameters
This is a follow up to c8a206a, and the support for blacklisting in the named template parameter usage analysis. This ensures that ever item we ever call `constrain` on has an entry in `used` for the set of template parameters it uses. Additionally, it adds extra assertions to enforce the invariant. We cannot completely avoid analyzing blacklisted items because we want to consider all of a blacklisted template's parameters as used. This is why we ensure that blacklisted items have a used template parameter set rather than ensuring that blacklisted items never end up in the worklist.
1 parent a36c09b commit 568b011

File tree

1 file changed

+30
-1
lines changed

1 file changed

+30
-1
lines changed

src/ir/named.rs

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,12 +322,14 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
322322

323323
for item in whitelisted_items.iter().cloned() {
324324
dependencies.entry(item).or_insert(vec![]);
325-
used.insert(item, Some(ItemSet::new()));
325+
used.entry(item).or_insert(Some(ItemSet::new()));
326326

327327
{
328328
// We reverse our natural IR graph edges to find dependencies
329329
// between nodes.
330330
item.trace(ctx, &mut |sub_item, _| {
331+
used.entry(sub_item).or_insert(Some(ItemSet::new()));
332+
331333
// We won't be generating code for items that aren't
332334
// whitelisted, so don't bother keeping track of their
333335
// template parameters. But isn't whitelisting the
@@ -353,12 +355,17 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
353355
&TypeKind::TemplateInstantiation(ref inst) => {
354356
let decl = ctx.resolve_type(inst.template_definition());
355357
let args = inst.template_arguments();
358+
356359
// Although template definitions should always have
357360
// template parameters, there is a single exception:
358361
// opaque templates. Hence the unwrap_or.
359362
let params = decl.self_template_params(ctx)
360363
.unwrap_or(vec![]);
364+
361365
for (arg, param) in args.iter().zip(params.iter()) {
366+
used.entry(*arg).or_insert(Some(ItemSet::new()));
367+
used.entry(*param).or_insert(Some(ItemSet::new()));
368+
362369
dependencies.entry(*arg)
363370
.or_insert(vec![])
364371
.push(*param);
@@ -368,6 +375,28 @@ impl<'ctx, 'gen> MonotoneFramework for UsedTemplateParameters<'ctx, 'gen> {
368375
});
369376
}
370377

378+
if cfg!(feature = "testing_only_extra_assertions") {
379+
// Invariant: The `used` map has an entry for every whitelisted
380+
// item, as well as all explicitly blacklisted items that are
381+
// reachable from whitelisted items.
382+
//
383+
// (This is so that every item we call `constrain` on is guaranteed
384+
// to have a set of template parameters, and we can allow
385+
// blacklisted templates to use all of their parameters).
386+
for item in whitelisted_items.iter() {
387+
extra_assert!(used.contains_key(item));
388+
item.trace(ctx, &mut |sub_item, _| {
389+
extra_assert!(used.contains_key(&sub_item));
390+
}, &())
391+
}
392+
393+
// Invariant: the `dependencies` map has an entry for every
394+
// whitelisted item.
395+
for item in whitelisted_items.iter() {
396+
extra_assert!(dependencies.contains_key(item));
397+
}
398+
}
399+
371400
UsedTemplateParameters {
372401
ctx: ctx,
373402
used: used,

0 commit comments

Comments
 (0)