Only generate domains for PrintAsObjC-able types

Otherwise we generate a call to String(reflecting:), which correctly handles many things we may not be able to (like private types), and which matches the default implementation of Error._domain.
This commit is contained in:
Brent Royal-Gordon
2018-12-21 15:45:21 -08:00
parent 1a6ca82d6b
commit 2eed5374db
4 changed files with 68 additions and 6 deletions

View File

@@ -28,7 +28,34 @@ using namespace swift;
using namespace swift::objc_translation;
static void deriveBodyBridgedNSError_enum_nsErrorDomain(
AbstractFunctionDecl *domainDecl, void *) {
AbstractFunctionDecl *domainDecl, void *) {
// enum SomeEnum {
// @derived
// static var _nsErrorDomain: String {
// return _typeName(self, qualified: true)
// }
// }
auto M = domainDecl->getParentModule();
auto &C = M->getASTContext();
auto self = domainDecl->getImplicitSelfDecl();
auto selfRef = new (C) DeclRefExpr(self, DeclNameLoc(), /*implicit*/ true);
auto stringType = TypeExpr::createForDecl(SourceLoc(), C.getStringDecl(),
domainDecl, /*implicit*/ true);
auto initReflectingCall =
CallExpr::createImplicit(C, stringType,
{ selfRef }, { C.getIdentifier("reflecting") });
auto ret =
new (C) ReturnStmt(SourceLoc(), initReflectingCall, /*implicit*/ true);
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc());
domainDecl->setBody(body);
}
static void deriveBodyBridgedNSError_printAsObjCEnum_nsErrorDomain(
AbstractFunctionDecl *domainDecl, void *) {
// enum SomeEnum {
// @derived
// static var _nsErrorDomain: String {
@@ -52,11 +79,12 @@ static void deriveBodyBridgedNSError_enum_nsErrorDomain(
}
static ValueDecl *
deriveBridgedNSError_enum_nsErrorDomain(DerivedConformance &derived) {
deriveBridgedNSError_enum_nsErrorDomain(DerivedConformance &derived,
void (*synthesizer)(AbstractFunctionDecl *, void*)) {
// enum SomeEnum {
// @derived
// static var _nsErrorDomain: String {
// return "ModuleName.SomeEnum"
// ...
// }
// }
@@ -74,7 +102,7 @@ deriveBridgedNSError_enum_nsErrorDomain(DerivedConformance &derived) {
// Define the getter.
auto getterDecl = derived.addGetterToReadOnlyDerivedProperty(
derived.TC, propDecl, stringTy);
getterDecl->setBodySynthesizer(&deriveBodyBridgedNSError_enum_nsErrorDomain);
getterDecl->setBodySynthesizer(synthesizer);
derived.addMembersToConformanceContext({getterDecl, propDecl, pbDecl});
@@ -85,8 +113,17 @@ ValueDecl *DerivedConformance::deriveBridgedNSError(ValueDecl *requirement) {
if (!isa<EnumDecl>(Nominal))
return nullptr;
if (requirement->getBaseName() == TC.Context.Id_nsErrorDomain)
return deriveBridgedNSError_enum_nsErrorDomain(*this);
if (requirement->getBaseName() == TC.Context.Id_nsErrorDomain) {
auto synthesizer = deriveBodyBridgedNSError_enum_nsErrorDomain;
auto scope = Nominal->getFormalAccessScope(Nominal->getModuleScopeContext());
if (scope.isPublic() || scope.isInternal())
// PrintAsObjC may print this domain, so we should make sure we use the
// same string it will.
synthesizer = deriveBodyBridgedNSError_printAsObjCEnum_nsErrorDomain;
return deriveBridgedNSError_enum_nsErrorDomain(*this, synthesizer);
}
TC.diagnose(requirement->getLoc(), diag::broken_errortype_requirement);
return nullptr;