Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
205 changes: 92 additions & 113 deletions lib/AST/NameLookup.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1082,14 +1082,36 @@ namespace {
};
}

enum class DirectlyReferencedTypeLookupFlags {
/// Include results that are `@inlinable` or `@usableFromInline`.
AllowUsableFromInline = 1 << 0,

/// Discard 'Self' requirements in protocol extension `where` clauses.
RHSOfSelfRequirement = 1 << 1,

/// Include results that are members of protocols to which the contextual
/// type conforms.
AllowProtocolMembers = 1 << 2,
};

using DirectlyReferencedTypeLookupOptions =
OptionSet<DirectlyReferencedTypeLookupFlags>;

DirectlyReferencedTypeLookupOptions defaultDirectlyReferencedTypeLookupOptions =
DirectlyReferencedTypeLookupFlags::AllowProtocolMembers;

inline DirectlyReferencedTypeLookupOptions
operator|(DirectlyReferencedTypeLookupFlags flag1,
DirectlyReferencedTypeLookupFlags flag2) {
return DirectlyReferencedTypeLookupOptions(flag1) | flag2;
}

/// Retrieve the set of type declarations that are directly referenced from
/// the given parsed type representation.
static DirectlyReferencedTypeDecls
directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx,
TypeRepr *typeRepr, DeclContext *dc,
bool allowUsableFromInline,
bool rhsOfSelfRequirement,
bool allowProtocolMembers);
DirectlyReferencedTypeLookupOptions options);

/// Retrieve the set of type declarations that are directly referenced from
/// the given type.
Expand Down Expand Up @@ -1147,11 +1169,12 @@ SelfBounds SelfBoundsFromWhereClauseRequest::evaluate(
// Resolve the right-hand side.
DirectlyReferencedTypeDecls rhsDecls;
if (auto typeRepr = req.getConstraintRepr()) {
auto typeLookupOptions =
defaultDirectlyReferencedTypeLookupOptions |
DirectlyReferencedTypeLookupFlags::RHSOfSelfRequirement;
rhsDecls = directReferencesForTypeRepr(evaluator, ctx, typeRepr,
const_cast<DeclContext *>(dc),
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/true,
/*allowProtocolMembers=*/true);
typeLookupOptions);
}

SmallVector<ModuleDecl *, 2> modulesFound;
Expand Down Expand Up @@ -1213,10 +1236,9 @@ TypeDeclsFromWhereClauseRequest::evaluate(Evaluator &evaluator,

DirectlyReferencedTypeDecls result;
auto resolve = [&](TypeRepr *typeRepr) {
auto decls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext,
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
auto decls =
directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext,
defaultDirectlyReferencedTypeLookupOptions);
result.first.insert(result.first.end(),
decls.first.begin(),
decls.first.end());
Expand Down Expand Up @@ -2880,20 +2902,19 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
}

/// Perform unqualified name lookup for types at the given location.
static DirectlyReferencedTypeDecls
directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
SourceLoc loc, DeclContext *dc,
LookupOuterResults lookupOuter,
bool allowUsableFromInline,
bool rhsOfSelfRequirement,
bool allowProtocolMembers) {
static DirectlyReferencedTypeDecls directReferencesForUnqualifiedTypeLookup(
DeclNameRef name, SourceLoc loc, DeclContext *dc,
LookupOuterResults lookupOuter,
DirectlyReferencedTypeLookupOptions typeLookupOptions) {
UnqualifiedLookupOptions options = UnqualifiedLookupFlags::TypeLookup;
if (allowProtocolMembers)
options |= UnqualifiedLookupFlags::AllowProtocolMembers;
if (typeLookupOptions.contains(
DirectlyReferencedTypeLookupFlags::AllowProtocolMembers))
options |= UnqualifiedLookupFlags::AllowProtocolMembers;
if (lookupOuter == LookupOuterResults::Included)
options |= UnqualifiedLookupFlags::IncludeOuterResults;

if (allowUsableFromInline)
if (typeLookupOptions.contains(
DirectlyReferencedTypeLookupFlags::AllowUsableFromInline))
options |= UnqualifiedLookupFlags::IncludeUsableFromInline;

// Manually exclude macro expansions here since the source location
Expand All @@ -2911,7 +2932,8 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
// To avoid cycles when resolving the right-hand side, we perform the
// lookup in the parent context (for a protocol), or a special mode where
// we disregard 'Self' requirements (for a protocol extension).
if (rhsOfSelfRequirement) {
if (typeLookupOptions.contains(
DirectlyReferencedTypeLookupFlags::RHSOfSelfRequirement)) {
if (dc->getExtendedProtocolDecl())
options |= UnqualifiedLookupFlags::DisregardSelfBounds;
else {
Expand Down Expand Up @@ -2999,37 +3021,32 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator,
}

/// Determine the types directly referenced by the given identifier type.
static DirectlyReferencedTypeDecls
directReferencesForDeclRefTypeRepr(Evaluator &evaluator, ASTContext &ctx,
DeclRefTypeRepr *repr, DeclContext *dc,
bool allowUsableFromInline,
bool rhsOfSelfRequirement,
bool allowProtocolMembers) {
static DirectlyReferencedTypeDecls directReferencesForDeclRefTypeRepr(
Evaluator &evaluator, ASTContext &ctx, DeclRefTypeRepr *repr,
DeclContext *dc, DirectlyReferencedTypeLookupOptions options) {
if (auto *qualIdentTR = dyn_cast<QualifiedIdentTypeRepr>(repr)) {
auto result = directReferencesForTypeRepr(
evaluator, ctx, qualIdentTR->getBase(), dc,
allowUsableFromInline, rhsOfSelfRequirement, allowProtocolMembers);
evaluator, ctx, qualIdentTR->getBase(), dc, options);

// For a qualified identifier, perform qualified name lookup.
result.first = directReferencesForQualifiedTypeLookup(
evaluator, ctx, result.first, repr->getNameRef(), dc, repr->getLoc(),
allowUsableFromInline);
options.contains(
DirectlyReferencedTypeLookupFlags::AllowUsableFromInline));

return result;
}

// For an unqualified identifier, perform unqualified name lookup.
return directReferencesForUnqualifiedTypeLookup(
repr->getNameRef(), repr->getLoc(), dc, LookupOuterResults::Excluded,
allowUsableFromInline, rhsOfSelfRequirement, allowProtocolMembers);
options);
}

static DirectlyReferencedTypeDecls
directReferencesForTypeRepr(Evaluator &evaluator,
ASTContext &ctx, TypeRepr *typeRepr,
DeclContext *dc, bool allowUsableFromInline,
bool rhsOfSelfRequirement,
bool allowProtocolMembers) {
directReferencesForTypeRepr(Evaluator &evaluator, ASTContext &ctx,
TypeRepr *typeRepr, DeclContext *dc,
DirectlyReferencedTypeLookupOptions options) {
DirectlyReferencedTypeDecls result;

switch (typeRepr->getKind()) {
Expand All @@ -3040,20 +3057,14 @@ directReferencesForTypeRepr(Evaluator &evaluator,
case TypeReprKind::Attributed: {
auto attributed = cast<AttributedTypeRepr>(typeRepr);
return directReferencesForTypeRepr(evaluator, ctx,
attributed->getTypeRepr(), dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
attributed->getTypeRepr(), dc, options);
}

case TypeReprKind::Composition: {
auto composition = cast<CompositionTypeRepr>(typeRepr);
for (auto component : composition->getTypes()) {
auto componentResult =
directReferencesForTypeRepr(evaluator, ctx, component, dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
directReferencesForTypeRepr(evaluator, ctx, component, dc, options);
result.first.insert(result.first.end(),
componentResult.first.begin(),
componentResult.first.end());
Expand All @@ -3066,11 +3077,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,

case TypeReprKind::QualifiedIdent:
case TypeReprKind::UnqualifiedIdent:
return directReferencesForDeclRefTypeRepr(evaluator, ctx,
cast<DeclRefTypeRepr>(typeRepr),
dc, allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
return directReferencesForDeclRefTypeRepr(
evaluator, ctx, cast<DeclRefTypeRepr>(typeRepr), dc, options);

case TypeReprKind::Dictionary:
result.first.push_back(ctx.getDictionaryDecl());
Expand All @@ -3079,11 +3087,8 @@ directReferencesForTypeRepr(Evaluator &evaluator,
case TypeReprKind::Tuple: {
auto tupleRepr = cast<TupleTypeRepr>(typeRepr);
if (tupleRepr->isParenType()) {
result = directReferencesForTypeRepr(evaluator, ctx,
tupleRepr->getElementType(0), dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
result = directReferencesForTypeRepr(
evaluator, ctx, tupleRepr->getElementType(0), dc, options);
} else {
result.first.push_back(ctx.getBuiltinTupleDecl());
}
Expand All @@ -3092,40 +3097,28 @@ directReferencesForTypeRepr(Evaluator &evaluator,

case TypeReprKind::Vararg: {
auto packExpansionRepr = cast<VarargTypeRepr>(typeRepr);
return directReferencesForTypeRepr(evaluator, ctx,
packExpansionRepr->getElementType(), dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
return directReferencesForTypeRepr(
evaluator, ctx, packExpansionRepr->getElementType(), dc, options);
}

case TypeReprKind::PackExpansion: {
auto packExpansionRepr = cast<PackExpansionTypeRepr>(typeRepr);
return directReferencesForTypeRepr(evaluator, ctx,
packExpansionRepr->getPatternType(), dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
return directReferencesForTypeRepr(
evaluator, ctx, packExpansionRepr->getPatternType(), dc, options);
}

case TypeReprKind::PackElement: {
auto packReferenceRepr = cast<PackElementTypeRepr>(typeRepr);
return directReferencesForTypeRepr(evaluator, ctx,
packReferenceRepr->getPackType(), dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
return directReferencesForTypeRepr(
evaluator, ctx, packReferenceRepr->getPackType(), dc, options);
}

case TypeReprKind::Inverse: {
// If ~P references a protocol P with a known inverse kind, record it in
// our set of inverses, otherwise just ignore it. We'll diagnose it later.
auto *inverseRepr = cast<InverseTypeRepr>(typeRepr);
auto innerResult = directReferencesForTypeRepr(evaluator, ctx,
inverseRepr->getConstraint(), dc,
allowUsableFromInline,
rhsOfSelfRequirement,
allowProtocolMembers);
auto innerResult = directReferencesForTypeRepr(
evaluator, ctx, inverseRepr->getConstraint(), dc, options);
if (innerResult.first.size() == 1) {
if (auto *proto = dyn_cast<ProtocolDecl>(innerResult.first[0])) {
if (auto ip = proto->getInvertibleProtocolKind()) {
Expand Down Expand Up @@ -3237,13 +3230,13 @@ DirectlyReferencedTypeDecls InheritedDeclsReferencedRequest::evaluate(
// If looking at a protocol's inheritance list,
// do not look at protocol members to avoid circularity.
// Protocols cannot inherit from any protocol members anyway.
bool allowProtocolMembers = (dc->getSelfProtocolDecl() == nullptr);
DirectlyReferencedTypeLookupOptions options;
if (dc->getSelfProtocolDecl() == nullptr) {
options |= DirectlyReferencedTypeLookupFlags::AllowProtocolMembers;
}

return directReferencesForTypeRepr(evaluator, dc->getASTContext(), typeRepr,
const_cast<DeclContext *>(dc),
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
allowProtocolMembers);
const_cast<DeclContext *>(dc), options);
}

// Fall back to semantic types.
Expand All @@ -3261,11 +3254,9 @@ DirectlyReferencedTypeDecls UnderlyingTypeDeclsReferencedRequest::evaluate(
TypeAliasDecl *typealias) const {
// Prefer syntactic information when we have it.
if (auto typeRepr = typealias->getUnderlyingTypeRepr()) {
return directReferencesForTypeRepr(evaluator, typealias->getASTContext(),
typeRepr, typealias,
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
return directReferencesForTypeRepr(
evaluator, typealias->getASTContext(), typeRepr, typealias,
defaultDirectlyReferencedTypeLookupOptions);
}

// Fall back to semantic types.
Expand Down Expand Up @@ -3421,11 +3412,12 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
}

ASTContext &ctx = ext->getASTContext();
DirectlyReferencedTypeDecls referenced =
directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext->getParent(),
ext->isInSpecializeExtensionContext(),
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
auto options = defaultDirectlyReferencedTypeLookupOptions;
if (ext->isInSpecializeExtensionContext()) {
options |= DirectlyReferencedTypeLookupFlags::AllowUsableFromInline;
}
DirectlyReferencedTypeDecls referenced = directReferencesForTypeRepr(
evaluator, ctx, typeRepr, ext->getParent(), options);

// Resolve those type declarations to nominal type declarations.
SmallVector<ModuleDecl *, 2> modulesFound;
Expand Down Expand Up @@ -3473,10 +3465,8 @@ static bool declsAreProtocols(ArrayRef<TypeDecl *> decls) {

bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc) {
auto &ctx = dc->getASTContext();
auto references = directReferencesForTypeRepr(ctx.evaluator, ctx, this, dc,
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
auto references = directReferencesForTypeRepr(
ctx.evaluator, ctx, this, dc, defaultDirectlyReferencedTypeLookupOptions);
return declsAreProtocols(references.first);
}

Expand Down Expand Up @@ -3506,13 +3496,9 @@ static GenericParamList *
createTupleExtensionGenericParams(ASTContext &ctx,
ExtensionDecl *ext,
TypeRepr *extendedTypeRepr) {
DirectlyReferencedTypeDecls referenced =
directReferencesForTypeRepr(ctx.evaluator, ctx,
extendedTypeRepr,
ext->getParent(),
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
DirectlyReferencedTypeDecls referenced = directReferencesForTypeRepr(
ctx.evaluator, ctx, extendedTypeRepr, ext->getParent(),
defaultDirectlyReferencedTypeLookupOptions);
assert(referenced.second.empty() && "Implement me");
if (referenced.first.size() != 1 || !isa<TypeAliasDecl>(referenced.first[0]))
return nullptr;
Expand Down Expand Up @@ -3784,11 +3770,9 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
auto &ctx = dc->getASTContext();
DirectlyReferencedTypeDecls decls;
if (auto *typeRepr = attr->getTypeRepr()) {
decls = directReferencesForTypeRepr(
evaluator, ctx, typeRepr, dc,
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
decls =
directReferencesForTypeRepr(evaluator, ctx, typeRepr, dc,
defaultDirectlyReferencedTypeLookupOptions);
} else if (Type type = attr->getType()) {
decls = directReferencesForType(type);
}
Expand Down Expand Up @@ -3818,9 +3802,7 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
anyObject = false;
decls = directReferencesForUnqualifiedTypeLookup(
name, loc, dc, LookupOuterResults::Included,
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers*/true);
defaultDirectlyReferencedTypeLookupOptions);
nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls.first,
ResolveToNominalOptions(),
modulesFound, anyObject);
Expand Down Expand Up @@ -4056,11 +4038,8 @@ ProtocolDecl *ImplementsAttrProtocolRequest::evaluate(
auto typeRepr = attr->getProtocolTypeRepr();

ASTContext &ctx = dc->getASTContext();
DirectlyReferencedTypeDecls referenced =
directReferencesForTypeRepr(evaluator, ctx, typeRepr, dc,
/*allowUsableFromInline=*/false,
/*rhsOfSelfRequirement=*/false,
/*allowProtocolMembers=*/true);
DirectlyReferencedTypeDecls referenced = directReferencesForTypeRepr(
evaluator, ctx, typeRepr, dc, defaultDirectlyReferencedTypeLookupOptions);

// Resolve those type declarations to nominal type declarations.
SmallVector<ModuleDecl *, 2> modulesFound;
Expand Down