Skip to content

Commit ce4ec08

Browse files
authored
Merge pull request #62838 from xedin/type-wrappers-and-swiftinterfaces
[Sema] TypeWrappers: If type wrapper comes from `.swiftinterface` use synthesized decls
2 parents c945561 + 4f84d8a commit ce4ec08

File tree

10 files changed

+168
-135
lines changed

10 files changed

+168
-135
lines changed

include/swift/AST/TypeCheckRequests.h

Lines changed: 0 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -3546,23 +3546,6 @@ class GetTypeWrapper
35463546
bool isCached() const { return true; }
35473547
};
35483548

3549-
/// Return a type of the type wrapper (if any) associated with the given
3550-
/// declaration.
3551-
class GetTypeWrapperType
3552-
: public SimpleRequest<GetTypeWrapperType, Type(NominalTypeDecl *),
3553-
RequestFlags::Cached> {
3554-
public:
3555-
using SimpleRequest::SimpleRequest;
3556-
3557-
private:
3558-
friend SimpleRequest;
3559-
3560-
Type evaluate(Evaluator &evaluator, NominalTypeDecl *) const;
3561-
3562-
public:
3563-
bool isCached() const { return true; }
3564-
};
3565-
35663549
/// Inject or get `$Storage` type which has all of the stored properties
35673550
/// of the given type with a type wrapper.
35683551
class GetTypeWrapperStorage
@@ -3762,23 +3745,6 @@ class GetTypeWrapperInitializer
37623745
bool isCached() const { return true; }
37633746
};
37643747

3765-
/// Check whether this is a protocol that has a type wrapper attribute
3766-
/// or one of its dependencies does.
3767-
class UsesTypeWrapperFeature
3768-
: public SimpleRequest<UsesTypeWrapperFeature, bool(NominalTypeDecl *),
3769-
RequestFlags::Cached> {
3770-
public:
3771-
using SimpleRequest::SimpleRequest;
3772-
3773-
private:
3774-
friend SimpleRequest;
3775-
3776-
bool evaluate(Evaluator &evaluator, NominalTypeDecl *) const;
3777-
3778-
public:
3779-
bool isCached() const { return true; }
3780-
};
3781-
37823748
/// Find the definition of a given macro.
37833749
class MacroDefinitionRequest
37843750
: public SimpleRequest<MacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -404,9 +404,6 @@ SWIFT_REQUEST(TypeChecker, GetSourceFileAsyncNode,
404404
SWIFT_REQUEST(TypeChecker, GetTypeWrapper,
405405
Optional<TypeWrapperInfo>(NominalTypeDecl *),
406406
Cached, NoLocationInfo)
407-
SWIFT_REQUEST(TypeChecker, GetTypeWrapperType,
408-
Type(NominalTypeDecl *),
409-
Cached, NoLocationInfo)
410407
SWIFT_REQUEST(TypeChecker, GetTypeWrapperStorage,
411408
TypeDecl *(NominalTypeDecl *),
412409
Cached, NoLocationInfo)
@@ -443,9 +440,6 @@ SWIFT_REQUEST(TypeChecker, ContinueTargetRequest,
443440
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
444441
ConstructorDecl *(NominalTypeDecl *),
445442
Cached, NoLocationInfo)
446-
SWIFT_REQUEST(TypeChecker, UsesTypeWrapperFeature,
447-
bool(NominalTypeDecl *),
448-
Cached, NoLocationInfo)
449443
SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
450444
MacroDefinition(MacroDecl *),
451445
Cached, NoLocationInfo)

include/swift/AST/TypeWrappers.h

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,17 +21,18 @@ namespace swift {
2121

2222
struct TypeWrapperInfo {
2323
CustomAttr *Attr;
24+
Type AttrType;
2425
NominalTypeDecl *Wrapper;
2526
NominalTypeDecl *AttachedTo;
2627
bool IsInferred;
2728

28-
TypeWrapperInfo(CustomAttr *attr, NominalTypeDecl *wrapperDecl,
29+
TypeWrapperInfo(CustomAttr *attr, Type attrType, NominalTypeDecl *wrapperDecl,
2930
NominalTypeDecl *attachedTo, bool isInferred)
30-
: Attr(attr), Wrapper(wrapperDecl), AttachedTo(attachedTo),
31-
IsInferred(isInferred) {}
31+
: Attr(attr), AttrType(attrType), Wrapper(wrapperDecl),
32+
AttachedTo(attachedTo), IsInferred(isInferred) {}
3233

3334
TypeWrapperInfo asInferred() const {
34-
return {Attr, Wrapper, AttachedTo, true};
35+
return {Attr, AttrType, Wrapper, AttachedTo, true};
3536
}
3637
};
3738

lib/AST/ASTPrinter.cpp

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2949,19 +2949,7 @@ static bool usesFeatureSpecializeAttributeWithAvailability(Decl *decl) {
29492949
}
29502950

29512951
static bool usesFeatureTypeWrappers(Decl *decl) {
2952-
NullablePtr<NominalTypeDecl> typeDecl;
2953-
2954-
if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
2955-
typeDecl = extension->getExtendedNominal();
2956-
} else {
2957-
typeDecl = dyn_cast<NominalTypeDecl>(decl);
2958-
}
2959-
2960-
if (!typeDecl)
2961-
return false;
2962-
2963-
return evaluateOrDefault(decl->getASTContext().evaluator,
2964-
UsesTypeWrapperFeature{typeDecl.get()}, false);
2952+
return false;
29652953
}
29662954

29672955
static bool usesFeatureRuntimeDiscoverableAttrs(Decl *decl) {

lib/AST/TypeWrapper.cpp

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -44,53 +44,3 @@ bool VarDecl::isTypeWrapperLocalStorageForInitializer() const {
4444
}
4545
return false;
4646
}
47-
48-
bool UsesTypeWrapperFeature::evaluate(Evaluator &evaluator,
49-
NominalTypeDecl *decl) const {
50-
// This is a type wrapper type.
51-
if (decl->getAttrs().hasAttribute<TypeWrapperAttr>())
52-
return true;
53-
54-
// This is a type wrapped type.
55-
if (decl->hasTypeWrapper())
56-
return true;
57-
58-
// This type could be depending on a type wrapper feature
59-
// indirectly by conforming to a protocol with a type
60-
// wrapper attribute. To determine that we need to walk
61-
// protocol dependency chains and check each one.
62-
63-
auto &ctx = decl->getASTContext();
64-
65-
auto usesTypeWrapperFeature = [&](ProtocolDecl *protocol) {
66-
return evaluateOrDefault(ctx.evaluator, UsesTypeWrapperFeature{protocol},
67-
false);
68-
};
69-
70-
for (unsigned i : indices(decl->getInherited())) {
71-
auto inheritedType = evaluateOrDefault(
72-
ctx.evaluator,
73-
InheritedTypeRequest{decl, i, TypeResolutionStage::Interface}, Type());
74-
75-
if (!(inheritedType && inheritedType->isConstraintType()))
76-
continue;
77-
78-
if (auto *protocol =
79-
dyn_cast_or_null<ProtocolDecl>(inheritedType->getAnyNominal())) {
80-
if (usesTypeWrapperFeature(protocol))
81-
return true;
82-
}
83-
84-
if (auto composition = inheritedType->getAs<ProtocolCompositionType>()) {
85-
for (auto member : composition->getMembers()) {
86-
if (auto *protocol =
87-
dyn_cast_or_null<ProtocolDecl>(member->getAnyNominal())) {
88-
if (usesTypeWrapperFeature(protocol))
89-
return true;
90-
}
91-
}
92-
}
93-
}
94-
95-
return false;
96-
}

lib/Sema/CodeSynthesis.cpp

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
362362
params.push_back(arg);
363363
}
364364
} else if (ICK == ImplicitConstructorKind::TypeWrapperStorage) {
365-
accessLevel = AccessLevel::Public;
365+
accessLevel = decl->getTypeWrapperStorageDecl()->getFormalAccess();
366366

367367
auto typeWrapperInfo = decl->getTypeWrapper();
368368
assert(typeWrapperInfo);
@@ -1657,14 +1657,29 @@ ConstructorDecl *SynthesizeTypeWrappedTypeStorageWrapperInitializer::evaluate(
16571657
if (!wrappedType->hasTypeWrapper())
16581658
return nullptr;
16591659

1660+
auto &ctx = wrappedType->getASTContext();
1661+
1662+
// .swiftinterfaces have both attribute and a synthesized member
1663+
// (if it's public), so in this case we need use existing declaration
1664+
// if available.
1665+
{
1666+
auto parentSF = wrappedType->getDeclContext()->getParentSourceFile();
1667+
if (parentSF && parentSF->Kind == SourceFileKind::Interface) {
1668+
DeclName initName(ctx, DeclBaseName::createConstructor(),
1669+
/*labels=*/{ctx.Id_storageWrapper});
1670+
auto results = wrappedType->lookupDirect(initName);
1671+
if (results.size() == 1)
1672+
return cast<ConstructorDecl>(results.front());
1673+
}
1674+
}
1675+
16601676
// `@typeWrapperIgnored` properties suppress this initializer.
16611677
if (llvm::any_of(wrappedType->getMembers(), [&](Decl *member) {
16621678
return member->getAttrs().hasAttribute<TypeWrapperIgnoredAttr>();
16631679
}))
16641680
return nullptr;
16651681

16661682
// Create the implicit type wrapper storage constructor.
1667-
auto &ctx = wrappedType->getASTContext();
16681683
auto ctor = createImplicitConstructor(
16691684
wrappedType, ImplicitConstructorKind::TypeWrapperStorage, ctx);
16701685
wrappedType->addMember(ctor);

lib/Sema/TypeCheckAttr.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3826,7 +3826,16 @@ void AttributeChecker::visitPropertyWrapperAttr(PropertyWrapperAttr *attr) {
38263826
}
38273827

38283828
void AttributeChecker::visitTypeWrapperAttr(TypeWrapperAttr *attr) {
3829-
if (!Ctx.LangOpts.hasFeature(Feature::TypeWrappers)) {
3829+
auto isEnabled = [&]() {
3830+
if (Ctx.LangOpts.hasFeature(Feature::TypeWrappers))
3831+
return true;
3832+
3833+
// Accept attributes that come from swiftinterface files.
3834+
auto *parentSF = D->getDeclContext()->getParentSourceFile();
3835+
return parentSF && parentSF->Kind == SourceFileKind::Interface;
3836+
};
3837+
3838+
if (!isEnabled()) {
38303839
diagnose(attr->getLocation(), diag::type_wrappers_are_experimental);
38313840
attr->setInvalid();
38323841
return;

lib/Sema/TypeCheckTypeWrapper.cpp

Lines changed: 42 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,17 @@
2626

2727
using namespace swift;
2828

29+
/// Check whether given declaration comes from the .swiftinterface file.
30+
static bool inSwiftInterfaceContext(NominalTypeDecl *typeDecl) {
31+
auto *SF = typeDecl->getDeclContext()->getParentSourceFile();
32+
return SF && SF->Kind == SourceFileKind::Interface;
33+
}
34+
35+
static ValueDecl *findMember(NominalTypeDecl *typeDecl, Identifier memberName) {
36+
auto members = typeDecl->lookupDirect(memberName);
37+
return members.size() == 1 ? members.front() : nullptr;
38+
}
39+
2940
static PatternBindingDecl *injectVariable(DeclContext *DC, Identifier name,
3041
Type type,
3142
VarDecl::Introducer introducer,
@@ -119,9 +130,19 @@ static void getTypeWrappers(NominalTypeDecl *decl,
119130
continue;
120131

121132
auto *typeWrapper = nominal->getAttrs().getAttribute<TypeWrapperAttr>();
122-
if (typeWrapper && typeWrapper->isValid())
133+
if (typeWrapper && typeWrapper->isValid()) {
134+
auto attrType = evaluateOrDefault(
135+
ctx.evaluator,
136+
CustomAttrTypeRequest{mutableAttr, decl,
137+
CustomAttrTypeKind::TypeWrapper},
138+
Type());
139+
140+
if (!attrType || attrType->hasError())
141+
continue;
142+
123143
typeWrappers.push_back(
124-
{mutableAttr, nominal, decl, /*isInferred=*/false});
144+
{mutableAttr, attrType, nominal, decl, /*isInferred=*/false});
145+
}
125146
}
126147

127148
// Do not allow transitive protocol inference between protocols.
@@ -184,24 +205,6 @@ GetTypeWrapper::evaluate(Evaluator &evaluator, NominalTypeDecl *decl) const {
184205
return typeWrappers.front();
185206
}
186207

187-
Type GetTypeWrapperType::evaluate(Evaluator &evaluator,
188-
NominalTypeDecl *decl) const {
189-
auto typeWrapperInfo = decl->getTypeWrapper();
190-
if (!typeWrapperInfo)
191-
return Type();
192-
193-
auto type = evaluateOrDefault(
194-
evaluator,
195-
CustomAttrTypeRequest{typeWrapperInfo->Attr, decl->getDeclContext(),
196-
CustomAttrTypeKind::TypeWrapper},
197-
Type());
198-
199-
if (!type || type->hasError()) {
200-
return ErrorType::get(decl->getASTContext());
201-
}
202-
return type;
203-
}
204-
205208
VarDecl *NominalTypeDecl::getTypeWrapperProperty() const {
206209
auto *mutableSelf = const_cast<NominalTypeDecl *>(this);
207210
return evaluateOrDefault(getASTContext().evaluator,
@@ -284,6 +287,15 @@ TypeDecl *GetTypeWrapperStorage::evaluate(Evaluator &evaluator,
284287

285288
auto &ctx = parent->getASTContext();
286289

290+
// .swiftinterfaces have both attribute and a synthesized member
291+
// (if it's public), so in this case we need use existing declaration
292+
// if available.
293+
if (inSwiftInterfaceContext(parent)) {
294+
if (auto *storage = dyn_cast_or_null<TypeDecl>(
295+
findMember(parent, ctx.Id_TypeWrapperStorage)))
296+
return storage;
297+
}
298+
287299
TypeDecl *storage = nullptr;
288300
if (isa<ProtocolDecl>(parent)) {
289301
// If type wrapper is associated with a protocol, we need to
@@ -320,13 +332,19 @@ GetTypeWrapperProperty::evaluate(Evaluator &evaluator,
320332
if (!typeWrapper)
321333
return nullptr;
322334

335+
// .swiftinterfaces have both attribute and a synthesized member
336+
// (if it's public), so in this case we need use existing declaration
337+
// if available.
338+
if (inSwiftInterfaceContext(parent)) {
339+
if (auto *storage = dyn_cast_or_null<VarDecl>(
340+
findMember(parent, ctx.Id_TypeWrapperProperty)))
341+
return storage;
342+
}
343+
323344
auto *storage = parent->getTypeWrapperStorageDecl();
324345
assert(storage);
325346

326-
auto *typeWrapperType =
327-
evaluateOrDefault(ctx.evaluator, GetTypeWrapperType{parent}, Type())
328-
->castTo<AnyGenericType>();
329-
assert(typeWrapperType);
347+
auto *typeWrapperType = typeWrapper->AttrType->castTo<AnyGenericType>();
330348

331349
// $storage: Wrapper<<ParentType>, <ParentType>.$Storage>
332350
auto propertyTy = BoundGenericType::get(

test/ModuleInterface/type_wrappers.swift

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ public struct Wrapper<W, S> {
3232

3333
// CHECK: @TypeWrappers.Wrapper public class Test<T> where T : Swift.StringProtocol {
3434
// CHECK: public init(a: Swift.Int, b: [T])
35-
// CHECK: public init(storageWrapper: TypeWrappers.Wrapper<TypeWrappers.Test<T>, TypeWrappers.Test<T>.$Storage>)
3635
// CHECK: }
3736

3837
@Wrapper

0 commit comments

Comments
 (0)