/// An analysis that finds for each IR item whether it has a destructor or not /// /// We use the monotone function `has destructor`, defined as follows: /// /// * If T is a type alias, a templated alias, or an indirection to another type, /// T has a destructor if the type T refers to has a destructor. /// * If T is a compound type, T has a destructor if we saw a destructor when parsing it, /// or if it's a struct, T has a destructor if any of its base members has a destructor, /// or if any of its fields have a destructor. /// * If T is an instantiation of an abstract template definition, T has /// a destructor if its template definition has a destructor, /// or if any of the template arguments has a destructor. /// * If T is the type of a field, that field has a destructor if it's not a bitfield, /// and if T has a destructor. #[derive(Debug, Clone)] pub(crate) struct HasDestructorAnalysis<'ctx> {
ctx: &'ctx BindgenContext,
// The incremental result of this analysis's computation. Everything in this // set definitely has a destructor.
have_destructor: HashSet<ItemId>,
// Dependencies saying that if a key ItemId has been inserted into the // `have_destructor` set, then each of the ids in Vec<ItemId> need to be // considered again. // // This is a subset of the natural IR graph with reversed edges, where we // only include the edges from the IR graph that can affect whether a type // has a destructor or not.
dependencies: HashMap<ItemId, Vec<ItemId>>,
}
impl<'ctx> HasDestructorAnalysis<'ctx> { fn consider_edge(kind: EdgeKind) -> bool { // These are the only edges that can affect whether a type has a // destructor or not.
matches!(
kind,
EdgeKind::TypeReference |
EdgeKind::BaseMember |
EdgeKind::Field |
EdgeKind::TemplateArgument |
EdgeKind::TemplateDeclaration
)
}
fn insert<Id: Into<ItemId>>(&mutself, id: Id) -> ConstrainResult { let id = id.into(); let was_not_already_in_set = self.have_destructor.insert(id);
assert!(
was_not_already_in_set, "We shouldn't try and insert {:?} twice because if it was \
already in the set, `constrain` should have exited early.",
id
);
ConstrainResult::Changed
}
}
impl<'ctx> MonotoneFramework for HasDestructorAnalysis<'ctx> { type Node = ItemId; type Extra = &'ctx BindgenContext; type Output = HashSet<ItemId>;
fn new(ctx: &'ctx BindgenContext) -> Self { let have_destructor = HashSet::default(); let dependencies = generate_dependencies(ctx, Self::consider_edge);
fn constrain(&mutself, id: ItemId) -> ConstrainResult { ifself.have_destructor.contains(&id) { // We've already computed that this type has a destructor and that can't // change. return ConstrainResult::Same;
}
let item = self.ctx.resolve_item(id); let ty = match item.as_type() {
None => return ConstrainResult::Same,
Some(ty) => ty,
};
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.