|
* Find each item's used template parameters when we begin the codegen phase
* Add TemplateDeclaration::used_template_params()
This method is available during the codegen phase, and uses the information
gleaned by the `ir::named::UsedTemplateParameters` analysis.
* Remove Item::{applicable_template_args,signature_contains_named_type}
They are replaced by the template parameter usage analysis and
TemplateDeclaration::used_template_params.
* Parse and de-duplicate named template type parameters
* Do not attempt to determine template parameter usage when not recursively whitelisting
* Add a proper TemplateInstantiation type
This makes it so that CompInfo is always either a compound type definition, or a
template compound type definition, never an instantiation of a template. It also
pulls out TypeKind::TemplateInstantiation(<inline stuff>) to a proper
ir::TemplateInstantiation type, and TypeKind::TemplateInstantiation just wraps
ir::TemplateInstantiation into TypeKind.
* Allow template definitions to lack template parameters because of opaque template definitions
* Detect and ignore cycles deriving Copy/Debug and whether a type has a vtable
* Bail out early in the face of partial template specialization
We don't support it, and shouldn't continue trying to parse a type from this
cursor.
* Do not consider inner type's parameter usage as our own parameter usage
* Do not require a parent_id for template instantiations
It is not necessary, and in fact was preventing us from creating template
instantiations in some places, resulting in such nonsense as a generic template
definition as a base for another type.
* Only join if this is NOT a named template type or a template instantiation
Otherwise, we'll always consider all of a template instantiation's arguments as
used, when they should only be considered used if the template definition uses
that template parameter.
* Consider function return and parameter types as used
Although we should not follow class method edges because we cannot create new
monomorphizations of methods, code can create aliases of function pointers whose
return or parameter types are template parameters, and those template parameters
should be considered used.
* Add the AsNamed trait for things which might be a named template type
This sees through ResolvedTypeReferences to get at the final named type and its
canonical item id. By using this in the named template parameter usage analysis,
we ensure we don't have bugs where there are ResolvedTypeReferences in the usage
sets rather than the canonical named item id, which could cause template
parameters to be ignored accidentally.
* Do not consider an inner var's template parameter usage as our own
* Make the expectations' tests less noisy
* Use opaque blobs for unknown template definition types
When we don't know how to generate a Rust type from a template definition (eg
because it uses non-type template parameters), then we should fall back to using
the instantiation's layout to generate the opaque blob.
* Implement CanDeriveDebug for TemplateInstantiation
We need the template instantiation's layout to determine if we can derive debug
for it when the instantiation's template definition has non-type parameters.
* Stop thrashing malloc when unioning ItemSets in UsedTemplateParameters
Previously, we were cloning an ItemSet, which requires a malloc for non-empty
sets, when taking its union with our current id's set. Now, instead of doing
that, we wrap each ItemSet in an Option, and take the set out of the hash map
when modifying it. This allows us to side-step the borrow checker and HashMap's
lack of an analog to `slice::split_at_mut` and mutate what is logically a value
in the hash map while also using immutable references of values that are
physically in the hash map.
* Add some tests explicitly about template parameter usage
* Updated test expectations now that we are inferring template parameter usage
* Reinstate the layout tests for template instantiations
* Generate opaque blobs for uses of partially specialized templates
This adds `TypeKind::Opaque` which signifies that we do not understand anything
about the given type and that we should just generate an opaque blob based on
the type's layout. It explicitly uses the opaque type kind for partially
specialized templates.
* Add note about None vs Some([]) in TemplateDeclaration
* Do not rely on TypeKind implementing PartialEq
* Prefer assert_eq!(lhs, rhs) to assert!(lhs == rhs)
* Expand some comments for ir::named::UsedTemplateParameters
* Expand Item::is_opaque to consider TypeKind::Opaque
* Use opaque types instead of panicking
Use opaque types as our last resort when resolving type references after we have
collected unresolved type references instead of panicking.
* Find template definitions that don't want to be found
* Recognize associated template types and make them opaque
|
|
TL;DR: The binding generator is a mess as of right now. At first it was funny
(in a "this is challenging" sense) to improve on it, but this is not
sustainable.
The truth is that the current architecture of the binding generator is a huge
pile of hacks, so these few days I've been working on rewriting it with a few
goals.
1) Have the hacks as contained and identified as possible. They're sometimes
needed because how clang exposes the AST, but ideally those hacks are well
identified and don't interact randomly with each others.
As an example, in the current bindgen when scanning the parameters of a
function that references a struct clones all the struct information, then if
the struct name changes (because we mangle it), everything breaks.
2) Support extending the bindgen output without having to deal with clang. The
way I'm aiming to do this is separating completely the parsing stage from
the code generation one, and providing a single id for each item the binding
generator provides.
3) No more random mutation of the internal representation from anywhere. That
means no more Rc<RefCell<T>>, no more random circular references, no more
borrow_state... nothing.
4) No more deduplication of declarations before code generation.
Current bindgen has a stage, called `tag_dup_decl`[1], that takes care of
deduplicating declarations. That's completely buggy, and for C++ it's a
complete mess, since we YOLO modify the world.
I've managed to take rid of this using the clang canonical declaration, and
the definition, to avoid scanning any type/item twice.
5) Code generation should not modify any internal data structure. It can lookup
things, traverse whatever it needs, but not modifying randomly.
6) Each item should have a canonical name, and a single source of mangling
logic, and that should be computed from the inmutable state, at code
generation.
I've put a few canonical_name stuff in the code generation phase, but it's
still not complete, and should change if I implement namespaces.
Improvements pending until this can land:
1) Add support for missing core stuff, mainly generating functions (note that
we parse the signatures for types correctly though), bitfields, generating
C++ methods.
2) Add support for the necessary features that were added to work around some
C++ pitfalls, like opaque types, etc...
3) Add support for the sugar that Manish added recently.
4) Optionally (and I guess this can land without it, because basically nobody
uses it since it's so buggy), bring back namespace support.
These are not completely trivial, but I think I can do them quite easily with
the current architecture.
I'm putting the current state of affairs here as a request for comments... Any
thoughts? Note that there are still a few smells I want to eventually
re-redesign, like the ParseError::Recurse thing, but until that happens I'm
way happier with this kind of architecture.
I'm keeping the old `parser.rs` and `gen.rs` in tree just for reference while I
code, but they will go away.
[1]: https://github.com/Yamakaky/rust-bindgen/blob/master/src/gen.rs#L448
|