-
Notifications
You must be signed in to change notification settings - Fork 10.5k
Fix subscript reconstruction #15096
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
Fix subscript reconstruction #15096
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -951,6 +951,15 @@ static void VisitNodeDestructor( | |
} | ||
} | ||
|
||
static Demangle::NodePointer DropGenericSignature( | ||
Demangle::NodePointer cur_node) { | ||
if (cur_node->getKind() != Demangle::Node::Kind::DependentGenericType) | ||
return nullptr; | ||
if (cur_node->getChild(0) == nullptr) | ||
return nullptr; | ||
return cur_node->getFirstChild(); | ||
} | ||
|
||
static void VisitNodeDeclContext( | ||
ASTContext *ast, | ||
Demangle::NodePointer cur_node, VisitNodeResult &result) { | ||
|
@@ -979,14 +988,10 @@ static void VisitNodeDeclContext( | |
if (generics->getChild(0) == nullptr) | ||
break; | ||
generics = generics->getFirstChild(); | ||
if (generics->getKind() != Demangle::Node::Kind::DependentGenericType) | ||
generics = DropGenericSignature(generics); | ||
if (generics == nullptr) | ||
break; | ||
if (generics->getChild(0) == nullptr) | ||
break; | ||
generics = generics->getFirstChild(); | ||
// if (generics->getKind() != | ||
// Demangle::Node::Kind::ArchetypeList) | ||
// break; | ||
|
||
AbstractFunctionDecl *func_decl = nullptr; | ||
for (Decl *decl : found_decls._decls) { | ||
func_decl = dyn_cast<AbstractFunctionDecl>(decl); | ||
|
@@ -1254,6 +1259,28 @@ static void VisitNodeFunction( | |
} | ||
} | ||
|
||
do { | ||
if (cur_node->getKind() == Demangle::Node::Kind::Subscript) { | ||
FindNamedDecls(ast, DeclBaseName::createSubscript(), | ||
decl_scope_result); | ||
if (decl_scope_result._decls.empty()) { | ||
result._error = stringWithFormat( | ||
"subscript identifier could not be found by name lookup"); | ||
break; | ||
} | ||
std::copy(decl_scope_result._decls.begin(), | ||
decl_scope_result._decls.end(), | ||
back_inserter(identifier_result._decls)); | ||
std::copy(decl_scope_result._types.begin(), | ||
decl_scope_result._types.end(), | ||
back_inserter(identifier_result._types)); | ||
identifier_result._module = decl_scope_result._module; | ||
if (decl_scope_result._decls.size() == 1) | ||
found_univocous = true; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is only used to break out of the earlier loop, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I’m just cargo culting the rest of the code in this function. Not sure I want to spend much time cleaning it up since most of it is going away soon. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In that case cargo-cult away, sir! |
||
break; | ||
} | ||
} while (0); | ||
|
||
// if (node_kind == Demangle::Node::Kind::Allocator) | ||
// { | ||
// // For allocators we don't have an identifier for | ||
|
@@ -1416,6 +1443,8 @@ static void VisitNodeSetterGetter( | |
Demangle::NodePointer cur_node, VisitNodeResult &result) { | ||
VisitNodeResult decl_ctx_result; | ||
std::string identifier; | ||
std::vector<StringRef> labels; | ||
|
||
VisitNodeResult type_result; | ||
|
||
assert(cur_node->getNumChildren() == 1 && | ||
|
@@ -1440,9 +1469,23 @@ static void VisitNodeSetterGetter( | |
case Demangle::Node::Kind::Identifier: | ||
identifier.assign((*pos)->getText()); | ||
break; | ||
case Demangle::Node::Kind::Type: | ||
VisitNode(ast, *pos, type_result); | ||
case Demangle::Node::Kind::Type: { | ||
auto type = (*pos)->getFirstChild(); | ||
if (DropGenericSignature(type)) | ||
type = type->getChild(1); | ||
VisitNode(ast, type, type_result); | ||
break; | ||
} | ||
case Demangle::Node::Kind::LabelList: { | ||
for (const auto &label : **pos) { | ||
if (label->getKind() == Demangle::Node::Kind::FirstElementMarker) | ||
labels.push_back(StringRef()); | ||
else { | ||
labels.push_back(label->getText()); | ||
} | ||
} | ||
break; | ||
} | ||
default: | ||
result._error = | ||
stringWithFormat("%s encountered in generic type children", | ||
|
@@ -1451,6 +1494,11 @@ static void VisitNodeSetterGetter( | |
} | ||
} | ||
|
||
if (!type_result.HasSingleType()) { | ||
result._error = "bad type"; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have a testcase for this case/diagnostic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No. These are invalid cases that should never come up (but maybe if your swiftmodule doesn’t match your debuginfo or something? I don’t know) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think we should worry too much (if we'll ever run across a case where this happens, we can consider adding a test), in particular considering that, as you say, this code might go away in the next while. |
||
return; | ||
} | ||
|
||
if (referenced_node->getKind() == Demangle::Node::Kind::Subscript) { | ||
// Since there can be many subscripts for the same nominal type, we need to | ||
// find the one matching the specified type. | ||
|
@@ -1467,9 +1515,6 @@ static void VisitNodeSetterGetter( | |
const AnyFunctionType *type_func = | ||
type_result._types.front()->getAs<AnyFunctionType>(); | ||
|
||
Type type_result_type = type_func->getResult(); | ||
Type type_input_type = type_func->getInput(); | ||
|
||
FuncDecl *identifier_func = nullptr; | ||
|
||
for (size_t i = 0; i < num_decls; i++) { | ||
|
@@ -1494,24 +1539,24 @@ static void VisitNodeSetterGetter( | |
break; | ||
} | ||
|
||
if (identifier_func && identifier_func->getInterfaceType()) { | ||
const AnyFunctionType *identifier_func_type = | ||
identifier_func->getInterfaceType()->getAs<AnyFunctionType>(); | ||
if (identifier_func_type) { | ||
if (identifier_func && | ||
subscript_decl->getGetter() && | ||
subscript_decl->getGetter()->getInterfaceType()) { | ||
auto subscript_type = | ||
subscript_decl->getGetter()->getInterfaceType()->getAs<AnyFunctionType>(); | ||
|
||
if (subscript_type) { | ||
// Swift function types are formally functions that take the class | ||
// and return the method, | ||
// we have to strip off the first level of function call to compare | ||
// against the type | ||
// from the demangled name. | ||
const AnyFunctionType *identifier_uncurried_result = | ||
identifier_func_type->getResult()->getAs<AnyFunctionType>(); | ||
if (identifier_uncurried_result) { | ||
Type identifier_result_type = | ||
identifier_uncurried_result->getResult(); | ||
Type identifier_input_type = | ||
identifier_uncurried_result->getInput(); | ||
if (identifier_result_type->isEqual(type_result_type) && | ||
identifier_input_type->isEqual(type_input_type)) { | ||
auto subscript_uncurried_result = | ||
subscript_type->getResult()->getAs<AnyFunctionType>(); | ||
if (subscript_uncurried_result) { | ||
if (CompareFunctionTypes(type_func, | ||
subscript_uncurried_result, | ||
labels)) { | ||
break; | ||
} | ||
} | ||
|
@@ -2061,6 +2106,25 @@ VisitNodeWeak(ASTContext *ast, | |
} | ||
} | ||
|
||
static void | ||
VisitNodeGenericParam(ASTContext *ast, | ||
Demangle::NodePointer cur_node, | ||
VisitNodeResult &result) { | ||
if (cur_node->getNumChildren() == 2) { | ||
auto first = cur_node->getChild(0); | ||
auto second = cur_node->getChild(1); | ||
if (first->getKind() == Demangle::Node::Kind::Index && | ||
second->getKind() == Demangle::Node::Kind::Index) { | ||
result._types.push_back( | ||
GenericTypeParamType::get(first->getIndex(), | ||
second->getIndex(), *ast)); | ||
return; | ||
} | ||
} | ||
|
||
result._error = "bad generic param type"; | ||
} | ||
|
||
static void VisitFirstChildNode( | ||
ASTContext *ast, | ||
Demangle::NodePointer cur_node, VisitNodeResult &result) { | ||
|
@@ -2159,7 +2223,8 @@ static void VisitNode( | |
|
||
case Demangle::Node::Kind::Function: | ||
case Demangle::Node::Kind::Allocator: | ||
case Demangle::Node::Kind::Variable: // Out of order on purpose | ||
case Demangle::Node::Kind::Variable: | ||
case Demangle::Node::Kind::Subscript: // Out of order on purpose | ||
VisitNodeFunction(ast, node, result); | ||
break; | ||
|
||
|
@@ -2229,6 +2294,10 @@ static void VisitNode( | |
VisitNodeWeak(ast, node, result); | ||
break; | ||
|
||
case Demangle::Node::Kind::DependentGenericParamType: | ||
VisitNodeGenericParam(ast, node, result); | ||
break; | ||
|
||
case Demangle::Node::Kind::LocalDeclName: | ||
case Demangle::Node::Kind::Identifier: | ||
case Demangle::Node::Kind::PrivateDeclName: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we get to this point do we really want to continue on to the code at line 1303?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See above