14
14
//
15
15
// ===----------------------------------------------------------------------===//
16
16
17
+ #include " TypeCheckConcurrency.h"
17
18
#include " TypeChecker.h"
18
19
#include " swift/AST/ASTContext.h"
19
20
#include " swift/AST/ASTMangler.h"
21
+ #include " swift/AST/ActorIsolation.h"
20
22
#include " swift/AST/Attr.h"
21
23
#include " swift/AST/Decl.h"
22
24
#include " swift/AST/Initializer.h"
@@ -46,6 +48,184 @@ ValueDecl::getRuntimeDiscoverableAttributeGenerator(CustomAttr *attr) const {
46
48
return std::make_pair (body, init->getType ()->mapTypeOutOfContext ());
47
49
}
48
50
51
+ static TypeRepr *buildTypeRepr (DeclContext *typeContext) {
52
+ assert (typeContext->isTypeContext ());
53
+
54
+ SmallVector<ComponentIdentTypeRepr *, 2 > components;
55
+
56
+ auto &ctx = typeContext->getASTContext ();
57
+ DeclContext *DC = typeContext;
58
+ while (!DC->isModuleContext ()) {
59
+ auto *NTD = DC->getSelfNominalTypeDecl ();
60
+ // Only contiguous chains of nominals and extensions thereof.
61
+ if (!NTD)
62
+ break ;
63
+
64
+ auto *component = new (ctx) SimpleIdentTypeRepr (
65
+ /* Loc=*/ DeclNameLoc (), NTD->createNameRef ());
66
+
67
+ // Resolve the component right away, instead of
68
+ // involving name lookup. This plays well with
69
+ // the fact that initializer is anchored on a
70
+ // source file.
71
+ component->setValue (NTD, NTD->getDeclContext ());
72
+
73
+ components.push_back (component);
74
+ DC = NTD->getDeclContext ();
75
+ }
76
+
77
+ // Reverse the components to form a valid outer-to-inner name sequence.
78
+ std::reverse (components.begin (), components.end ());
79
+
80
+ if (components.size () == 1 )
81
+ return components.front ();
82
+
83
+ return CompoundIdentTypeRepr::create (ctx, components);
84
+ }
85
+
86
+ // / Synthesizes a closure thunk that forwards all of the arguments
87
+ // / to the underlying method. This is required to support mutating
88
+ // / methods and create uniform signatures where for instance methods
89
+ // / first parameter is always `self` (with or without `inout`).
90
+ static ClosureExpr *synthesizeMethodThunk (DeclContext *thunkDC,
91
+ NominalTypeDecl *nominal,
92
+ FuncDecl *method) {
93
+ auto &ctx = method->getASTContext ();
94
+
95
+ // If this is a method, let's form a thunk so that attribute initializer
96
+ // gets `([inout] T, Argument, ...) -> Result` signature.
97
+ auto *funcParams = method->getParameters ();
98
+
99
+ SmallVector<ParamDecl *, 4 > closureParams;
100
+
101
+ NullablePtr<ParamDecl> selfParam;
102
+ if (!method->isStatic ()) {
103
+ auto *self = ParamDecl::createImplicit (
104
+ ctx,
105
+ /* argumentName=*/ Identifier (),
106
+ /* parameterName=*/ ctx.Id_self ,
107
+ /* type=*/ nominal->getDeclaredInterfaceType (), thunkDC,
108
+ method->isMutating () ? ParamSpecifier::InOut : ParamSpecifier::Default);
109
+
110
+ // This is very important for the solver, without a type repr
111
+ // it would create a type variable and attempt infer the type
112
+ // from the body.
113
+ self->setTypeRepr (buildTypeRepr (nominal));
114
+
115
+ closureParams.push_back (self);
116
+ selfParam = self;
117
+ }
118
+
119
+ if (funcParams) {
120
+ unsigned anonIdx = 0 ;
121
+ for (auto *param : *funcParams) {
122
+ auto name = param->getParameterName ();
123
+ // Cannot leave parameter anonymous because it would be
124
+ // referenced in the body.
125
+ if (name.empty ())
126
+ name = ctx.getIdentifier ((Twine (" $anon" ) + Twine (anonIdx++)).str ());
127
+
128
+ auto *closureParam = ParamDecl::createImplicit (
129
+ ctx,
130
+ /* argumentName=*/ Identifier (),
131
+ /* parameterName=*/ name, param->getInterfaceType (), thunkDC,
132
+ param->getSpecifier ());
133
+ closureParam->setTypeRepr (param->getTypeRepr ());
134
+
135
+ closureParams.push_back (closureParam);
136
+ }
137
+ }
138
+
139
+ // return self.<func>(<arguments>)
140
+ SmallVector<ASTNode, 2 > body;
141
+ {
142
+ NullablePtr<Expr> baseExpr;
143
+ if (method->isStatic ()) {
144
+ baseExpr =
145
+ TypeExpr::createImplicit (nominal->getDeclaredInterfaceType (), ctx);
146
+ } else {
147
+ baseExpr = new (ctx) DeclRefExpr ({selfParam.get ()}, /* Loc=*/ DeclNameLoc (),
148
+ /* implicit=*/ true );
149
+ }
150
+
151
+ auto *memberRef = new (ctx) MemberRefExpr (
152
+ baseExpr.get (), /* dotLoc=*/ SourceLoc (), {method}, /* loc=*/ DeclNameLoc (),
153
+ /* Implicit=*/ true );
154
+
155
+ SmallVector<Argument, 4 > arguments;
156
+ if (funcParams) {
157
+ for (unsigned i = 0 , n = funcParams->size (); i != n; ++i) {
158
+ const auto *param = funcParams->get (i);
159
+
160
+ Expr *argExpr = new (ctx)
161
+ DeclRefExpr ({closureParams[method->isStatic () ? i : i + 1 ]},
162
+ /* Loc=*/ DeclNameLoc (),
163
+ /* implicit=*/ true );
164
+
165
+ if (param->isInOut ()) {
166
+ argExpr = new (ctx) InOutExpr (/* operLoc=*/ SourceLoc (), argExpr,
167
+ Type (), /* implicit=*/ true );
168
+ }
169
+
170
+ arguments.push_back (
171
+ {/* labelLoc=*/ SourceLoc (), param->getArgumentName (), argExpr});
172
+ }
173
+ }
174
+
175
+ Expr *call = CallExpr::createImplicit (
176
+ ctx, memberRef, ArgumentList::createImplicit (ctx, arguments));
177
+
178
+ bool isAsync = false ;
179
+ bool isThrows = method->hasThrows ();
180
+
181
+ switch (getActorIsolation (method)) {
182
+ case ActorIsolation::Unspecified:
183
+ case ActorIsolation::Independent: {
184
+ isAsync = method->hasAsync ();
185
+ break ;
186
+ }
187
+
188
+ case ActorIsolation::ActorInstance: {
189
+ isAsync = true ;
190
+ isThrows |= nominal->isDistributedActor ();
191
+ break ;
192
+ }
193
+
194
+ case ActorIsolation::GlobalActor:
195
+ isAsync = true ;
196
+ LLVM_FALLTHROUGH;
197
+ case ActorIsolation::GlobalActorUnsafe: {
198
+ break ;
199
+ }
200
+ }
201
+
202
+ if (isAsync)
203
+ call = AwaitExpr::createImplicit (ctx, /* awaitLoc=*/ SourceLoc (), call);
204
+
205
+ if (isThrows)
206
+ call = TryExpr::createImplicit (ctx, /* tryLoc=*/ SourceLoc (), call);
207
+
208
+ body.push_back (new (ctx) ReturnStmt (/* ReturnLoc=*/ SourceLoc (), call,
209
+ /* implicit=*/ true ));
210
+ }
211
+
212
+ DeclAttributes attrs;
213
+ auto *closure = new (ctx) ClosureExpr (
214
+ attrs, /* bracketRange=*/ SourceRange (),
215
+ /* capturedSelf=*/ nullptr , ParameterList::create (ctx, closureParams),
216
+ /* asyncLoc=*/ SourceLoc (),
217
+ /* throwsLoc=*/ SourceLoc (),
218
+ /* arrowLoc=*/ SourceLoc (),
219
+ /* inLoc=*/ SourceLoc (),
220
+ /* explicitResultType=*/ nullptr , thunkDC);
221
+
222
+ closure->setBody (BraceStmt::createImplicit (ctx, body),
223
+ /* isSingleExpr=*/ true );
224
+ closure->setImplicit ();
225
+
226
+ return closure;
227
+ }
228
+
49
229
Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate (
50
230
Evaluator &evaluator, CustomAttr *attr, ValueDecl *attachedTo) const {
51
231
auto &ctx = attachedTo->getASTContext ();
@@ -77,13 +257,7 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
77
257
DotSelfExpr (metatype, /* dot=*/ SourceLoc (), /* self=*/ SourceLoc ());
78
258
} else if (auto *func = dyn_cast<FuncDecl>(attachedTo)) {
79
259
if (auto *nominal = func->getDeclContext ()->getSelfNominalTypeDecl ()) {
80
- auto *baseExpr =
81
- TypeExpr::createImplicit (nominal->getDeclaredInterfaceType (), ctx);
82
-
83
- // Form an initializer call passing in the function reference
84
- initArgument = new (ctx) MemberRefExpr (baseExpr, /* dotLoc=*/ SourceLoc (),
85
- {func}, /* loc=*/ DeclNameLoc (),
86
- /* Implicit=*/ true );
260
+ initArgument = synthesizeMethodThunk (initContext, nominal, func);
87
261
} else {
88
262
initArgument = new (ctx)
89
263
DeclRefExpr ({func}, /* Loc=*/ DeclNameLoc (), /* implicit=*/ true );
@@ -102,44 +276,7 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
102
276
// Build a type repr for base of the key path, since attribute
103
277
// could be attached to an inner type, we need to go up decl
104
278
// contexts and add every parent type.
105
- {
106
- SmallVector<ComponentIdentTypeRepr *, 2 > baseNameComponents;
107
-
108
- auto *DC = var->getDeclContext ();
109
- while (!DC->isModuleContext ()) {
110
- auto *NTD = DC->getSelfNominalTypeDecl ();
111
- // Only contiguous chains of nominals and extensions thereof.
112
- if (!NTD)
113
- break ;
114
-
115
- auto *component = new (ctx) SimpleIdentTypeRepr (
116
- /* Loc=*/ DeclNameLoc (), NTD->createNameRef ());
117
-
118
- // Resolve the component right away, instead of
119
- // involving name lookup. This plays well with
120
- // the fact that initializer is anchored on a
121
- // source file.
122
- component->setValue (NTD, NTD->getDeclContext ());
123
-
124
- baseNameComponents.push_back (component);
125
- DC = NTD->getDeclContext ();
126
- }
127
-
128
- // Reverse the components to form a valid outer-to-inner name sequence.
129
- std::reverse (baseNameComponents.begin (), baseNameComponents.end ());
130
-
131
- // Set the 'root' of the key path to the newly build base name.
132
- // We cannot do this via `parsedRoot` because it has strict
133
- // rules about leading-dot.
134
- TypeRepr *rootName = nullptr ;
135
- if (baseNameComponents.size () == 1 ) {
136
- rootName = baseNameComponents.front ();
137
- } else {
138
- rootName = CompoundIdentTypeRepr::create (ctx, baseNameComponents);
139
- }
140
-
141
- keyPath->setRootType (rootName);
142
- }
279
+ keyPath->setRootType (buildTypeRepr (var->getDeclContext ()));
143
280
144
281
initArgument = keyPath;
145
282
}
@@ -177,6 +314,7 @@ Expr *SynthesizeRuntimeMetadataAttrGenerator::evaluate(
177
314
return nullptr ;
178
315
179
316
TypeChecker::contextualizeInitializer (initContext, result);
317
+ checkInitializerActorIsolation (initContext, result);
180
318
TypeChecker::checkInitializerEffects (initContext, result);
181
319
182
320
return result;
0 commit comments