@@ -77,6 +77,64 @@ static std::string stringWithFormat(const std::string fmt_str, ...) {
77
77
return std::string (formatted.get ());
78
78
}
79
79
80
+ static swift::TypeBase*
81
+ GetTemplateArgument (swift::TypeBase* type,
82
+ size_t arg_idx)
83
+ {
84
+ if (type)
85
+ {
86
+ swift::CanType swift_can_type = type->getDesugaredType ()->getCanonicalType ();
87
+
88
+ const swift::TypeKind type_kind = swift_can_type->getKind ();
89
+ switch (type_kind)
90
+ {
91
+ case swift::TypeKind::UnboundGeneric:
92
+ {
93
+ swift::UnboundGenericType *unbound_generic_type = swift_can_type->getAs <swift::UnboundGenericType>();
94
+ if (!unbound_generic_type)
95
+ break ;
96
+ swift::NominalTypeDecl *nominal_type_decl = unbound_generic_type->getDecl ();
97
+ if (!nominal_type_decl)
98
+ break ;
99
+ swift::GenericParamList *generic_param_list = nominal_type_decl->getGenericParams ();
100
+ if (!generic_param_list)
101
+ break ;
102
+ if (arg_idx >= generic_param_list->getAllArchetypes ().size ())
103
+ break ;
104
+ return generic_param_list->getAllArchetypes ()[arg_idx];
105
+ }
106
+ break ;
107
+ case swift::TypeKind::BoundGenericClass:
108
+ case swift::TypeKind::BoundGenericStruct:
109
+ case swift::TypeKind::BoundGenericEnum:
110
+ {
111
+ swift::BoundGenericType *bound_generic_type = swift_can_type->getAs <swift::BoundGenericType>();
112
+ if (!bound_generic_type)
113
+ break ;
114
+ const llvm::ArrayRef<swift::Substitution>& substitutions = bound_generic_type->getSubstitutions (nullptr ,nullptr );
115
+ if (arg_idx >= substitutions.size ())
116
+ break ;
117
+ const swift::Substitution& substitution = substitutions[arg_idx];
118
+ return substitution.getReplacement ().getPointer ();
119
+ }
120
+ case swift::TypeKind::PolymorphicFunction:
121
+ {
122
+ swift::PolymorphicFunctionType *polymorhpic_func_type = swift_can_type->getAs <swift::PolymorphicFunctionType>();
123
+ if (!polymorhpic_func_type)
124
+ break ;
125
+ if (arg_idx >= polymorhpic_func_type->getGenericParameters ().size ())
126
+ break ;
127
+ return polymorhpic_func_type->getGenericParameters ()[arg_idx]->getArchetype ();
128
+ }
129
+ break ;
130
+ default :
131
+ break ;
132
+ }
133
+ }
134
+
135
+ return nullptr ;
136
+ }
137
+
80
138
enum class MemberType : uint32_t {
81
139
Invalid,
82
140
BaseClass,
@@ -469,6 +527,30 @@ class DeclsLookupSource {
469
527
return (this ->operator bool ()) && (_type == Type::Extension);
470
528
}
471
529
530
+ swift::Type
531
+ GetQualifiedArchetype (size_t index,
532
+ swift::ASTContext* ast)
533
+ {
534
+ if (this ->operator bool () && ast)
535
+ {
536
+ switch (_type)
537
+ {
538
+ case Type::Extension:
539
+ {
540
+ swift::TypeBase *type_ptr = _extension._decl ->getType ().getPointer ();
541
+ if (swift::MetatypeType *metatype_ptr = type_ptr->getAs <swift::MetatypeType>())
542
+ type_ptr = metatype_ptr->getInstanceType ().getPointer ();
543
+ swift::TypeBase *archetype = GetTemplateArgument (type_ptr, index);
544
+ return swift::Type (archetype);
545
+ }
546
+ break ;
547
+ default :
548
+ break ;
549
+ }
550
+ }
551
+ return swift::Type ();
552
+ }
553
+
472
554
private:
473
555
Type _type;
474
556
@@ -2239,6 +2321,66 @@ VisitNodeQualifiedArchetype (SwiftASTContext *ast,
2239
2321
const VisitNodeResult &generic_context, // set by GenericType case
2240
2322
Log *log)
2241
2323
{
2324
+ if (cur_node->begin () != cur_node->end ())
2325
+ {
2326
+ swift::Demangle::Node::iterator end = cur_node->end ();
2327
+ VisitNodeResult type_result;
2328
+ uint64_t index = 0xFFFFFFFFFFFFFFFF ;
2329
+ for (swift::Demangle::Node::iterator pos = cur_node->begin (); pos != end; ++pos)
2330
+ {
2331
+ switch (pos->get ()->getKind ())
2332
+ {
2333
+ case swift::Demangle::Node::Kind::Number:
2334
+ index = pos->get ()->getIndex ();
2335
+ break ;
2336
+ case swift::Demangle::Node::Kind::DeclContext:
2337
+ nodes.push_back (*pos);
2338
+ VisitNode (ast, nodes, type_result, generic_context, log);
2339
+ break ;
2340
+ default :
2341
+ break ;
2342
+ }
2343
+ }
2344
+ if (index != 0xFFFFFFFFFFFFFFFF )
2345
+ {
2346
+ if (type_result._types .size () == 1 && type_result._decls .size () == 1 )
2347
+ {
2348
+ // given a method defined as func ... (args) -> (ret) {...}
2349
+ // the Swift type system represents it as
2350
+ // (SomeTypeMoniker) -> (args) -> (ret), where SomeTypeMoniker is an appropriately crafted
2351
+ // reference to the type that contains the method (e.g. for a struct, an @inout StructType)
2352
+ // For a qualified archetype of a method, we do not care about the first-level function, but about
2353
+ // the returned function, which is the thing whose archetypes we truly care to extract
2354
+ // TODO: this might be a generally useful operation, but it requires a Decl as well as a type
2355
+ // to be reliably performed, and as such we cannot just put it in CompilerType as of now
2356
+ // (consider, func foo (@inout StructType) -> (Int) -> () vs struct StructType {func foo(Int) -> ()} to see why)
2357
+ swift::TypeBase *type_ptr = type_result._types [0 ].getPointer ();
2358
+ swift::Decl* decl_ptr = type_result._decls [0 ];
2359
+ // if this is a function...
2360
+ if (type_ptr && type_ptr->is <swift::AnyFunctionType>())
2361
+ {
2362
+ // if this is defined in a type...
2363
+ if (decl_ptr->getDeclContext ()->isTypeContext ())
2364
+ {
2365
+ // if I can get the function type from it
2366
+ if (auto func_type = llvm::dyn_cast_or_null<swift::AnyFunctionType>(type_ptr))
2367
+ {
2368
+ // and it has a return type which is itself a function
2369
+ auto return_func_type = llvm::dyn_cast_or_null<swift::AnyFunctionType>(func_type->getResult ().getPointer ());
2370
+ if (return_func_type)
2371
+ type_ptr = return_func_type; // then use IT as our source of archetypes
2372
+ }
2373
+ }
2374
+ }
2375
+ swift::TypeBase *arg_type = GetTemplateArgument (type_ptr, index);
2376
+ result._types .push_back (swift::Type (arg_type));
2377
+ }
2378
+ else if (type_result._module .IsExtension ())
2379
+ {
2380
+ result._types .push_back (type_result._module .GetQualifiedArchetype (index, ast));
2381
+ }
2382
+ }
2383
+ }
2242
2384
}
2243
2385
2244
2386
static void
0 commit comments