mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
Verify that a function's DeclName, TuplePattern, and ParamDecls are in sync.
This required a few changes in places where we synthesize functions to make sure these properties hold. That's good because we don't know where we might already be depending on them. (On the other hand, we could also decide not to care about TuplePattern labels, in which case I wonder if we could eventually discard them altogether in functions.) Still untested: that the function type is also in sync.
This commit is contained in:
@@ -2117,6 +2117,87 @@ struct ASTNodeBase {};
|
|||||||
void verifyChecked(AbstractFunctionDecl *AFD) {
|
void verifyChecked(AbstractFunctionDecl *AFD) {
|
||||||
PrettyStackTraceDecl debugStack("verifying AbstractFunctionDecl", AFD);
|
PrettyStackTraceDecl debugStack("verifying AbstractFunctionDecl", AFD);
|
||||||
|
|
||||||
|
// All of the parameter names should match.
|
||||||
|
if (!isa<DestructorDecl>(AFD)) {
|
||||||
|
auto paramNames = AFD->getFullName().getArgumentNames();
|
||||||
|
bool checkParamNames = (bool)AFD->getFullName();
|
||||||
|
bool hasSelf = AFD->getDeclContext()->isTypeContext();
|
||||||
|
const Pattern *firstParams =
|
||||||
|
AFD->getBodyParamPatterns()[hasSelf ? 1 : 0];
|
||||||
|
|
||||||
|
if (auto *paramTuple = dyn_cast<TuplePattern>(firstParams)) {
|
||||||
|
if (checkParamNames &&
|
||||||
|
paramNames.size() != paramTuple->getNumElements()) {
|
||||||
|
Out << "Function name does not match its argument pattern ("
|
||||||
|
<< paramNames.size() << " elements instead of "
|
||||||
|
<< paramTuple->getNumElements() << ")\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
// This doesn't use for_each because paramNames shouldn't be checked
|
||||||
|
// when the function is anonymous.
|
||||||
|
for (size_t i = 0, e = paramTuple->getNumElements(); i < e; ++i) {
|
||||||
|
TuplePatternElt elt = paramTuple->getElement(i);
|
||||||
|
Pattern *param = elt.getPattern()->getSemanticsProvidingPattern();
|
||||||
|
if (auto *namedParam = dyn_cast<NamedPattern>(param)) {
|
||||||
|
if (namedParam->getBoundName() != elt.getLabel()) {
|
||||||
|
Out << "Function body param tuple label "
|
||||||
|
"doesn't match variable's public name\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkParamNames &&
|
||||||
|
namedParam->getBoundName() != paramNames[i]) {
|
||||||
|
Out << "Function full name doesn't match variable name\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(isa<AnyPattern>(param));
|
||||||
|
if (!elt.getLabel().empty()) {
|
||||||
|
Out << "Function body param tuple has a label, "
|
||||||
|
"but there's no variable\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (checkParamNames && !paramNames[i].empty()) {
|
||||||
|
Out << "Function full name doesn't match variable name\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (checkParamNames && paramNames.size() != 1) {
|
||||||
|
Out << "Function name does not match its non-tuple argument pattern ("
|
||||||
|
<< paramNames.size() << " elements instead of 1)\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
|
||||||
|
firstParams = firstParams->getSemanticsProvidingPattern();
|
||||||
|
if (auto *namedParam = dyn_cast<NamedPattern>(firstParams)) {
|
||||||
|
if (checkParamNames &&
|
||||||
|
namedParam->getBoundName() != paramNames.front()) {
|
||||||
|
Out << "Function full name doesn't match variable name\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
assert(isa<AnyPattern>(firstParams));
|
||||||
|
if (checkParamNames && !paramNames.front().empty()) {
|
||||||
|
Out << "Function full name has an argument name, "
|
||||||
|
"but there's no variable\n";
|
||||||
|
AFD->dump(Out);
|
||||||
|
abort();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If this function is generic or is within a generic type, it should
|
// If this function is generic or is within a generic type, it should
|
||||||
// have an interface type.
|
// have an interface type.
|
||||||
if ((AFD->getGenericParams() ||
|
if ((AFD->getGenericParams() ||
|
||||||
|
|||||||
@@ -584,6 +584,7 @@ makeEnumRawValueConstructor(ClangImporter::Implementation &Impl,
|
|||||||
paramPattern->setImplicit();
|
paramPattern->setImplicit();
|
||||||
|
|
||||||
auto patternElt = TuplePatternElt(paramPattern);
|
auto patternElt = TuplePatternElt(paramPattern);
|
||||||
|
patternElt.setLabel(C.Id_rawValue, SourceLoc());
|
||||||
paramPattern = TuplePattern::create(C, SourceLoc(), patternElt, SourceLoc());
|
paramPattern = TuplePattern::create(C, SourceLoc(), patternElt, SourceLoc());
|
||||||
paramPattern->setImplicit();
|
paramPattern->setImplicit();
|
||||||
auto typeElt = TupleTypeElt(enumDecl->getRawType(), C.Id_rawValue);
|
auto typeElt = TupleTypeElt(enumDecl->getRawType(), C.Id_rawValue);
|
||||||
@@ -1767,6 +1768,7 @@ namespace {
|
|||||||
Pattern *pattern = createTypedNamedPattern(param);
|
Pattern *pattern = createTypedNamedPattern(param);
|
||||||
paramPatterns.push_back(pattern);
|
paramPatterns.push_back(pattern);
|
||||||
patternElts.push_back(TuplePatternElt(pattern));
|
patternElts.push_back(TuplePatternElt(pattern));
|
||||||
|
patternElts.back().setLabel(argName, SourceLoc());
|
||||||
tupleElts.push_back(TupleTypeElt(var->getType(), var->getName()));
|
tupleElts.push_back(TupleTypeElt(var->getType(), var->getName()));
|
||||||
}
|
}
|
||||||
auto paramPattern = TuplePattern::create(context, SourceLoc(), patternElts,
|
auto paramPattern = TuplePattern::create(context, SourceLoc(), patternElts,
|
||||||
|
|||||||
@@ -1456,7 +1456,8 @@ Type ClangImporter::Implementation::importFunctionType(
|
|||||||
TypeLoc::withoutLoc(swiftParamTy));
|
TypeLoc::withoutLoc(swiftParamTy));
|
||||||
bodyPattern->setType(swiftParamTy);
|
bodyPattern->setType(swiftParamTy);
|
||||||
bodyPatternElts.push_back(TuplePatternElt(bodyPattern));
|
bodyPatternElts.push_back(TuplePatternElt(bodyPattern));
|
||||||
|
bodyPatternElts.back().setLabel(name, SourceLoc());
|
||||||
|
|
||||||
// Add the tuple elements for the function types.
|
// Add the tuple elements for the function types.
|
||||||
swiftArgParams.push_back(TupleTypeElt(swiftParamTy, name));
|
swiftArgParams.push_back(TupleTypeElt(swiftParamTy, name));
|
||||||
swiftBodyParams.push_back(TupleTypeElt(swiftParamTy, bodyName));
|
swiftBodyParams.push_back(TupleTypeElt(swiftParamTy, bodyName));
|
||||||
@@ -2316,6 +2317,7 @@ Type ClangImporter::Implementation::importMethodType(
|
|||||||
pattern->setType(type);
|
pattern->setType(type);
|
||||||
|
|
||||||
bodyPatternElts.push_back(TuplePatternElt(pattern));
|
bodyPatternElts.push_back(TuplePatternElt(pattern));
|
||||||
|
bodyPatternElts.back().setLabel(argName, SourceLoc());
|
||||||
swiftArgParams.push_back(TupleTypeElt(type, argName));
|
swiftArgParams.push_back(TupleTypeElt(type, argName));
|
||||||
swiftBodyParams.push_back(TupleTypeElt(type, argName));
|
swiftBodyParams.push_back(TupleTypeElt(type, argName));
|
||||||
};
|
};
|
||||||
@@ -2463,6 +2465,7 @@ Type ClangImporter::Implementation::importMethodType(
|
|||||||
bodyPattern->setType(swiftParamTy);
|
bodyPattern->setType(swiftParamTy);
|
||||||
TuplePatternElt patternElt(bodyPattern);
|
TuplePatternElt patternElt(bodyPattern);
|
||||||
patternElt.setDefaultArgKind(defaultArg);
|
patternElt.setDefaultArgKind(defaultArg);
|
||||||
|
patternElt.setLabel(name, SourceLoc());
|
||||||
bodyPatternElts.push_back(patternElt);
|
bodyPatternElts.push_back(patternElt);
|
||||||
|
|
||||||
// Add the tuple elements for the function types.
|
// Add the tuple elements for the function types.
|
||||||
|
|||||||
@@ -155,9 +155,10 @@ static Pattern *buildIndexForwardingPattern(AbstractStorageDecl *storage,
|
|||||||
// Clone index patterns in a manner that allows them to be
|
// Clone index patterns in a manner that allows them to be
|
||||||
// perfectly forwarded.
|
// perfectly forwarded.
|
||||||
DeclContext *DC = storage->getDeclContext();
|
DeclContext *DC = storage->getDeclContext();
|
||||||
auto addVarPatternFor = [&](Pattern *P) {
|
auto addVarPatternFor = [&](Pattern *P, Identifier label = Identifier()) {
|
||||||
Pattern *vp = P->cloneForwardable(TC.Context, DC, Pattern::Implicit);
|
Pattern *vp = P->cloneForwardable(TC.Context, DC, Pattern::Implicit);
|
||||||
elements.push_back(TuplePatternElt(vp));
|
elements.push_back(TuplePatternElt(vp));
|
||||||
|
elements.back().setLabel(label, SourceLoc());
|
||||||
};
|
};
|
||||||
|
|
||||||
// This is the same breakdown the parser does.
|
// This is the same breakdown the parser does.
|
||||||
@@ -167,7 +168,7 @@ static Pattern *buildIndexForwardingPattern(AbstractStorageDecl *storage,
|
|||||||
} else {
|
} else {
|
||||||
auto tp = cast<TuplePattern>(indices);
|
auto tp = cast<TuplePattern>(indices);
|
||||||
for (auto &element : tp->getElements()) {
|
for (auto &element : tp->getElements()) {
|
||||||
addVarPatternFor(element.getPattern());
|
addVarPatternFor(element.getPattern(), element.getLabel());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user