mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[IDE] Teach type checker about conditional conformance extensions.
Before conditional conformances, the archetypes in conformance extensions (i.e. extension Foo: SomeProtocol) were equivalent to those in the type decl, with the same protocol bounds and so on. The code for printing "synthesized" members relied on this fact. This commit teaches that code to deal with archetypes in the conditional conformance extension when required. Fixes rdar://problem/36553066 and SR-6930.
This commit is contained in:
@@ -55,7 +55,7 @@ void PrintOptions::setBaseType(Type T) {
|
||||
TransformContext = TypeTransformContext(T);
|
||||
}
|
||||
|
||||
void PrintOptions::initForSynthesizedExtension(NominalTypeDecl *D) {
|
||||
void PrintOptions::initForSynthesizedExtension(TypeOrExtensionDecl D) {
|
||||
TransformContext = TypeTransformContext(D);
|
||||
}
|
||||
|
||||
@@ -63,16 +63,40 @@ void PrintOptions::clearSynthesizedExtension() {
|
||||
TransformContext.reset();
|
||||
}
|
||||
|
||||
TypeOrExtensionDecl::TypeOrExtensionDecl(NominalTypeDecl *D) : Decl(D) {}
|
||||
TypeOrExtensionDecl::TypeOrExtensionDecl(ExtensionDecl *D) : Decl(D) {}
|
||||
|
||||
Decl *TypeOrExtensionDecl::getAsDecl() const {
|
||||
if (auto NTD = Decl.dyn_cast<NominalTypeDecl *>())
|
||||
return NTD;
|
||||
|
||||
return Decl.get<ExtensionDecl *>();
|
||||
}
|
||||
DeclContext *TypeOrExtensionDecl::getAsDeclContext() const {
|
||||
return getAsDecl()->getInnermostDeclContext();
|
||||
}
|
||||
NominalTypeDecl *TypeOrExtensionDecl::getBaseNominal() const {
|
||||
return getAsDeclContext()->getAsNominalTypeOrNominalTypeExtensionContext();
|
||||
}
|
||||
bool TypeOrExtensionDecl::isNull() const { return Decl.isNull(); }
|
||||
|
||||
TypeTransformContext::TypeTransformContext(Type T)
|
||||
: BaseType(T.getPointer()) {
|
||||
assert(T->mayHaveMembers());
|
||||
}
|
||||
|
||||
TypeTransformContext::TypeTransformContext(NominalTypeDecl *NTD)
|
||||
: BaseType(NTD->getDeclaredTypeInContext().getPointer()), Nominal(NTD) {}
|
||||
TypeTransformContext::TypeTransformContext(TypeOrExtensionDecl D)
|
||||
: BaseType(nullptr), Decl(D) {
|
||||
if (auto NTD = Decl.Decl.dyn_cast<NominalTypeDecl *>())
|
||||
BaseType = NTD->getDeclaredTypeInContext().getPointer();
|
||||
else
|
||||
BaseType = Decl.Decl.get<ExtensionDecl *>()->getExtendedType().getPointer();
|
||||
}
|
||||
|
||||
NominalTypeDecl *TypeTransformContext::getNominal() const {
|
||||
return Nominal;
|
||||
TypeOrExtensionDecl TypeTransformContext::getDecl() const { return Decl; }
|
||||
|
||||
DeclContext *TypeTransformContext::getDeclContext() const {
|
||||
return Decl.getAsDecl()->getDeclContext();
|
||||
}
|
||||
|
||||
Type TypeTransformContext::getBaseType() const {
|
||||
@@ -80,7 +104,7 @@ Type TypeTransformContext::getBaseType() const {
|
||||
}
|
||||
|
||||
bool TypeTransformContext::isPrintingSynthesizedExtension() const {
|
||||
return Nominal != nullptr;
|
||||
return !Decl.isNull();
|
||||
}
|
||||
|
||||
std::string ASTPrinter::sanitizeUtf8(StringRef Text) {
|
||||
@@ -631,8 +655,7 @@ private:
|
||||
#define STMT(Name, Parent) void visit##Name##Stmt(Name##Stmt *stmt);
|
||||
#include "swift/AST/StmtNodes.def"
|
||||
|
||||
void printSynthesizedExtension(NominalTypeDecl* Decl,
|
||||
ExtensionDecl* ExtDecl);
|
||||
void printSynthesizedExtension(Type ExtendedType, ExtensionDecl *ExtDecl);
|
||||
|
||||
void printExtension(ExtensionDecl* ExtDecl);
|
||||
|
||||
@@ -668,8 +691,9 @@ public:
|
||||
Options.TransformContext &&
|
||||
Options.TransformContext->isPrintingSynthesizedExtension() &&
|
||||
isa<ExtensionDecl>(D);
|
||||
if (Synthesize)
|
||||
Printer.setSynthesizedTarget(Options.TransformContext->getNominal());
|
||||
if (Synthesize) {
|
||||
Printer.setSynthesizedTarget(Options.TransformContext->getDecl());
|
||||
}
|
||||
|
||||
// We want to print a newline before doc comments. Swift code already
|
||||
// handles this, but we need to insert it for clang doc comments when not
|
||||
@@ -692,10 +716,10 @@ public:
|
||||
ASTVisitor::visit(D);
|
||||
|
||||
if (Synthesize) {
|
||||
Printer.setSynthesizedTarget(nullptr);
|
||||
Printer.printSynthesizedExtensionPost(
|
||||
cast<ExtensionDecl>(D), Options.TransformContext->getNominal(),
|
||||
Options.BracketOptions);
|
||||
Printer.setSynthesizedTarget({});
|
||||
Printer.printSynthesizedExtensionPost(cast<ExtensionDecl>(D),
|
||||
Options.TransformContext->getDecl(),
|
||||
Options.BracketOptions);
|
||||
} else {
|
||||
Printer.callPrintDeclPost(D, Options.BracketOptions);
|
||||
}
|
||||
@@ -1775,14 +1799,14 @@ static void printExtendedTypeName(Type ExtendedType, ASTPrinter &Printer,
|
||||
Printer.printTypeRef(ExtendedType, Nominal, Nominal->getName());
|
||||
}
|
||||
|
||||
void PrintAST::
|
||||
printSynthesizedExtension(NominalTypeDecl* Decl, ExtensionDecl *ExtDecl) {
|
||||
void PrintAST::printSynthesizedExtension(Type ExtendedType,
|
||||
ExtensionDecl *ExtDecl) {
|
||||
if (Options.BracketOptions.shouldOpenExtension(ExtDecl)) {
|
||||
printDocumentationComment(ExtDecl);
|
||||
printAttributes(ExtDecl);
|
||||
Printer << tok::kw_extension << " ";
|
||||
|
||||
printExtendedTypeName(Decl->getDeclaredType(), Printer, Options);
|
||||
printExtendedTypeName(ExtendedType, Printer, Options);
|
||||
printInherited(ExtDecl);
|
||||
|
||||
if (ExtDecl->getGenericParams())
|
||||
@@ -1832,9 +1856,11 @@ void PrintAST::printExtension(ExtensionDecl *decl) {
|
||||
|
||||
void PrintAST::visitExtensionDecl(ExtensionDecl *decl) {
|
||||
if (Options.TransformContext &&
|
||||
Options.TransformContext->isPrintingSynthesizedExtension())
|
||||
printSynthesizedExtension(Options.TransformContext->getNominal(), decl);
|
||||
else
|
||||
Options.TransformContext->isPrintingSynthesizedExtension()) {
|
||||
auto extendedType =
|
||||
Options.TransformContext->getBaseType()->mapTypeOutOfContext();
|
||||
printSynthesizedExtension(extendedType, decl);
|
||||
} else
|
||||
printExtension(decl);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user