-
Notifications
You must be signed in to change notification settings - Fork 742
Instantiating a template with a template instantiation (eg Template1<Template2<Type>>) causes us to generate bad bindings #446
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Nope, this isn't as much due to specialization but to us skipping template parameters with empty names. |
We could fix that, I guess. In the end of the day those parameters can't be referenced, so we could define them with the name we want. |
Hmm, so maybe creduce ended up finding a different bug then the one I was tracking down, because I'm hitting something related to this in SpiderMonkey DEBUG (but not non-DEBUG) builds. |
Yes, generating names sounds good to me: |
For posterity: I have a fix to generate names for anonymous named types, but this uncovers another extant bug which we are hitting in |
Specifically, here is the AST clang gives us:
Note that The result is that we generate this code: #[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct JS_PersistentRooted<c> {
pub _base: a<__anon_named_type_0>,
pub _phantom_0: ::std::marker::PhantomData<c>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct a<__anon_named_type_0> {
pub b: *mut a<__anon_named_type_0>,
} When it should really be something more like this: #[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct JS_PersistentRooted<c> {
pub _base: a<JS_PersistentRooted<c>>,
pub _phantom_0: ::std::marker::PhantomData<c>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct a<__anon_named_type_0> {
pub b: *mut a<__anon_named_type_0>,
} |
Here is a simpler test case that fails right now, without my patches applied, and doesn't involve either of anonymous named types or inheritance: template <typename T>
class List {
List<T> *next;
};
template <typename T>
class PersistentRooted {
List<PersistentRooted<T>> list;
}; |
I think specializing with any specialization is broken. |
Interesting, if I modify this test case to have |
Both of these also work: using Self = PersistentRooted<T>;
List<Self> list;
using Self = PersistentRooted;
List<Self> list; |
Ok, here is a brain dump of what I have so far. I had to modify I think I might need to extend When parsing the
My best hope at the moment is to check the |
@emilio do you have any ideas or feedback ^ ? Thanks! |
The problem with checking currently_parsed_stack is that it's likely not enough? I need to digest this, I'll probably come back with more input :P |
This isn't partial template specialization, as I understand it. All the templates involved in my test cases are fully specialized, with no free template parameters. |
Well, it's partial in the sense that PersistentRooted is incomplete when used as a template parameter in a base class, right? |
I believe LLVM would give us proper type info if it was complete at that point. |
Ah ok, we are each parsing "partial template specialization" differently :) I have always parsed it as "(partial (template specialization))" and it seems you parse it as "((partial template) specialization)". I do not know which parsing is correct, although I guess both come up in C++... |
Anyways, I've been expanding our clang AST dumping, because I am going crazy trying to find what is or isn't available. PR to land this extended dumping soon, but here is what we get for the failing test case here: (
kind = ClassTemplate
spelling = "List"
location = ./issue-358.hpp:4:7
is-definition? true
is-declaration? true
is-anonymous? false
is-inlined-function? false
template-kind = ClassDecl
usr = "c:@ST>1#T@List"
type.kind = Invalid
(
kind = TemplateTypeParameter
spelling = "T"
location = ./issue-358.hpp:3:20
is-definition? true
is-declaration? true
is-anonymous? false
is-inlined-function? false
usr = "c:issue-358.hpp@43"
type.kind = Unexposed
type.spelling = "T"
type.is-variadic? false
type.canonical.kind = Unexposed
type.canonical.spelling = "type-parameter-0-0"
type.canonical.is-variadic? false
)
(
kind = FieldDecl
spelling = "next"
location = ./issue-358.hpp:5:14
is-definition? true
is-declaration? true
is-anonymous? false
is-inlined-function? false
usr = "c:@ST>1#T@List@FI@next"
type.kind = Pointer
type.spelling = "List<T> *"
type.is-variadic? false
type.canonical.kind = Pointer
type.canonical.spelling = "List<T> *"
type.canonical.is-variadic? false
type.canonical.pointee.kind = Unexposed
type.canonical.pointee.spelling = "List<T>"
type.canonical.pointee.is-variadic? false
type.pointee.kind = Unexposed
type.pointee.spelling = "List<T>"
type.pointee.is-variadic? false
type.pointee.canonical.kind = Unexposed
type.pointee.canonical.spelling = "List<T>"
type.pointee.canonical.is-variadic? false
(
kind = TemplateRef
spelling = "List"
location = ./issue-358.hpp:5:5
is-definition? false
is-declaration? false
is-anonymous? false
is-inlined-function? false
definition.kind = ClassTemplate
definition.spelling = "List"
definition.location = ./issue-358.hpp:4:7
definition.is-definition? true
definition.is-declaration? true
definition.is-anonymous? false
definition.is-inlined-function? false
definition.template-kind = ClassDecl
definition.usr = "c:@ST>1#T@List"
referenced.kind = ClassTemplate
referenced.spelling = "List"
referenced.location = ./issue-358.hpp:4:7
referenced.is-definition? true
referenced.is-declaration? true
referenced.is-anonymous? false
referenced.is-inlined-function? false
referenced.template-kind = ClassDecl
referenced.usr = "c:@ST>1#T@List"
type.kind = Invalid
)
(
kind = TypeRef
spelling = "T"
location = ./issue-358.hpp:5:10
is-definition? false
is-declaration? false
is-anonymous? false
is-inlined-function? false
definition.kind = TemplateTypeParameter
definition.spelling = "T"
definition.location = ./issue-358.hpp:3:20
definition.is-definition? true
definition.is-declaration? true
definition.is-anonymous? false
definition.is-inlined-function? false
definition.usr = "c:issue-358.hpp@43"
referenced.kind = TemplateTypeParameter
referenced.spelling = "T"
referenced.location = ./issue-358.hpp:3:20
referenced.is-definition? true
referenced.is-declaration? true
referenced.is-anonymous? false
referenced.is-inlined-function? false
referenced.usr = "c:issue-358.hpp@43"
type.kind = Unexposed
type.spelling = "T"
type.is-variadic? false
type.canonical.kind = Unexposed
type.canonical.spelling = "type-parameter-0-0"
type.canonical.is-variadic? false
)
)
)
(
kind = ClassTemplate
spelling = "PersistentRooted"
location = ./issue-358.hpp:9:7
is-definition? true
is-declaration? true
is-anonymous? false
is-inlined-function? false
template-kind = ClassDecl
usr = "c:@ST>1#T@PersistentRooted"
type.kind = Invalid
(
kind = TemplateTypeParameter
spelling = "T"
location = ./issue-358.hpp:8:20
is-definition? true
is-declaration? true
is-anonymous? false
is-inlined-function? false
usr = "c:issue-358.hpp@101"
type.kind = Unexposed
type.spelling = "T"
type.is-variadic? false
type.canonical.kind = Unexposed
type.canonical.spelling = "type-parameter-0-0"
type.canonical.is-variadic? false
)
(
kind = FieldDecl
spelling = "root_list"
location = ./issue-358.hpp:11:31
is-definition? true
is-declaration? true
is-anonymous? false
is-inlined-function? false
usr = "c:@ST>1#T@PersistentRooted@FI@root_list"
type.kind = Unexposed
type.spelling = "List<PersistentRooted<T> >"
type.is-variadic? false
type.canonical.kind = Unexposed
type.canonical.spelling = "List<PersistentRooted<T> >"
type.canonical.is-variadic? false
type.declaration.kind = ClassTemplate
type.declaration.spelling = "List"
type.declaration.location = ./issue-358.hpp:4:7
type.declaration.is-definition? true
type.declaration.is-declaration? true
type.declaration.is-anonymous? false
type.declaration.is-inlined-function? false
type.declaration.template-kind = ClassDecl
type.declaration.usr = "c:@ST>1#T@List"
(
kind = TemplateRef
spelling = "List"
location = ./issue-358.hpp:11:5
is-definition? false
is-declaration? false
is-anonymous? false
is-inlined-function? false
definition.kind = ClassTemplate
definition.spelling = "List"
definition.location = ./issue-358.hpp:4:7
definition.is-definition? true
definition.is-declaration? true
definition.is-anonymous? false
definition.is-inlined-function? false
definition.template-kind = ClassDecl
definition.usr = "c:@ST>1#T@List"
referenced.kind = ClassTemplate
referenced.spelling = "List"
referenced.location = ./issue-358.hpp:4:7
referenced.is-definition? true
referenced.is-declaration? true
referenced.is-anonymous? false
referenced.is-inlined-function? false
referenced.template-kind = ClassDecl
referenced.usr = "c:@ST>1#T@List"
type.kind = Invalid
)
(
kind = TemplateRef
spelling = "PersistentRooted"
location = ./issue-358.hpp:11:10
is-definition? false
is-declaration? false
is-anonymous? false
is-inlined-function? false
definition.kind = ClassTemplate
definition.spelling = "PersistentRooted"
definition.location = ./issue-358.hpp:9:7
definition.is-definition? true
definition.is-declaration? true
definition.is-anonymous? false
definition.is-inlined-function? false
definition.template-kind = ClassDecl
definition.usr = "c:@ST>1#T@PersistentRooted"
referenced.kind = ClassTemplate
referenced.spelling = "PersistentRooted"
referenced.location = ./issue-358.hpp:9:7
referenced.is-definition? true
referenced.is-declaration? true
referenced.is-anonymous? false
referenced.is-inlined-function? false
referenced.template-kind = ClassDecl
referenced.usr = "c:@ST>1#T@PersistentRooted"
type.kind = Invalid
)
(
kind = TypeRef
spelling = "T"
location = ./issue-358.hpp:11:27
is-definition? false
is-declaration? false
is-anonymous? false
is-inlined-function? false
definition.kind = TemplateTypeParameter
definition.spelling = "T"
definition.location = ./issue-358.hpp:8:20
definition.is-definition? true
definition.is-declaration? true
definition.is-anonymous? false
definition.is-inlined-function? false
definition.usr = "c:issue-358.hpp@101"
referenced.kind = TemplateTypeParameter
referenced.spelling = "T"
referenced.location = ./issue-358.hpp:8:20
referenced.is-definition? true
referenced.is-declaration? true
referenced.is-anonymous? false
referenced.is-inlined-function? false
referenced.usr = "c:issue-358.hpp@101"
type.kind = Unexposed
type.spelling = "T"
type.is-variadic? false
type.canonical.kind = Unexposed
type.canonical.spelling = "type-parameter-0-0"
type.canonical.is-variadic? false
)
)
) |
(FWIW, https://en.wikipedia.org/wiki/Partial_template_specialization describes "(partial (template specialization))") |
Really frustrating that libclang is returning |
Worth noting that this only happens when there are incomplete types, i.e., the following works fine:
|
We can probably try to coerce libclang in returning the proper types though, I think that's going to be the easiest fix. |
From libclang:
I'm not super familiar with their code base, but that just seems plain wrong. What about templated class declarations ( |
Observation: if we are instantiating an incomplete template, then that template must be on our currently parsing stack, or else the input would be malformed C++ and clang would give a hard error before we can even attempt to create our ir. |
Immediate plan of attack:
Longer term plan of attack:
|
Ok! Getting a little bit close! My local branch is now generating too many template instantiations instead of too few! :-P /* automatically generated by rust-bindgen */
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct List<T> {
pub next: *mut List<List<T>>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PersistentRooted<T> {
pub root_list: List<List<PersistentRooted<T>>>,
} |
Ship it! :D
…On Mon, Feb 06, 2017 at 03:00:32PM -0800, Nick Fitzgerald wrote:
Ok! Getting a little bit close!
My local branch is now generating too many template instantiations instead of too few! :-P
```rust
/* automatically generated by rust-bindgen */
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct List<T> {
pub next: *mut List<List<T>>,
}
#[repr(C)]
#[derive(Debug, Copy, Clone)]
pub struct PersistentRooted<T> {
pub root_list: List<List<PersistentRooted<T>>>,
}
```
--
You are receiving this because you were mentioned.
Reply to this email directly or view it on GitHub:
#446 (comment)
|
Template instantiation I very much suspect this needs a rebase, but I haven't done it yet. This is the majority of #446, although it doesn't have the name generation for anonymous named types patches yet (that will be a different PR).
Going to close this for fixing instantiations. Will open new issues for figuring out how to handle unnamed type parameters, and aliases that don't use their template parameters. |
Input:
Output with
--enable-cxx-namespaces -- --std=c++11
:Compilation errors:
I'm not 100% sure what the best thing to do in this case is, but whatever we do the bindings we emit should compile.
This seems really familiar... I wonder if we regressed something recently?
The text was updated successfully, but these errors were encountered: