diff options
author | Nick Fitzgerald <fitzgen@gmail.com> | 2016-11-03 11:23:11 -0700 |
---|---|---|
committer | Nick Fitzgerald <fitzgen@gmail.com> | 2016-11-03 11:23:11 -0700 |
commit | eff92920d42eb87a9dedc5fb32c02aac382a51c5 (patch) | |
tree | 63b2f242cf589678d08d9df390a4601e32e70a06 | |
parent | 33d475dd56b8c0513771139da2f04e7542eaadb3 (diff) |
Do not overwrite existing replacements
It turns out that we can end up overwriting existing replacements. This commit
embeds the assumption that the first replacement definition is the correct one,
and warns on all attempts to overwrite the first replacement definition with a
new one. Additionally, it adds some debug logging about replacements.
-rw-r--r-- | src/ir/context.rs | 21 |
1 files changed, 19 insertions, 2 deletions
diff --git a/src/ir/context.rs b/src/ir/context.rs index beccc514..b51a2cb9 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -4,7 +4,7 @@ use BindgenOptions; use clang::{self, Cursor}; use parse::ClangItemParser; use std::borrow::{Borrow, Cow}; -use std::collections::{HashMap, HashSet}; +use std::collections::{HashMap, HashSet, hash_map}; use std::collections::btree_map::{self, BTreeMap}; use std::fmt; use super::int::IntKind; @@ -308,6 +308,7 @@ impl<'ctx> BindgenContext<'ctx> { /// `replaces="SomeType"` annotation with the replacement type. fn process_replacements(&mut self) { if self.replacements.is_empty() { + debug!("No replacements to process"); return; } @@ -347,6 +348,8 @@ impl<'ctx> BindgenContext<'ctx> { } for (id, replacement) in replacements { + debug!("Replacing {:?} with {:?}", id, replacement); + let mut item = self.items.get_mut(&id).unwrap(); *item.kind_mut().as_type_mut().unwrap().kind_mut() = TypeKind::ResolvedTypeRef(replacement); @@ -725,7 +728,21 @@ impl<'ctx> BindgenContext<'ctx> { /// Replacement types are declared using the `replaces="xxx"` annotation, /// and implies that the original type is hidden. pub fn replace(&mut self, name: &str, potential_ty: ItemId) { - self.replacements.insert(name.into(), potential_ty); + match self.replacements.entry(name.into()) { + hash_map::Entry::Vacant(entry) => { + debug!("Defining replacement for {} as {:?}", + name, + potential_ty); + entry.insert(potential_ty); + } + hash_map::Entry::Occupied(occupied) => { + warn!("Replacement for {} already defined as {:?}; \ + ignoring duplicate replacement definition as {:?}}}", + name, + occupied.get(), + potential_ty); + } + } } /// Is the item with the given `name` hidden? Or is the item with the given |