Skip to content

Commit 0001606

Browse files
author
bors-servo
authored
Auto merge of #491 - fitzgen:template-instantiation, r=emilio
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).
2 parents 0927273 + 5b5d4f8 commit 0001606

File tree

14 files changed

+638
-215
lines changed

14 files changed

+638
-215
lines changed

src/clang.rs

+106-16
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,11 @@ impl Cursor {
136136
// `clang_Cursor_getNumTemplateArguments` is totally unreliable.
137137
// Therefore, try former first, and only fallback to the latter if we
138138
// have to.
139-
self.cur_type().num_template_args()
139+
self.cur_type()
140+
.num_template_args()
140141
.or_else(|| {
141-
let n: c_int = unsafe {
142-
clang_Cursor_getNumTemplateArguments(self.x)
143-
};
142+
let n: c_int =
143+
unsafe { clang_Cursor_getNumTemplateArguments(self.x) };
144144

145145
if n >= 0 {
146146
Some(n as u32)
@@ -360,6 +360,41 @@ impl Cursor {
360360
}
361361
}
362362

363+
/// Collect all of this cursor's children into a vec and return them.
364+
pub fn collect_children(&self) -> Vec<Cursor> {
365+
let mut children = vec![];
366+
self.visit(|c| {
367+
children.push(c);
368+
CXChildVisit_Continue
369+
});
370+
children
371+
}
372+
373+
/// Does this cursor have any children?
374+
pub fn has_children(&self) -> bool {
375+
let mut has_children = false;
376+
self.visit(|_| {
377+
has_children = true;
378+
CXChildVisit_Break
379+
});
380+
has_children
381+
}
382+
383+
/// Does this cursor have at least `n` children?
384+
pub fn has_at_least_num_children(&self, n: usize) -> bool {
385+
assert!(n > 0);
386+
let mut num_left = n;
387+
self.visit(|_| {
388+
num_left -= 1;
389+
if num_left == 0 {
390+
CXChildVisit_Break
391+
} else {
392+
CXChildVisit_Continue
393+
}
394+
});
395+
num_left == 0
396+
}
397+
363398
/// Returns whether the given location contains a cursor with the given
364399
/// kind in the first level of nesting underneath (doesn't look
365400
/// recursively).
@@ -581,7 +616,7 @@ impl Hash for Cursor {
581616
}
582617

583618
/// The type of a node in clang's AST.
584-
#[derive(Clone)]
619+
#[derive(Clone, Copy)]
585620
pub struct Type {
586621
x: CXType,
587622
}
@@ -657,6 +692,31 @@ impl Type {
657692
}
658693
}
659694

695+
/// Get the canonical declaration of this type, if it is available.
696+
pub fn canonical_declaration(&self,
697+
location: Option<&Cursor>)
698+
-> Option<CanonicalTypeDeclaration> {
699+
let mut declaration = self.declaration();
700+
if !declaration.is_valid() {
701+
if let Some(location) = location {
702+
let mut location = *location;
703+
if let Some(referenced) = location.referenced() {
704+
location = referenced;
705+
}
706+
if location.is_template_like() {
707+
declaration = location;
708+
}
709+
}
710+
}
711+
712+
let canonical = declaration.canonical();
713+
if canonical.is_valid() && canonical.kind() != CXCursor_NoDeclFound {
714+
Some(CanonicalTypeDeclaration(*self, canonical))
715+
} else {
716+
None
717+
}
718+
}
719+
660720
/// Get a raw display name for this type.
661721
pub fn spelling(&self) -> String {
662722
unsafe { cxstring_into_string(clang_getTypeSpelling(self.x)) }
@@ -731,10 +791,12 @@ impl Type {
731791
/// If this type is a class template specialization, return its
732792
/// template arguments. Otherwise, return None.
733793
pub fn template_args(&self) -> Option<TypeTemplateArgIterator> {
734-
self.num_template_args().map(|n| TypeTemplateArgIterator {
735-
x: self.x,
736-
length: n,
737-
index: 0,
794+
self.num_template_args().map(|n| {
795+
TypeTemplateArgIterator {
796+
x: self.x,
797+
length: n,
798+
index: 0,
799+
}
738800
})
739801
}
740802

@@ -836,9 +898,8 @@ impl Type {
836898
// Yep, the spelling of this containing type-parameter is extremely
837899
// nasty... But can happen in <type_traits>. Unfortunately I couldn't
838900
// reduce it enough :(
839-
self.template_args().map_or(false, |args| {
840-
args.len() > 0
841-
}) && match self.declaration().kind() {
901+
self.template_args().map_or(false, |args| args.len() > 0) &&
902+
match self.declaration().kind() {
842903
CXCursor_ClassTemplatePartialSpecialization |
843904
CXCursor_TypeAliasTemplateDecl |
844905
CXCursor_TemplateTemplateParameter => false,
@@ -847,6 +908,26 @@ impl Type {
847908
}
848909
}
849910

911+
/// The `CanonicalTypeDeclaration` type exists as proof-by-construction that its
912+
/// cursor is the canonical declaration for its type. If you have a
913+
/// `CanonicalTypeDeclaration` instance, you know for sure that the type and
914+
/// cursor match up in a canonical declaration relationship, and it simply
915+
/// cannot be otherwise.
916+
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
917+
pub struct CanonicalTypeDeclaration(Type, Cursor);
918+
919+
impl CanonicalTypeDeclaration {
920+
/// Get the type.
921+
pub fn ty(&self) -> &Type {
922+
&self.0
923+
}
924+
925+
/// Get the type's canonical declaration cursor.
926+
pub fn cursor(&self) -> &Cursor {
927+
&self.1
928+
}
929+
}
930+
850931
/// An iterator for a type's template arguments.
851932
pub struct TypeTemplateArgIterator {
852933
x: CXType,
@@ -1389,7 +1470,10 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
13891470
type_to_str(ty.kind())));
13901471
}
13911472
if let Some(ty) = c.ret_type() {
1392-
print_indent(depth, format!(" {}ret-type = {}", prefix, type_to_str(ty.kind())));
1473+
print_indent(depth,
1474+
format!(" {}ret-type = {}",
1475+
prefix,
1476+
type_to_str(ty.kind())));
13931477
}
13941478

13951479
if let Some(refd) = c.referenced() {
@@ -1398,7 +1482,9 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
13981482
print_cursor(depth,
13991483
String::from(prefix) + "referenced.",
14001484
&refd);
1401-
print_cursor(depth, String::from(prefix) + "referenced.", &refd);
1485+
print_cursor(depth,
1486+
String::from(prefix) + "referenced.",
1487+
&refd);
14021488
}
14031489
}
14041490

@@ -1408,7 +1494,9 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
14081494
print_cursor(depth,
14091495
String::from(prefix) + "canonical.",
14101496
&canonical);
1411-
print_cursor(depth, String::from(prefix) + "canonical.", &canonical);
1497+
print_cursor(depth,
1498+
String::from(prefix) + "canonical.",
1499+
&canonical);
14121500
}
14131501

14141502
if let Some(specialized) = c.specialized() {
@@ -1417,7 +1505,9 @@ pub fn ast_dump(c: &Cursor, depth: isize) -> CXChildVisitResult {
14171505
print_cursor(depth,
14181506
String::from(prefix) + "specialized.",
14191507
&specialized);
1420-
print_cursor(depth, String::from(prefix) + "specialized.", &specialized);
1508+
print_cursor(depth,
1509+
String::from(prefix) + "specialized.",
1510+
&specialized);
14211511
}
14221512
}
14231513
}

src/codegen/helpers.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -89,9 +89,7 @@ pub mod ast_ty {
8989
let prefix = ctx.rust_ident_raw(prefix);
9090
quote_ty!(ctx.ext_cx(), $prefix::$ident)
9191
}
92-
None => {
93-
quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident)
94-
}
92+
None => quote_ty!(ctx.ext_cx(), ::std::os::raw::$ident),
9593
}
9694
}
9795

src/codegen/mod.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ impl CodeGenerator for Type {
521521
TypeKind::Pointer(..) |
522522
TypeKind::BlockPointer |
523523
TypeKind::Reference(..) |
524-
TypeKind::TemplateRef(..) |
524+
TypeKind::TemplateInstantiation(..) |
525525
TypeKind::Function(..) |
526526
TypeKind::ResolvedTypeRef(..) |
527527
TypeKind::Named => {
@@ -1377,9 +1377,10 @@ impl CodeGenerator for CompInfo {
13771377
// FIXME when [issue #465](https://github.com/servo/rust-bindgen/issues/465) ready
13781378
let too_many_base_vtables = self.base_members()
13791379
.iter()
1380-
.filter(|base| ctx.resolve_type(base.ty).has_vtable(ctx))
1381-
.count() >
1382-
1;
1380+
.filter(|base| {
1381+
ctx.resolve_type(base.ty).has_vtable(ctx)
1382+
})
1383+
.count() > 1;
13831384

13841385
let should_skip_field_offset_checks = item.is_opaque(ctx) ||
13851386
too_many_base_vtables;
@@ -2180,7 +2181,7 @@ impl ToRustTy for Type {
21802181
let path = item.namespace_aware_canonical_path(ctx);
21812182
aster::AstBuilder::new().ty().path().ids(path).build()
21822183
}
2183-
TypeKind::TemplateRef(inner, ref template_args) => {
2184+
TypeKind::TemplateInstantiation(inner, ref template_args) => {
21842185
// PS: Sorry for the duplication here.
21852186
let mut inner_ty = inner.to_rust_ty(ctx).unwrap();
21862187

@@ -2189,7 +2190,7 @@ impl ToRustTy for Type {
21892190
.map(|arg| arg.to_rust_ty(ctx))
21902191
.collect::<Vec<_>>();
21912192

2192-
path.segments.last_mut().unwrap().parameters = if
2193+
path.segments.last_mut().unwrap().parameters = if
21932194
template_args.is_empty() {
21942195
None
21952196
} else {
@@ -2509,8 +2510,8 @@ mod utils {
25092510
use super::ItemToRustTy;
25102511
use aster;
25112512
use ir::context::{BindgenContext, ItemId};
2512-
use ir::item::{Item, ItemCanonicalPath};
25132513
use ir::function::FunctionSig;
2514+
use ir::item::{Item, ItemCanonicalPath};
25142515
use ir::ty::TypeKind;
25152516
use std::mem;
25162517
use syntax::ast;

src/ir/comp.rs

+13-5
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ use super::context::{BindgenContext, ItemId};
55
use super::derive::{CanDeriveCopy, CanDeriveDebug, CanDeriveDefault};
66
use super::item::Item;
77
use super::layout::Layout;
8-
use super::ty::Type;
8+
use super::ty::{TemplateDeclaration, Type};
99
use super::type_collector::{ItemSet, TypeCollector};
1010
use clang;
1111
use parse::{ClangItemParser, ParseError};
@@ -559,10 +559,8 @@ impl CompInfo {
559559
_ => false,
560560
});
561561
ci.template_args = match ty.template_args() {
562-
// In forward declarations and not specializations,
563-
// etc, they are in
564-
// the ast, we'll meet them in
565-
// CXCursor_TemplateTypeParameter
562+
// In forward declarations and not specializations, etc, they are in
563+
// the ast, we'll meet them in CXCursor_TemplateTypeParameter
566564
None => vec![],
567565
Some(arg_types) => {
568566
let num_arg_types = arg_types.len();
@@ -911,6 +909,16 @@ impl CompInfo {
911909
}
912910
}
913911

912+
impl TemplateDeclaration for CompInfo {
913+
fn template_params(&self, _ctx: &BindgenContext) -> Option<Vec<ItemId>> {
914+
if self.template_args.is_empty() {
915+
None
916+
} else {
917+
Some(self.template_args.clone())
918+
}
919+
}
920+
}
921+
914922
impl CanDeriveDebug for CompInfo {
915923
type Extra = Option<Layout>;
916924

0 commit comments

Comments
 (0)