Skip to content

Commit 26fcf1a

Browse files
committed
[Clang importer] Properly create getter for bridged swift_newtype's rawValue.
When swift_newtype is introducing a new Swift type that wraps a bridged type, the actual storage (called _rawValue) matches the Objective-C type and "rawValue" itself is a computed properly. Properly create the getter for that computed property, which performs a bridging conversion.
1 parent c2c2f9e commit 26fcf1a

File tree

2 files changed

+80
-11
lines changed

2 files changed

+80
-11
lines changed

lib/ClangImporter/ImportDecl.cpp

Lines changed: 65 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -431,6 +431,59 @@ static FuncDecl *makeEnumRawValueGetter(ClangImporter::Implementation &Impl,
431431
return getterDecl;
432432
}
433433

434+
// Build the rawValue getter for a bridged, swift_newtype'd type.
435+
// struct SomeType: RawRepresentable {
436+
// var _rawValue: ObjCType
437+
// var rawValue: SwiftType {
438+
// return _rawValue as SwiftType
439+
// }
440+
// }
441+
static FuncDecl *makeNewtypeBridgedRawValueGetter(
442+
ClangImporter::Implementation &Impl,
443+
StructDecl *structDecl,
444+
VarDecl *computedVar,
445+
VarDecl *storedVar) {
446+
ASTContext &C = Impl.SwiftContext;
447+
448+
auto selfDecl = ParamDecl::createSelf(SourceLoc(), structDecl);
449+
450+
ParameterList *params[] = {
451+
ParameterList::createWithoutLoc(selfDecl),
452+
ParameterList::createEmpty(C)
453+
};
454+
455+
auto computedType = computedVar->getType();
456+
457+
auto getterDecl =
458+
FuncDecl::create(C, SourceLoc(), StaticSpellingKind::None, SourceLoc(),
459+
DeclName(), SourceLoc(), SourceLoc(), SourceLoc(), nullptr,
460+
Type(), params,
461+
TypeLoc::withoutLoc(computedType), structDecl);
462+
getterDecl->setImplicit();
463+
getterDecl->setType(ParameterList::getFullType(computedType, params));
464+
getterDecl->setBodyResultType(computedType);
465+
getterDecl->setAccessibility(Accessibility::Public);
466+
467+
computedVar->makeComputed(SourceLoc(), getterDecl, nullptr, nullptr,
468+
SourceLoc());
469+
470+
// Don't bother synthesizing the body if we've already finished type-checking.
471+
if (Impl.hasFinishedTypeChecking())
472+
return getterDecl;
473+
474+
auto selfRef = new (C) DeclRefExpr(selfDecl, DeclNameLoc(), /*implicit*/true);
475+
auto storedRef = new (C) MemberRefExpr(selfRef, SourceLoc(), storedVar,
476+
DeclNameLoc(), /*Implicit=*/true);
477+
auto coerce = new (C) CoerceExpr(storedRef, {}, {nullptr, computedType});
478+
auto ret = new (C) ReturnStmt(SourceLoc(), coerce);
479+
auto body = BraceStmt::create(C, SourceLoc(), ASTNode(ret), SourceLoc(),
480+
/*implicit*/ true);
481+
482+
getterDecl->setBody(body);
483+
C.addExternalDecl(getterDecl);
484+
return getterDecl;
485+
}
486+
434487
static FuncDecl *makeFieldGetterDecl(ClangImporter::Implementation &Impl,
435488
StructDecl *importedDecl,
436489
VarDecl *importedFieldDecl,
@@ -1668,18 +1721,21 @@ namespace {
16681721

16691722
//
16701723
// Create a computed value variable
1671-
auto dre = new (cxt) DeclRefExpr(
1672-
storedVar, {}, true, AccessSemantics::Ordinary, storedUnderlyingType);
1673-
auto coerce = new (cxt)
1674-
CoerceExpr(dre, {}, {nullptr, bridgedType});
1675-
auto computedVar = cast<VarDecl>(Impl.createConstant(
1676-
computedVarName, structDecl, bridgedType, coerce,
1677-
ConstantConvertKind::Coerce, false, {}));
1724+
auto computedVar = new (cxt) VarDecl(/*static*/ false,
1725+
/*IsLet*/ false,
1726+
SourceLoc(), computedVarName,
1727+
bridgedType, structDecl);
16781728
computedVar->setImplicit();
16791729
computedVar->setAccessibility(Accessibility::Public);
1730+
computedVar->setSetterAccessibility(Accessibility::Private);
16801731

1681-
// Create a pattern binding to describe the variable.
1732+
// Create the getter for the computed value variable.
1733+
auto computedVarGetter = makeNewtypeBridgedRawValueGetter(Impl,
1734+
structDecl,
1735+
computedVar,
1736+
storedVar);
16821737

1738+
// Create a pattern binding to describe the variable.
16831739
Pattern *computedVarPattern = createTypedNamedPattern(computedVar);
16841740
auto computedPatternBinding = PatternBindingDecl::create(
16851741
cxt, SourceLoc(), StaticSpellingKind::None, SourceLoc(),
@@ -1711,9 +1767,6 @@ namespace {
17111767
/*Implicit=*/true);
17121768
auto body = BraceStmt::create(cxt, SourceLoc(), {assign}, SourceLoc());
17131769
init->setBody(body);
1714-
1715-
// We want to inline away as much of this as we can
1716-
init->getAttrs().add(new (cxt) TransparentAttr(/*implicit*/ true));
17171770
}
17181771

17191772
structDecl->setHasDelayedMembers();
@@ -1722,6 +1775,7 @@ namespace {
17221775
structDecl->addMember(storedVar);
17231776
structDecl->addMember(computedPatternBinding);
17241777
structDecl->addMember(computedVar);
1778+
structDecl->addMember(computedVarGetter);
17251779
}
17261780

17271781
/// \brief Create a constructor that initializes a struct from its members.

test/SILGen/newtype.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,18 @@ func createErrorDomain(str: String) -> ErrorDomain {
2424
// CHECK-RAW: [[BRIDGED:%[0-9]+]] = apply [[BRIDGE_FN]]([[STR]])
2525
// CHECK-RAW: [[RAWVALUE_ADDR:%[0-9]+]] = struct_element_addr [[UNINIT_SELF]]
2626
// CHECK-RAW: assign [[BRIDGED]] to [[RAWVALUE_ADDR]]
27+
28+
func getRawValue(ed: ErrorDomain) -> String {
29+
return ed.rawValue
30+
}
31+
32+
// CHECK-RAW-LABEL: sil shared @_TFVSC11ErrorDomaing8rawValueSS
33+
// CHECK-RAW: bb0([[SELF:%[0-9]+]] : $ErrorDomain):
34+
// CHECK-RAW: [[FORCE_BRIDGE:%[0-9]+]] = function_ref @_forceBridgeFromObjectiveC_bridgeable
35+
// CHECK-RAW: [[STORED_VALUE:%[0-9]+]] = struct_extract [[SELF]] : $ErrorDomain, #ErrorDomain._rawValue
36+
// CHECK-RAW: [[STRING_META:%[0-9]+]] = metatype $@thick String.Type
37+
// CHECK-RAW: [[STRING_RESULT_ADDR:%[0-9]+]] = alloc_stack $String
38+
// CHECK-RAW: apply [[FORCE_BRIDGE]]<String, NSString>([[STRING_RESULT_ADDR]], [[STORED_VALUE]], [[STRING_META]])
39+
// CHECK-RAW: [[STRING_RESULT:%[0-9]+]] = load [[STRING_RESULT_ADDR]]
40+
// CHECK-RAW: return [[STRING_RESULT]]
41+

0 commit comments

Comments
 (0)