@@ -333,8 +333,7 @@ UnqualifiedLookupFactory::getBaseDeclForResult(const DeclContext *baseDC) const
333333// / unwrapping condition (e.g. `guard let self else { return }`).
334334// / If this is true, then we know any implicit self reference in the
335335// / following scope is guaranteed to be non-optional.
336- static bool implicitSelfReferenceIsUnwrapped (const ValueDecl *selfDecl,
337- const AbstractClosureExpr *inClosure) {
336+ static bool implicitSelfReferenceIsUnwrapped (const ValueDecl *selfDecl) {
338337 ASTContext &Ctx = selfDecl->getASTContext ();
339338
340339 // Check if the implicit self decl refers to a var in a conditional stmt
@@ -352,71 +351,40 @@ static bool implicitSelfReferenceIsUnwrapped(const ValueDecl *selfDecl,
352351 return conditionalStmt->rebindsSelf (Ctx);
353352}
354353
355- // Finds the nearest parent closure, which would define the
356- // permitted usage of implicit self. In closures this is most
357- // often just `dc` itself, but in functions defined in the
358- // closure body this would be some parent context.
359- static ClosureExpr *closestParentClosure (DeclContext *dc) {
360- if (!dc) {
361- return nullptr ;
362- }
363-
364- if (auto closure = dyn_cast<ClosureExpr>(dc)) {
365- return closure;
366- }
367-
368- // Stop searching if we find a type decl, since types always
369- // redefine what 'self' means, even when nested inside a closure.
370- if (dc->getContextKind () == DeclContextKind::GenericTypeDecl) {
371- return nullptr ;
372- }
373-
374- return closestParentClosure (dc->getParent ());
375- }
376-
377354ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl (const DeclContext *baseDC) const {
378355 // Perform an unqualified lookup for the base decl of this result. This
379356 // handles cases where self was rebound (e.g. `guard let self = self`)
380- // earlier in the scope.
381- //
382- // Only do this in closures that capture self weakly, since implicit self
383- // isn't allowed to be rebound in other contexts. In other contexts, implicit
384- // self _always_ refers to the context's self `ParamDecl`, even if there
385- // is another local decl with the name `self` that would be found by
386- // `lookupSingleLocalDecl`.
387- auto closureExpr = closestParentClosure (DC);
357+ // earlier in this closure or some outer closure.
358+ auto closureExpr = DC->getInnermostClosureForSelfCapture ();
388359 if (!closureExpr) {
389360 return nullptr ;
390361 }
391362
392- bool capturesSelfWeakly = false ;
393- if (auto decl = closureExpr->getCapturedSelfDecl ()) {
394- if (auto a = decl->getAttrs ().getAttribute <ReferenceOwnershipAttr>()) {
395- capturesSelfWeakly = a->get () == ReferenceOwnership::Weak;
396- }
397- }
398-
399- if (!capturesSelfWeakly) {
400- return nullptr ;
401- }
402-
403363 auto selfDecl = ASTScope::lookupSingleLocalDecl (
404364 DC->getParentSourceFile (), DeclName (Ctx.Id_self ), Loc);
405365
406366 if (!selfDecl) {
407367 return nullptr ;
408368 }
409369
370+ bool capturesSelfWeakly = false ;
371+ if (auto decl = closureExpr->getCapturedSelfDecl ()) {
372+ if (auto a = decl->getAttrs ().getAttribute <ReferenceOwnershipAttr>()) {
373+ capturesSelfWeakly = a->get () == ReferenceOwnership::Weak;
374+ }
375+ }
376+
410377 // In Swift 5 mode, implicit self is allowed within non-escaping
411- // closures even before self is unwrapped. For example, this is allowed:
378+ // `weak self` closures even before self is unwrapped.
379+ // For example, this is allowed:
412380 //
413381 // doVoidStuffNonEscaping { [weak self] in
414382 // method() // implicitly `self.method()`
415383 // }
416384 //
417385 // To support this, we have to preserve the lookup behavior from
418386 // Swift 5.7 and earlier where implicit self defaults to the closure's
419- // `ParamDecl`. This causes the closure to capture self strongly, however,
387+ // `ParamDecl`. This causes the closure to capture self strongly,
420388 // which is not acceptable for escaping closures.
421389 //
422390 // Escaping closures, however, only need to permit implicit self once
@@ -430,8 +398,29 @@ ValueDecl *UnqualifiedLookupFactory::lookupBaseDecl(const DeclContext *baseDC) c
430398 // In these cases, using the Swift 6 lookup behavior doesn't affect
431399 // how the body is type-checked, so it can be used in Swift 5 mode
432400 // without breaking source compatibility for non-escaping closures.
433- if (!Ctx.LangOpts .isSwiftVersionAtLeast (6 ) &&
434- !implicitSelfReferenceIsUnwrapped (selfDecl, closureExpr)) {
401+ if (capturesSelfWeakly && !Ctx.LangOpts .isSwiftVersionAtLeast (6 ) &&
402+ !implicitSelfReferenceIsUnwrapped (selfDecl)) {
403+ return nullptr ;
404+ }
405+
406+ // Closures are only allowed to rebind self in specific circumstances:
407+ // 1. In a capture list with an explicit capture.
408+ // 2. In a `guard let self = self` / `if let self = self` condition
409+ // in a closure that captures self weakly.
410+ //
411+ // These rebindings can be done by any parent closure, and apply
412+ // to all nested closures. We only need to check these structural
413+ // requirements loosely here -- more extensive validation happens
414+ // later in MiscDiagnostics::diagnoseImplicitSelfUseInClosure.
415+ //
416+ // Other types of rebindings, like an arbitrary "let `self` = foo",
417+ // are never allowed to rebind self.
418+ auto selfVD = dyn_cast<VarDecl>(selfDecl);
419+ if (!selfVD) {
420+ return nullptr ;
421+ }
422+
423+ if (!(selfVD->isCaptureList () || selfVD->getParentPatternStmt ())) {
435424 return nullptr ;
436425 }
437426
0 commit comments