Skip to content

Commit daf65ce

Browse files
committed
AST: Explicitly encode that only protocol and extension members are visible in a 'where' clause
Today, ASTScope only creates NominalTypeWhereScopes for the 'where' clause of an extension or a protocol. All other generic declarations model the 'where' clause as part of the declaration's scope itself (but it's not part of the body scope). Lookups into the NominalTypeWhereScope would look inside the type, because this is how we want protocol and protocol extension scopes to work -- you should be able to refer to associated types without a 'Self' prefix. Let's add a conditional check for protocols and extensions to the implementation of NominalTypeWhereScope, so that we can use this scope for all other 'where' clauses and keep the old behavior. Note that today, even _concrete_ extensions have this behavior, which is perhaps slightly unexpected: class C<T> { typealias U = Int } extension C where T == U {} It would be nice to tighten up the rule here but there's already a test in the suite that depends on it.
1 parent a39c560 commit daf65ce

File tree

2 files changed

+22
-0
lines changed

2 files changed

+22
-0
lines changed

include/swift/AST/ASTScope.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,10 @@ class GenericTypeOrExtensionWherePortion final
715715
GenericTypeOrExtensionWherePortion()
716716
: GenericTypeOrExtensionWhereOrBodyPortion("Where") {}
717717

718+
bool lookupMembersOf(const GenericTypeOrExtensionScope *scope,
719+
ArrayRef<const ASTScopeImpl *>,
720+
ASTScopeImpl::DeclConsumer consumer) const override;
721+
718722
ASTScopeImpl *expandScope(GenericTypeOrExtensionScope *,
719723
ScopeCreator &) const override;
720724

@@ -815,6 +819,8 @@ class GenericTypeOrExtensionScope : public ASTScopeImpl {
815819
return nullptr;
816820
}
817821

822+
bool areMembersVisibleFromWhereClause() const;
823+
818824
virtual void createBodyScope(ASTScopeImpl *leaf, ScopeCreator &) {}
819825

820826
protected:

lib/AST/ASTScopeLookup.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -370,6 +370,22 @@ bool GenericTypeOrExtensionWhereOrBodyPortion::lookupMembersOf(
370370
});
371371
}
372372

373+
bool GenericTypeOrExtensionWherePortion::lookupMembersOf(
374+
const GenericTypeOrExtensionScope *scope,
375+
ArrayRef<const ASTScopeImpl *> history,
376+
ASTScopeImpl::DeclConsumer consumer) const {
377+
if (!scope->areMembersVisibleFromWhereClause())
378+
return false;
379+
380+
return GenericTypeOrExtensionWhereOrBodyPortion::lookupMembersOf(
381+
scope, history, consumer);
382+
}
383+
384+
bool GenericTypeOrExtensionScope::areMembersVisibleFromWhereClause() const {
385+
auto *decl = getDecl();
386+
return isa<ProtocolDecl>(decl) || isa<ExtensionDecl>(decl);
387+
}
388+
373389
#pragma mark looking in locals or members - locals
374390

375391
bool GenericParamScope::lookupLocalsOrMembers(ArrayRef<const ASTScopeImpl *>,

0 commit comments

Comments
 (0)