Skip to content

Commit 7b08b30

Browse files
authored
Merge pull request #62586 from xedin/rdar-103270262
[AST/Sema] TypeWrappers: Fix a couple of issues with attribute inference from protocols
2 parents abfdc1b + 5c11a4b commit 7b08b30

File tree

12 files changed

+419
-72
lines changed

12 files changed

+419
-72
lines changed

include/swift/AST/Decl.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
#include "swift/AST/StorageImpl.h"
3636
#include "swift/AST/TypeAlignments.h"
3737
#include "swift/AST/TypeWalker.h"
38+
#include "swift/AST/TypeWrappers.h"
3839
#include "swift/AST/Types.h"
3940
#include "swift/Basic/ArrayRefView.h"
4041
#include "swift/Basic/Compiler.h"
@@ -3903,7 +3904,7 @@ class NominalTypeDecl : public GenericTypeDecl, public IterableDeclContext {
39033904
bool hasTypeWrapper() const { return bool(getTypeWrapper()); }
39043905

39053906
/// Return a type wrapper (if any) associated with this type.
3906-
NominalTypeDecl *getTypeWrapper() const;
3907+
Optional<TypeWrapperInfo> getTypeWrapper() const;
39073908

39083909
/// If this declaration has a type wrapper return a property that
39093910
/// is used for all type wrapper related operations (mainly for

include/swift/AST/TypeCheckRequests.h

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ struct TypeWitnessAndDecl;
6464
class ValueDecl;
6565
enum class OpaqueReadOwnership: uint8_t;
6666
class StorageImplInfo;
67+
struct TypeWrapperInfo;
6768

6869
/// Display a nominal type or extension thereof.
6970
void simple_display(
@@ -3522,15 +3523,17 @@ class GetSourceFileAsyncNode
35223523

35233524
/// Return a type wrapper (if any) associated with the given declaration.
35243525
class GetTypeWrapper
3525-
: public SimpleRequest<GetTypeWrapper, NominalTypeDecl *(NominalTypeDecl *),
3526+
: public SimpleRequest<GetTypeWrapper,
3527+
Optional<TypeWrapperInfo>(NominalTypeDecl *),
35263528
RequestFlags::Cached> {
35273529
public:
35283530
using SimpleRequest::SimpleRequest;
35293531

35303532
private:
35313533
friend SimpleRequest;
35323534

3533-
NominalTypeDecl *evaluate(Evaluator &evaluator, NominalTypeDecl *) const;
3535+
Optional<TypeWrapperInfo> evaluate(Evaluator &evaluator,
3536+
NominalTypeDecl *) const;
35343537

35353538
public:
35363539
bool isCached() const { return true; }
@@ -3752,6 +3755,23 @@ class GetTypeWrapperInitializer
37523755
bool isCached() const { return true; }
37533756
};
37543757

3758+
/// Check whether this is a protocol that has a type wrapper attribute
3759+
/// or one of its dependencies does.
3760+
class UsesTypeWrapperFeature
3761+
: public SimpleRequest<UsesTypeWrapperFeature, bool(NominalTypeDecl *),
3762+
RequestFlags::Cached> {
3763+
public:
3764+
using SimpleRequest::SimpleRequest;
3765+
3766+
private:
3767+
friend SimpleRequest;
3768+
3769+
bool evaluate(Evaluator &evaluator, NominalTypeDecl *) const;
3770+
3771+
public:
3772+
bool isCached() const { return true; }
3773+
};
3774+
37553775
/// Find the definition of a given macro.
37563776
class MacroDefinitionRequest
37573777
: public SimpleRequest<MacroDefinitionRequest,

include/swift/AST/TypeCheckerTypeIDZone.def

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ SWIFT_REQUEST(TypeChecker, GetSourceFileAsyncNode,
402402
AwaitExpr *(const SourceFile *),
403403
Cached, NoLocationInfo)
404404
SWIFT_REQUEST(TypeChecker, GetTypeWrapper,
405-
NominalTypeDecl *(NominalTypeDecl *),
405+
Optional<TypeWrapperInfo>(NominalTypeDecl *),
406406
Cached, NoLocationInfo)
407407
SWIFT_REQUEST(TypeChecker, GetTypeWrapperType,
408408
Type(NominalTypeDecl *),
@@ -443,6 +443,9 @@ SWIFT_REQUEST(TypeChecker, ContinueTargetRequest,
443443
SWIFT_REQUEST(TypeChecker, GetTypeWrapperInitializer,
444444
ConstructorDecl *(NominalTypeDecl *),
445445
Cached, NoLocationInfo)
446+
SWIFT_REQUEST(TypeChecker, UsesTypeWrapperFeature,
447+
bool(NominalTypeDecl *),
448+
Cached, NoLocationInfo)
446449
SWIFT_REQUEST(TypeChecker, MacroDefinitionRequest,
447450
MacroDefinition(MacroDecl *),
448451
Cached, NoLocationInfo)

include/swift/AST/TypeWrappers.h

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//===--------- TypeWrappers.h - Type Wrapper ASTs ---------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file defines helper types for type wrappers.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_AST_TYPE_WRAPPERS_H
18+
#define SWIFT_AST_TYPE_WRAPPERS_H
19+
20+
namespace swift {
21+
22+
struct TypeWrapperInfo {
23+
CustomAttr *Attr;
24+
NominalTypeDecl *Wrapper;
25+
NominalTypeDecl *AttachedTo;
26+
bool IsInferred;
27+
28+
TypeWrapperInfo(CustomAttr *attr, NominalTypeDecl *wrapperDecl,
29+
NominalTypeDecl *attachedTo, bool isInferred)
30+
: Attr(attr), Wrapper(wrapperDecl), AttachedTo(attachedTo),
31+
IsInferred(isInferred) {}
32+
33+
TypeWrapperInfo asInferred() const {
34+
return {Attr, Wrapper, AttachedTo, true};
35+
}
36+
};
37+
38+
} // end namespace swift
39+
40+
#endif // SWIFT_AST_TYPE_WRAPPERS_H

lib/AST/ASTPrinter.cpp

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
#include "swift/AST/ProtocolConformance.h"
3838
#include "swift/AST/SILLayout.h"
3939
#include "swift/AST/Stmt.h"
40+
#include "swift/AST/TypeCheckRequests.h"
4041
#include "swift/AST/TypeVisitor.h"
4142
#include "swift/AST/TypeWalker.h"
4243
#include "swift/AST/Types.h"
@@ -1179,6 +1180,16 @@ void PrintAST::printAttributes(const Decl *D) {
11791180

11801181
D->getAttrs().print(Printer, Options, D);
11811182

1183+
// We need to check whether this is a type with an inferred
1184+
// type wrapper attribute and if so print it explicitly.
1185+
if (auto *NTD = dyn_cast<NominalTypeDecl>(D)) {
1186+
auto typeWrapperInfo = NTD->getTypeWrapper();
1187+
// The attribute has been inferred and we have to print it.
1188+
if (typeWrapperInfo && typeWrapperInfo->IsInferred) {
1189+
typeWrapperInfo->Attr->print(Printer, Options, D);
1190+
}
1191+
}
1192+
11821193
// Print the implicit 'final' attribute.
11831194
if (auto VD = dyn_cast<ValueDecl>(D)) {
11841195
auto VarD = dyn_cast<VarDecl>(D);
@@ -2936,7 +2947,19 @@ static bool usesFeatureSpecializeAttributeWithAvailability(Decl *decl) {
29362947
}
29372948

29382949
static bool usesFeatureTypeWrappers(Decl *decl) {
2939-
return decl->getAttrs().hasAttribute<TypeWrapperAttr>();
2950+
NullablePtr<NominalTypeDecl> typeDecl;
2951+
2952+
if (auto *extension = dyn_cast<ExtensionDecl>(decl)) {
2953+
typeDecl = extension->getExtendedNominal();
2954+
} else {
2955+
typeDecl = dyn_cast<NominalTypeDecl>(decl);
2956+
}
2957+
2958+
if (!typeDecl)
2959+
return false;
2960+
2961+
return evaluateOrDefault(decl->getASTContext().evaluator,
2962+
UsesTypeWrapperFeature{typeDecl.get()}, false);
29402963
}
29412964

29422965
static bool usesFeatureRuntimeDiscoverableAttrs(Decl *decl) {

lib/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,7 @@ add_swift_host_library(swiftAST STATIC
116116
TypeRefinementContext.cpp
117117
TypeRepr.cpp
118118
TypeWalker.cpp
119+
TypeWrapper.cpp
119120
UnqualifiedLookup.cpp
120121
USRGeneration.cpp
121122

lib/AST/Decl.cpp

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -6599,14 +6599,6 @@ bool VarDecl::isMemberwiseInitialized(bool preferDeclaredProperties) const {
65996599
return true;
66006600
}
66016601

6602-
bool VarDecl::isTypeWrapperLocalStorageForInitializer() const {
6603-
if (auto *ctor =
6604-
dyn_cast_or_null<ConstructorDecl>(getDeclContext()->getAsDecl())) {
6605-
return this == ctor->getLocalTypeWrapperStorageVar();
6606-
}
6607-
return false;
6608-
}
6609-
66106602
bool VarDecl::isLet() const {
66116603
// An awful hack that stabilizes the value of 'isLet' for ParamDecl instances.
66126604
//
@@ -8891,14 +8883,6 @@ bool ConstructorDecl::isObjCZeroParameterWithLongSelector() const {
88918883
return params->get(0)->getInterfaceType()->isVoid();
88928884
}
88938885

8894-
VarDecl *ConstructorDecl::getLocalTypeWrapperStorageVar() const {
8895-
auto &ctx = getASTContext();
8896-
auto *mutableSelf = const_cast<ConstructorDecl *>(this);
8897-
return evaluateOrDefault(
8898-
ctx.evaluator, SynthesizeLocalVariableForTypeWrapperStorage{mutableSelf},
8899-
nullptr);
8900-
}
8901-
89028886
DestructorDecl::DestructorDecl(SourceLoc DestructorLoc, DeclContext *Parent)
89038887
: AbstractFunctionDecl(DeclKind::Destructor, Parent,
89048888
DeclBaseName::createDestructor(), DestructorLoc,

lib/AST/TypeWrapper.cpp

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
//===--- TypeWrapper.cpp - Type Traversal ---------------------------------===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2014 - 2022 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file implements functionality related to type wrapper feature.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#include "swift/AST/ASTContext.h"
18+
#include "swift/AST/Decl.h"
19+
#include "swift/AST/TypeCheckRequests.h"
20+
#include "swift/AST/TypeResolutionStage.h"
21+
#include "swift/AST/TypeWrappers.h"
22+
23+
using namespace swift;
24+
25+
Optional<TypeWrapperInfo> NominalTypeDecl::getTypeWrapper() const {
26+
auto *mutableSelf = const_cast<NominalTypeDecl *>(this);
27+
return evaluateOrDefault(getASTContext().evaluator,
28+
GetTypeWrapper{mutableSelf},
29+
Optional<TypeWrapperInfo>());
30+
}
31+
32+
VarDecl *ConstructorDecl::getLocalTypeWrapperStorageVar() const {
33+
auto &ctx = getASTContext();
34+
auto *mutableSelf = const_cast<ConstructorDecl *>(this);
35+
return evaluateOrDefault(
36+
ctx.evaluator, SynthesizeLocalVariableForTypeWrapperStorage{mutableSelf},
37+
nullptr);
38+
}
39+
40+
bool VarDecl::isTypeWrapperLocalStorageForInitializer() const {
41+
if (auto *ctor =
42+
dyn_cast_or_null<ConstructorDecl>(getDeclContext()->getAsDecl())) {
43+
return this == ctor->getLocalTypeWrapperStorageVar();
44+
}
45+
return false;
46+
}
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/SILOptimizer/Mandatory/DefiniteInitialization.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,8 +1257,9 @@ void LifetimeChecker::injectTypeWrapperStorageInitalization() {
12571257
{
12581258
bool isClass = isa<ClassDecl>(parentType);
12591259

1260-
auto typeWrapper = parentType->getTypeWrapper();
1261-
auto *typeWrapperInit = typeWrapper->getTypeWrapperInitializer();
1260+
auto typeWrapperInfo = parentType->getTypeWrapper();
1261+
auto *typeWrapperInit =
1262+
typeWrapperInfo->Wrapper->getTypeWrapperInitializer();
12621263
SILValue typeWrapperInitRef = createInitRef(typeWrapperInit);
12631264

12641265
auto *self = TheMemory.findUninitializedSelfValue();

lib/Sema/CodeSynthesis.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,7 +364,10 @@ static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
364364
} else if (ICK == ImplicitConstructorKind::TypeWrapperStorage) {
365365
accessLevel = AccessLevel::Public;
366366

367-
auto *typeWrapper = decl->getTypeWrapper();
367+
auto typeWrapperInfo = decl->getTypeWrapper();
368+
assert(typeWrapperInfo);
369+
370+
auto *typeWrapper = typeWrapperInfo->Wrapper;
368371

369372
auto *arg = new (ctx) ParamDecl(SourceLoc(), Loc, ctx.Id_storageWrapper,
370373
Loc, ctx.Id_storageWrapper, decl);

0 commit comments

Comments
 (0)