@@ -204,6 +204,129 @@ bool IsActorRequest::evaluate(
204204 return actorAttr != nullptr ;
205205}
206206
207+ static bool isDeclNotAsAccessibleAsParent (ValueDecl *decl,
208+ NominalTypeDecl *parent) {
209+ return decl->getFormalAccess () <
210+ std::min (parent->getFormalAccess (), AccessLevel::Public);
211+ }
212+
213+ VarDecl *GlobalActorInstanceRequest::evaluate (
214+ Evaluator &evaluator, NominalTypeDecl *nominal) const {
215+ auto globalActorAttr = nominal->getAttrs ().getAttribute <GlobalActorAttr>();
216+ if (!globalActorAttr)
217+ return nullptr ;
218+
219+ // Ensure that the actor protocol has been loaded.
220+ ASTContext &ctx = nominal->getASTContext ();
221+ auto actorProto = ctx.getProtocol (KnownProtocolKind::Actor);
222+ if (!actorProto) {
223+ nominal->diagnose (diag::concurrency_lib_missing, " Actor" );
224+ return nullptr ;
225+ }
226+
227+ // Global actors have a static property "shared" that provides an actor
228+ // instance. The value must
229+ SmallVector<ValueDecl *, 4 > decls;
230+ nominal->lookupQualified (
231+ nominal, DeclNameRef (ctx.Id_shared ), NL_QualifiedDefault, decls);
232+ VarDecl *sharedVar = nullptr ;
233+ llvm::TinyPtrVector<VarDecl *> candidates;
234+ for (auto decl : decls) {
235+ auto var = dyn_cast<VarDecl>(decl);
236+ if (!var)
237+ continue ;
238+
239+ auto varDC = var->getDeclContext ();
240+ if (var->isStatic () &&
241+ !isDeclNotAsAccessibleAsParent (var, nominal) &&
242+ !(isa<ExtensionDecl>(varDC) &&
243+ cast<ExtensionDecl>(varDC)->isConstrainedExtension ()) &&
244+ TypeChecker::conformsToProtocol (
245+ varDC->mapTypeIntoContext (var->getValueInterfaceType ()),
246+ actorProto, nominal)) {
247+ sharedVar = var;
248+ break ;
249+ }
250+
251+ candidates.push_back (var);
252+ }
253+
254+ // If we found a suitable candidate, we're done.
255+ if (sharedVar)
256+ return sharedVar;
257+
258+ // Complain about the lack of a suitable 'shared' property.
259+ {
260+ auto primaryDiag = nominal->diagnose (
261+ diag::global_actor_missing_shared, nominal->getName ());
262+
263+ // If there were no candidates, provide a Fix-It with a prototype.
264+ if (candidates.empty () && nominal->getBraces ().Start .isValid ()) {
265+ // Figure out the indentation we need.
266+ SourceLoc sharedInsertionLoc = Lexer::getLocForEndOfToken (
267+ ctx.SourceMgr , nominal->getBraces ().Start );
268+
269+ StringRef extraIndent;
270+ StringRef currentIndent = Lexer::getIndentationForLine (
271+ ctx.SourceMgr , sharedInsertionLoc, &extraIndent);
272+ std::string stubIndent = (currentIndent + extraIndent).str ();
273+
274+ // From the string to add the declaration.
275+ std::string sharedDeclString = " \n " + stubIndent;
276+ if (nominal->getFormalAccess () >= AccessLevel::Public)
277+ sharedDeclString += " public " ;
278+
279+ sharedDeclString += " static let shared = <#actor instance#>" ;
280+
281+ primaryDiag.fixItInsert (sharedInsertionLoc, sharedDeclString);
282+ }
283+ }
284+
285+ // Remark about all of the candidates that failed (and why).
286+ for (auto candidate : candidates) {
287+ if (!candidate->isStatic ()) {
288+ candidate->diagnose (diag::global_actor_shared_not_static)
289+ .fixItInsert (candidate->getAttributeInsertionLoc (true ), " static " );
290+ continue ;
291+ }
292+
293+ if (isDeclNotAsAccessibleAsParent (candidate, nominal)) {
294+ AccessLevel needAccessLevel = std::min (
295+ nominal->getFormalAccess (), AccessLevel::Public);
296+ auto diag = candidate->diagnose (
297+ diag::global_actor_shared_inaccessible,
298+ getAccessLevelSpelling (candidate->getFormalAccess ()),
299+ getAccessLevelSpelling (needAccessLevel));
300+ if (auto attr = candidate->getAttrs ().getAttribute <AccessControlAttr>()) {
301+ if (needAccessLevel == AccessLevel::Internal) {
302+ diag.fixItRemove (attr->getRange ());
303+ } else {
304+ diag.fixItReplace (
305+ attr->getRange (), getAccessLevelSpelling (needAccessLevel));
306+ }
307+ } else {
308+ diag.fixItInsert (
309+ candidate->getAttributeInsertionLoc (true ),
310+ getAccessLevelSpelling (needAccessLevel));
311+ }
312+ continue ;
313+ }
314+
315+ if (auto ext = dyn_cast<ExtensionDecl>(candidate->getDeclContext ())) {
316+ if (ext->isConstrainedExtension ()) {
317+ candidate->diagnose (diag::global_actor_shared_constrained_extension);
318+ continue ;
319+ }
320+ }
321+
322+ Type varType = candidate->getDeclContext ()->mapTypeIntoContext (
323+ candidate->getValueInterfaceType ());
324+ candidate->diagnose (diag::global_actor_shared_non_actor_type, varType);
325+ }
326+
327+ return nullptr ;
328+ }
329+
207330namespace {
208331
209332// / The isolation restriction in effect for a given declaration that is
0 commit comments