mirror of
https://github.com/apple/swift.git
synced 2025-12-14 20:36:38 +01:00
AST: Refactor directReferencesForTypeRepr() to track inverses
This commit is contained in:
@@ -603,7 +603,7 @@ struct InheritedNominalEntry : Located<NominalTypeDecl *> {
|
||||
void getDirectlyInheritedNominalTypeDecls(
|
||||
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
|
||||
unsigned i, llvm::SmallVectorImpl<InheritedNominalEntry> &result,
|
||||
bool &anyObject);
|
||||
InvertibleProtocolSet &inverses, bool &anyObject);
|
||||
|
||||
/// Retrieve the set of nominal type declarations that are directly
|
||||
/// "inherited" by the given declaration, looking through typealiases
|
||||
@@ -612,7 +612,7 @@ void getDirectlyInheritedNominalTypeDecls(
|
||||
/// If we come across the AnyObject type, set \c anyObject true.
|
||||
SmallVector<InheritedNominalEntry, 4> getDirectlyInheritedNominalTypeDecls(
|
||||
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
|
||||
bool &anyObject);
|
||||
InvertibleProtocolSet &inverses, bool &anyObject);
|
||||
|
||||
/// Retrieve the set of nominal type declarations that appear as the
|
||||
/// constraint type of any "Self" constraints in the where clause of the
|
||||
|
||||
@@ -58,7 +58,8 @@ void simple_display(
|
||||
|
||||
/// Describes a set of type declarations that are "direct" referenced by
|
||||
/// a particular type in the AST.
|
||||
using DirectlyReferencedTypeDecls = llvm::TinyPtrVector<TypeDecl *>;
|
||||
using DirectlyReferencedTypeDecls = std::pair<llvm::TinyPtrVector<TypeDecl *>,
|
||||
InvertibleProtocolSet>;
|
||||
|
||||
/// Request the set of declarations directly referenced by the an "inherited"
|
||||
/// type of a type or extension declaration.
|
||||
@@ -270,6 +271,7 @@ public:
|
||||
|
||||
struct SelfBounds {
|
||||
llvm::TinyPtrVector<NominalTypeDecl *> decls;
|
||||
InvertibleProtocolSet inverses;
|
||||
bool anyObject = false;
|
||||
};
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ DefaultAndMaxAccessLevelRequest::evaluate(Evaluator &evaluator,
|
||||
|
||||
// Try to scope the extension's access to the least public type mentioned
|
||||
// in its where clause.
|
||||
for (auto *typeDecl : typeDecls) {
|
||||
for (auto *typeDecl : typeDecls.first) {
|
||||
if (isa<TypeAliasDecl>(typeDecl) || isa<NominalTypeDecl>(typeDecl)) {
|
||||
auto scope = typeDecl->getFormalAccessScope(ED->getDeclContext());
|
||||
maxScope = maxScope->intersectWith(scope);
|
||||
|
||||
@@ -209,9 +209,10 @@ void ConformanceLookupTable::forEachInStage(ConformanceStage stage,
|
||||
}
|
||||
} else if (next->getParentSourceFile() ||
|
||||
next->getParentModule()->isBuiltinModule()) {
|
||||
InvertibleProtocolSet inverses;
|
||||
bool anyObject = false;
|
||||
for (const auto &found :
|
||||
getDirectlyInheritedNominalTypeDecls(next, anyObject)) {
|
||||
getDirectlyInheritedNominalTypeDecls(next, inverses, anyObject)) {
|
||||
if (auto proto = dyn_cast<ProtocolDecl>(found.Item))
|
||||
protocols.push_back(
|
||||
{proto, found.Loc, found.uncheckedLoc, found.preconcurrencyLoc});
|
||||
@@ -497,9 +498,10 @@ void ConformanceLookupTable::addInheritedProtocols(
|
||||
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
|
||||
ConformanceSource source) {
|
||||
// Find all of the protocols in the inheritance list.
|
||||
InvertibleProtocolSet inverses;
|
||||
bool anyObject = false;
|
||||
for (const auto &found :
|
||||
getDirectlyInheritedNominalTypeDecls(decl, anyObject)) {
|
||||
getDirectlyInheritedNominalTypeDecls(decl, inverses, anyObject)) {
|
||||
if (auto proto = dyn_cast<ProtocolDecl>(found.Item)) {
|
||||
addProtocol(proto, found.Loc,
|
||||
source.withUncheckedLoc(found.uncheckedLoc)
|
||||
|
||||
@@ -1155,13 +1155,16 @@ SelfBounds SelfBoundsFromWhereClauseRequest::evaluate(
|
||||
}
|
||||
|
||||
SmallVector<ModuleDecl *, 2> modulesFound;
|
||||
auto rhsNominals = resolveTypeDeclsToNominal(evaluator, ctx, rhsDecls,
|
||||
auto rhsNominals = resolveTypeDeclsToNominal(evaluator, ctx, rhsDecls.first,
|
||||
ResolveToNominalOptions(),
|
||||
modulesFound,
|
||||
result.anyObject);
|
||||
result.decls.insert(result.decls.end(),
|
||||
rhsNominals.begin(),
|
||||
rhsNominals.end());
|
||||
|
||||
// Collect inverse markings on 'Self'.
|
||||
result.inverses.insertAll(rhsDecls.second);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1180,7 +1183,6 @@ SelfBounds swift::getSelfBoundsFromWhereClause(
|
||||
SelfBounds SelfBoundsFromGenericSignatureRequest::evaluate(
|
||||
Evaluator &evaluator, const ExtensionDecl *extDecl) const {
|
||||
SelfBounds result;
|
||||
ASTContext &ctx = extDecl->getASTContext();
|
||||
auto selfType = extDecl->getSelfInterfaceType();
|
||||
for (const auto &req : extDecl->getGenericRequirements()) {
|
||||
auto kind = req.getKind();
|
||||
@@ -1188,17 +1190,10 @@ SelfBounds SelfBoundsFromGenericSignatureRequest::evaluate(
|
||||
kind != RequirementKind::Superclass)
|
||||
continue;
|
||||
// The left-hand side of the type constraint must be 'Self'.
|
||||
bool isSelfLHS = selfType->isEqual(req.getFirstType());
|
||||
if (!isSelfLHS)
|
||||
if (!selfType->isEqual(req.getFirstType()))
|
||||
continue;
|
||||
|
||||
auto rhsDecls = directReferencesForType(req.getSecondType());
|
||||
SmallVector<ModuleDecl *, 2> modulesFound;
|
||||
auto rhsNominals = resolveTypeDeclsToNominal(
|
||||
evaluator, ctx, rhsDecls, ResolveToNominalOptions(),
|
||||
modulesFound, result.anyObject);
|
||||
result.decls.insert(result.decls.end(), rhsNominals.begin(),
|
||||
rhsNominals.end());
|
||||
result.decls.push_back(req.getSecondType()->getAnyNominal());
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -1211,15 +1206,18 @@ swift::getSelfBoundsFromGenericSignature(const ExtensionDecl *extDecl) {
|
||||
SelfBoundsFromGenericSignatureRequest{extDecl}, {});
|
||||
}
|
||||
|
||||
TinyPtrVector<TypeDecl *>
|
||||
DirectlyReferencedTypeDecls
|
||||
TypeDeclsFromWhereClauseRequest::evaluate(Evaluator &evaluator,
|
||||
ExtensionDecl *ext) const {
|
||||
ASTContext &ctx = ext->getASTContext();
|
||||
|
||||
TinyPtrVector<TypeDecl *> result;
|
||||
DirectlyReferencedTypeDecls result;
|
||||
auto resolve = [&](TypeRepr *typeRepr) {
|
||||
auto decls = directReferencesForTypeRepr(evaluator, ctx, typeRepr, ext);
|
||||
result.insert(result.end(), decls.begin(), decls.end());
|
||||
result.first.insert(result.first.end(),
|
||||
decls.first.begin(),
|
||||
decls.first.end());
|
||||
result.second.insertAll(decls.second);
|
||||
};
|
||||
|
||||
if (auto *whereClause = ext->getTrailingWhereClause()) {
|
||||
@@ -2761,7 +2759,7 @@ resolveTypeDeclsToNominal(Evaluator &evaluator,
|
||||
UnderlyingTypeDeclsReferencedRequest{typealias}, {});
|
||||
|
||||
auto underlyingNominalReferences
|
||||
= resolveTypeDeclsToNominal(evaluator, ctx, underlyingTypeReferences,
|
||||
= resolveTypeDeclsToNominal(evaluator, ctx, underlyingTypeReferences.first,
|
||||
options, modulesFound, anyObject, typealiases);
|
||||
std::for_each(underlyingNominalReferences.begin(),
|
||||
underlyingNominalReferences.end(),
|
||||
@@ -2874,19 +2872,19 @@ directReferencesForUnqualifiedTypeLookup(DeclNameRef name,
|
||||
if (isa<NominalTypeDecl>(typeDecl))
|
||||
nominalTypeDeclCount++;
|
||||
|
||||
results.push_back(typeDecl);
|
||||
results.first.push_back(typeDecl);
|
||||
}
|
||||
|
||||
// If we saw multiple nominal type declarations with the same name,
|
||||
// the result of the lookup is definitely ambiguous.
|
||||
if (nominalTypeDeclCount > 1)
|
||||
results.clear();
|
||||
results.first.clear();
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/// Perform qualified name lookup for types.
|
||||
static DirectlyReferencedTypeDecls
|
||||
static llvm::TinyPtrVector<TypeDecl *>
|
||||
directReferencesForQualifiedTypeLookup(Evaluator &evaluator,
|
||||
ASTContext &ctx,
|
||||
ArrayRef<TypeDecl *> baseTypes,
|
||||
@@ -2894,7 +2892,7 @@ directReferencesForQualifiedTypeLookup(Evaluator &evaluator,
|
||||
DeclContext *dc,
|
||||
SourceLoc loc,
|
||||
bool allowUsableFromInline=false) {
|
||||
DirectlyReferencedTypeDecls result;
|
||||
llvm::TinyPtrVector<TypeDecl *> result;
|
||||
auto addResults = [&result](ArrayRef<ValueDecl *> found){
|
||||
for (auto decl : found){
|
||||
assert(isa<TypeDecl>(decl) &&
|
||||
@@ -2943,19 +2941,16 @@ static DirectlyReferencedTypeDecls
|
||||
directReferencesForDeclRefTypeRepr(Evaluator &evaluator, ASTContext &ctx,
|
||||
DeclRefTypeRepr *repr, DeclContext *dc,
|
||||
bool allowUsableFromInline) {
|
||||
// If we already set a declaration, use it.
|
||||
if (auto *typeDecl = repr->getBoundDecl()) {
|
||||
return {typeDecl};
|
||||
}
|
||||
|
||||
if (auto *memberTR = dyn_cast<MemberTypeRepr>(repr)) {
|
||||
DirectlyReferencedTypeDecls baseTypeDecls = directReferencesForTypeRepr(
|
||||
auto result = directReferencesForTypeRepr(
|
||||
evaluator, ctx, memberTR->getBase(), dc, allowUsableFromInline);
|
||||
|
||||
// For a qualified identifier, perform qualified name lookup.
|
||||
return directReferencesForQualifiedTypeLookup(
|
||||
evaluator, ctx, baseTypeDecls, repr->getNameRef(), dc, repr->getLoc(),
|
||||
result.first = directReferencesForQualifiedTypeLookup(
|
||||
evaluator, ctx, result.first, repr->getNameRef(), dc, repr->getLoc(),
|
||||
allowUsableFromInline);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// For an unqualified identifier, perform unqualified name lookup.
|
||||
@@ -2968,9 +2963,12 @@ static DirectlyReferencedTypeDecls
|
||||
directReferencesForTypeRepr(Evaluator &evaluator,
|
||||
ASTContext &ctx, TypeRepr *typeRepr,
|
||||
DeclContext *dc, bool allowUsableFromInline) {
|
||||
DirectlyReferencedTypeDecls result;
|
||||
|
||||
switch (typeRepr->getKind()) {
|
||||
case TypeReprKind::Array:
|
||||
return {1, ctx.getArrayDecl()};
|
||||
result.first.push_back(ctx.getArrayDecl());
|
||||
return result;
|
||||
|
||||
case TypeReprKind::Attributed: {
|
||||
auto attributed = cast<AttributedTypeRepr>(typeRepr);
|
||||
@@ -2980,15 +2978,17 @@ directReferencesForTypeRepr(Evaluator &evaluator,
|
||||
}
|
||||
|
||||
case TypeReprKind::Composition: {
|
||||
DirectlyReferencedTypeDecls result;
|
||||
auto composition = cast<CompositionTypeRepr>(typeRepr);
|
||||
for (auto component : composition->getTypes()) {
|
||||
auto componentResult =
|
||||
directReferencesForTypeRepr(evaluator, ctx, component, dc,
|
||||
allowUsableFromInline);
|
||||
result.insert(result.end(),
|
||||
componentResult.begin(),
|
||||
componentResult.end());
|
||||
result.first.insert(result.first.end(),
|
||||
componentResult.first.begin(),
|
||||
componentResult.first.end());
|
||||
|
||||
// Merge inverses.
|
||||
result.second.insertAll(componentResult.second);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -3001,18 +3001,19 @@ directReferencesForTypeRepr(Evaluator &evaluator,
|
||||
dc, allowUsableFromInline);
|
||||
|
||||
case TypeReprKind::Dictionary:
|
||||
return { 1, ctx.getDictionaryDecl()};
|
||||
result.first.push_back(ctx.getDictionaryDecl());
|
||||
return result;
|
||||
|
||||
case TypeReprKind::Tuple: {
|
||||
auto tupleRepr = cast<TupleTypeRepr>(typeRepr);
|
||||
if (tupleRepr->isParenType()) {
|
||||
return directReferencesForTypeRepr(evaluator, ctx,
|
||||
tupleRepr->getElementType(0), dc,
|
||||
allowUsableFromInline);
|
||||
result = directReferencesForTypeRepr(evaluator, ctx,
|
||||
tupleRepr->getElementType(0), dc,
|
||||
allowUsableFromInline);
|
||||
} else {
|
||||
return { 1, ctx.getBuiltinTupleDecl() };
|
||||
result.first.push_back(ctx.getBuiltinTupleDecl());
|
||||
}
|
||||
return { };
|
||||
return result;
|
||||
}
|
||||
|
||||
case TypeReprKind::Vararg: {
|
||||
@@ -3036,6 +3037,23 @@ directReferencesForTypeRepr(Evaluator &evaluator,
|
||||
allowUsableFromInline);
|
||||
}
|
||||
|
||||
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);
|
||||
if (innerResult.first.size() == 1) {
|
||||
auto *proto = dyn_cast<ProtocolDecl>(innerResult.first[0]);
|
||||
if (auto ip = proto->getInvertibleProtocolKind()) {
|
||||
result.second.insert(*ip);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
case TypeReprKind::Error:
|
||||
case TypeReprKind::Function:
|
||||
case TypeReprKind::Ownership:
|
||||
@@ -3049,11 +3067,10 @@ directReferencesForTypeRepr(Evaluator &evaluator,
|
||||
case TypeReprKind::OpaqueReturn:
|
||||
case TypeReprKind::NamedOpaqueReturn:
|
||||
case TypeReprKind::Existential:
|
||||
case TypeReprKind::Inverse:
|
||||
case TypeReprKind::ResultDependsOn:
|
||||
case TypeReprKind::LifetimeDependentReturn:
|
||||
case TypeReprKind::Transferring:
|
||||
return { };
|
||||
return result;
|
||||
|
||||
case TypeReprKind::Fixed:
|
||||
llvm_unreachable("Cannot get fixed TypeReprs in name lookup");
|
||||
@@ -3062,41 +3079,62 @@ directReferencesForTypeRepr(Evaluator &evaluator,
|
||||
|
||||
case TypeReprKind::Optional:
|
||||
case TypeReprKind::ImplicitlyUnwrappedOptional:
|
||||
return { 1, ctx.getOptionalDecl() };
|
||||
result.first.push_back(ctx.getOptionalDecl());
|
||||
return result;
|
||||
}
|
||||
llvm_unreachable("unhandled kind");
|
||||
}
|
||||
|
||||
static DirectlyReferencedTypeDecls directReferencesForType(Type type) {
|
||||
DirectlyReferencedTypeDecls result;
|
||||
|
||||
// If it's a typealias, return that.
|
||||
if (auto aliasType = dyn_cast<TypeAliasType>(type.getPointer()))
|
||||
return { 1, aliasType->getDecl() };
|
||||
|
||||
// If there is a generic declaration, return it.
|
||||
if (auto genericDecl = type->getAnyGeneric())
|
||||
return { 1, genericDecl };
|
||||
|
||||
if (dyn_cast<TupleType>(type.getPointer()))
|
||||
return { 1, type->getASTContext().getBuiltinTupleDecl() };
|
||||
|
||||
if (type->isExistentialType()) {
|
||||
DirectlyReferencedTypeDecls result;
|
||||
const auto &layout = type->getExistentialLayout();
|
||||
|
||||
// Superclass.
|
||||
if (auto superclassType = layout.explicitSuperclass) {
|
||||
if (auto superclassDecl = superclassType->getAnyGeneric()) {
|
||||
result.push_back(superclassDecl);
|
||||
}
|
||||
}
|
||||
|
||||
// Protocols.
|
||||
for (auto protoDecl : layout.getProtocols())
|
||||
result.push_back(protoDecl);
|
||||
if (auto aliasType = dyn_cast<TypeAliasType>(type.getPointer())) {
|
||||
result.first.push_back(aliasType->getDecl());
|
||||
return result;
|
||||
}
|
||||
|
||||
return { };
|
||||
// If there is a generic declaration, return it.
|
||||
if (auto genericDecl = type->getAnyGeneric()) {
|
||||
result.first.push_back(genericDecl);
|
||||
return result;
|
||||
}
|
||||
|
||||
if (type->is<TupleType>()) {
|
||||
result.first.push_back(type->getASTContext().getBuiltinTupleDecl());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (auto *protoType = type->getAs<ProtocolType>()) {
|
||||
result.first.push_back(protoType->getDecl());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (auto *compositionType = type->getAs<ProtocolCompositionType>()) {
|
||||
for (auto member : compositionType->getMembers()) {
|
||||
auto componentResult = directReferencesForType(member);
|
||||
result.first.insert(result.first.end(),
|
||||
componentResult.first.begin(),
|
||||
componentResult.first.end());
|
||||
|
||||
// Merge inverses from each member recursively.
|
||||
result.second.insertAll(componentResult.second);
|
||||
}
|
||||
|
||||
// Merge inverses attached to the composition itself.
|
||||
result.second.insertAll(compositionType->getInverses());
|
||||
return result;
|
||||
}
|
||||
|
||||
if (auto *paramType = type->getAs<ParameterizedProtocolType>()) {
|
||||
return directReferencesForType(paramType->getBaseType());
|
||||
}
|
||||
|
||||
if (auto *existentialType = type->getAs<ExistentialType>()) {
|
||||
return directReferencesForType(existentialType->getConstraintType());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
DirectlyReferencedTypeDecls InheritedDeclsReferencedRequest::evaluate(
|
||||
@@ -3192,7 +3230,8 @@ SuperclassDeclRequest::evaluate(Evaluator &evaluator,
|
||||
bool anyObject = false;
|
||||
auto inheritedNominalTypes
|
||||
= resolveTypeDeclsToNominal(evaluator, Ctx,
|
||||
inheritedTypes, ResolveToNominalOptions(),
|
||||
inheritedTypes.first,
|
||||
ResolveToNominalOptions(),
|
||||
modulesFound, anyObject);
|
||||
|
||||
// Look for a class declaration.
|
||||
@@ -3225,14 +3264,17 @@ ArrayRef<ProtocolDecl *>
|
||||
InheritedProtocolsRequest::evaluate(Evaluator &evaluator,
|
||||
ProtocolDecl *PD) const {
|
||||
llvm::SmallSetVector<ProtocolDecl *, 2> inherited;
|
||||
InvertibleProtocolSet inverses;
|
||||
bool anyObject = false;
|
||||
for (const auto &found :
|
||||
getDirectlyInheritedNominalTypeDecls(PD, anyObject)) {
|
||||
for (const auto &found : getDirectlyInheritedNominalTypeDecls(
|
||||
PD, inverses, anyObject)) {
|
||||
auto proto = dyn_cast<ProtocolDecl>(found.Item);
|
||||
if (proto && proto != PD)
|
||||
inherited.insert(proto);
|
||||
}
|
||||
|
||||
// FIXME: Apply inverses
|
||||
|
||||
return PD->getASTContext().AllocateCopy(inherited.getArrayRef());
|
||||
}
|
||||
|
||||
@@ -3268,7 +3310,7 @@ ExtendedNominalRequest::evaluate(Evaluator &evaluator,
|
||||
SmallVector<ModuleDecl *, 2> modulesFound;
|
||||
bool anyObject = false;
|
||||
auto nominalTypes
|
||||
= resolveTypeDeclsToNominal(evaluator, ctx, referenced,
|
||||
= resolveTypeDeclsToNominal(evaluator, ctx, referenced.first,
|
||||
ResolveToNominalFlags::AllowTupleType,
|
||||
modulesFound, anyObject);
|
||||
|
||||
@@ -3308,9 +3350,10 @@ static bool declsAreProtocols(ArrayRef<TypeDecl *> decls) {
|
||||
});
|
||||
}
|
||||
|
||||
bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc){
|
||||
bool TypeRepr::isProtocolOrProtocolComposition(DeclContext *dc) {
|
||||
auto &ctx = dc->getASTContext();
|
||||
return declsAreProtocols(directReferencesForTypeRepr(ctx.evaluator, ctx, this, dc));
|
||||
auto references = directReferencesForTypeRepr(ctx.evaluator, ctx, this, dc);
|
||||
return declsAreProtocols(references.first);
|
||||
}
|
||||
|
||||
bool TypeRepr::isInverseOf(InvertibleProtocolKind target, DeclContext *dc) {
|
||||
@@ -3319,7 +3362,7 @@ bool TypeRepr::isInverseOf(InvertibleProtocolKind target, DeclContext *dc) {
|
||||
|
||||
auto &ctx = dc->getASTContext();
|
||||
return llvm::any_of(
|
||||
directReferencesForTypeRepr(ctx.evaluator, ctx, constraint, dc),
|
||||
directReferencesForTypeRepr(ctx.evaluator, ctx, constraint, dc).first,
|
||||
[&](const TypeDecl *decl) {
|
||||
if (auto *P = dyn_cast<ProtocolDecl>(decl))
|
||||
return P->getInvertibleProtocolKind() == target;
|
||||
@@ -3366,11 +3409,11 @@ createTupleExtensionGenericParams(ASTContext &ctx,
|
||||
directReferencesForTypeRepr(ctx.evaluator, ctx,
|
||||
extendedTypeRepr,
|
||||
ext->getParent());
|
||||
|
||||
if (referenced.size() != 1 || !isa<TypeAliasDecl>(referenced[0]))
|
||||
assert(referenced.second.empty() && "Implement me");
|
||||
if (referenced.first.size() != 1 || !isa<TypeAliasDecl>(referenced.first[0]))
|
||||
return nullptr;
|
||||
|
||||
auto *typeAlias = cast<TypeAliasDecl>(referenced[0]);
|
||||
auto *typeAlias = cast<TypeAliasDecl>(referenced.first[0]);
|
||||
if (!typeAlias->isGeneric())
|
||||
return nullptr;
|
||||
|
||||
@@ -3646,7 +3689,7 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
|
||||
// Dig out the nominal type declarations.
|
||||
SmallVector<ModuleDecl *, 2> modulesFound;
|
||||
bool anyObject = false;
|
||||
auto nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls,
|
||||
auto nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls.first,
|
||||
ResolveToNominalOptions(),
|
||||
modulesFound, anyObject);
|
||||
if (nominals.size() == 1 && !isa<ProtocolDecl>(nominals.front()))
|
||||
@@ -3654,17 +3697,17 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
|
||||
|
||||
// If we found declarations that are associated types, look outside of
|
||||
// the current context to see if we can recover.
|
||||
if (declsAreAssociatedTypes(decls)) {
|
||||
if (declsAreAssociatedTypes(decls.first)) {
|
||||
if (auto typeRepr = attr->getTypeRepr()) {
|
||||
if (auto identTypeRepr = dyn_cast<SimpleIdentTypeRepr>(typeRepr)) {
|
||||
auto assocType = cast<AssociatedTypeDecl>(decls.front());
|
||||
auto assocType = cast<AssociatedTypeDecl>(decls.first.front());
|
||||
|
||||
modulesFound.clear();
|
||||
anyObject = false;
|
||||
decls = directReferencesForUnqualifiedTypeLookup(
|
||||
identTypeRepr->getNameRef(), identTypeRepr->getLoc(), dc,
|
||||
LookupOuterResults::Included);
|
||||
nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls,
|
||||
nominals = resolveTypeDeclsToNominal(evaluator, ctx, decls.first,
|
||||
ResolveToNominalOptions(),
|
||||
modulesFound, anyObject);
|
||||
if (nominals.size() == 1 && !isa<ProtocolDecl>(nominals.front())) {
|
||||
@@ -3699,10 +3742,12 @@ CustomAttrNominalRequest::evaluate(Evaluator &evaluator,
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/// Decompose the ith inheritance clause entry to a list of type declarations,
|
||||
/// inverses, and optional AnyObject member.
|
||||
void swift::getDirectlyInheritedNominalTypeDecls(
|
||||
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
|
||||
unsigned i, llvm::SmallVectorImpl<InheritedNominalEntry> &result,
|
||||
bool &anyObject) {
|
||||
InvertibleProtocolSet &inverses, bool &anyObject) {
|
||||
auto typeDecl = decl.dyn_cast<const TypeDecl *>();
|
||||
auto extDecl = decl.dyn_cast<const ExtensionDecl *>();
|
||||
|
||||
@@ -3713,10 +3758,13 @@ void swift::getDirectlyInheritedNominalTypeDecls(
|
||||
auto referenced = evaluateOrDefault(ctx.evaluator,
|
||||
InheritedDeclsReferencedRequest{decl, i}, {});
|
||||
|
||||
// Apply inverses written on this inheritance clause entry.
|
||||
inverses.insertAll(referenced.second);
|
||||
|
||||
// Resolve those type declarations to nominal type declarations.
|
||||
SmallVector<ModuleDecl *, 2> modulesFound;
|
||||
auto nominalTypes
|
||||
= resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced,
|
||||
= resolveTypeDeclsToNominal(ctx.evaluator, ctx, referenced.first,
|
||||
ResolveToNominalOptions(),
|
||||
modulesFound, anyObject);
|
||||
|
||||
@@ -3739,32 +3787,21 @@ void swift::getDirectlyInheritedNominalTypeDecls(
|
||||
}
|
||||
}
|
||||
|
||||
/// Decompose all inheritance clause entries and return the union of their
|
||||
/// type declarations, inverses, and optional AnyObject member.
|
||||
SmallVector<InheritedNominalEntry, 4>
|
||||
swift::getDirectlyInheritedNominalTypeDecls(
|
||||
llvm::PointerUnion<const TypeDecl *, const ExtensionDecl *> decl,
|
||||
bool &anyObject) {
|
||||
auto inheritedTypes = InheritedTypes(decl);
|
||||
|
||||
// Gather results from all of the inherited types.
|
||||
InvertibleProtocolSet &inverses, bool &anyObject) {
|
||||
SmallVector<InheritedNominalEntry, 4> result;
|
||||
for (unsigned i : inheritedTypes.getIndices()) {
|
||||
getDirectlyInheritedNominalTypeDecls(decl, i, result, anyObject);
|
||||
}
|
||||
|
||||
// For a deserialized protocol, the syntactic representations are not going to
|
||||
// tell us anything. Ask the requirement signature instead.
|
||||
auto *typeDecl = decl.dyn_cast<const TypeDecl *>();
|
||||
auto *protoDecl = dyn_cast_or_null<ProtocolDecl>(typeDecl);
|
||||
if (protoDecl == nullptr)
|
||||
return result;
|
||||
|
||||
// FIXME: Refactor SelfBoundsFromWhereClauseRequest to dig out
|
||||
// the source location.
|
||||
SourceLoc loc = SourceLoc();
|
||||
|
||||
// For a deserialized protocol, the where clause isn't going to tell us
|
||||
// anything. Ask the requirement signature instead.
|
||||
if (protoDecl->wasDeserialized()) {
|
||||
if (protoDecl && protoDecl->wasDeserialized()) {
|
||||
auto protoSelfTy = protoDecl->getSelfInterfaceType();
|
||||
for (auto &req : protoDecl->getRequirementSignature().getRequirements()) {
|
||||
for (auto req : protoDecl->getRequirementSignature().getRequirements()) {
|
||||
// Dig out a conformance requirement...
|
||||
if (req.getKind() != RequirementKind::Conformance)
|
||||
continue;
|
||||
@@ -3773,11 +3810,21 @@ swift::getDirectlyInheritedNominalTypeDecls(
|
||||
if (!req.getFirstType()->isEqual(protoSelfTy))
|
||||
continue;
|
||||
|
||||
result.emplace_back(req.getProtocolDecl(), loc, SourceLoc(), SourceLoc());
|
||||
result.emplace_back(req.getProtocolDecl(),
|
||||
SourceLoc(), SourceLoc(), SourceLoc());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Gather results from all of the inherited types.
|
||||
auto inheritedTypes = InheritedTypes(decl);
|
||||
for (unsigned i : inheritedTypes.getIndices()) {
|
||||
getDirectlyInheritedNominalTypeDecls(decl, i, result, inverses, anyObject);
|
||||
}
|
||||
|
||||
if (!protoDecl)
|
||||
return result;
|
||||
|
||||
// Check for SynthesizedProtocolAttrs on the protocol. ClangImporter uses
|
||||
// these to add `Sendable` conformances to protocols without modifying the
|
||||
// inherited type list.
|
||||
@@ -3791,10 +3838,13 @@ swift::getDirectlyInheritedNominalTypeDecls(
|
||||
|
||||
// Else we have access to this information on the where clause.
|
||||
auto selfBounds = getSelfBoundsFromWhereClause(decl);
|
||||
inverses.insertAll(selfBounds.inverses);
|
||||
anyObject |= selfBounds.anyObject;
|
||||
|
||||
// FIXME: Refactor SelfBoundsFromWhereClauseRequest to dig out
|
||||
// the source location.
|
||||
for (auto inheritedNominal : selfBounds.decls)
|
||||
result.emplace_back(inheritedNominal, loc, SourceLoc(), SourceLoc());
|
||||
result.emplace_back(inheritedNominal, SourceLoc(), SourceLoc(), SourceLoc());
|
||||
|
||||
return result;
|
||||
}
|
||||
@@ -3916,7 +3966,7 @@ ProtocolDecl *ImplementsAttrProtocolRequest::evaluate(
|
||||
SmallVector<ModuleDecl *, 2> modulesFound;
|
||||
bool anyObject = false;
|
||||
auto nominalTypes
|
||||
= resolveTypeDeclsToNominal(evaluator, ctx, referenced,
|
||||
= resolveTypeDeclsToNominal(evaluator, ctx, referenced.first,
|
||||
ResolveToNominalOptions(),
|
||||
modulesFound, anyObject);
|
||||
|
||||
|
||||
@@ -5781,8 +5781,9 @@ namespace {
|
||||
template<typename D>
|
||||
bool inheritanceListContainsProtocol(D decl, const ProtocolDecl *proto) {
|
||||
bool anyObject = false;
|
||||
InvertibleProtocolSet inverses;
|
||||
for (const auto &found :
|
||||
getDirectlyInheritedNominalTypeDecls(decl, anyObject)) {
|
||||
getDirectlyInheritedNominalTypeDecls(decl, inverses, anyObject)) {
|
||||
if (auto protoDecl = dyn_cast<ProtocolDecl>(found.Item))
|
||||
if (protoDecl == proto || protoDecl->inheritsFrom(proto))
|
||||
return true;
|
||||
|
||||
@@ -236,8 +236,9 @@ HasCircularInheritedProtocolsRequest::evaluate(Evaluator &evaluator,
|
||||
if (canSkipCircularityCheck(decl))
|
||||
return false;
|
||||
|
||||
InvertibleProtocolSet inverses;
|
||||
bool anyObject = false;
|
||||
auto inherited = getDirectlyInheritedNominalTypeDecls(decl, anyObject);
|
||||
auto inherited = getDirectlyInheritedNominalTypeDecls(decl, inverses, anyObject);
|
||||
for (auto &found : inherited) {
|
||||
auto *protoDecl = dyn_cast<ProtocolDecl>(found.Item);
|
||||
if (!protoDecl)
|
||||
@@ -648,9 +649,10 @@ ProtocolRequiresClassRequest::evaluate(Evaluator &evaluator,
|
||||
return true;
|
||||
|
||||
// Determine the set of nominal types that this protocol inherits.
|
||||
InvertibleProtocolSet inverses;
|
||||
bool anyObject = false;
|
||||
auto allInheritedNominals =
|
||||
getDirectlyInheritedNominalTypeDecls(decl, anyObject);
|
||||
getDirectlyInheritedNominalTypeDecls(decl, inverses, anyObject);
|
||||
|
||||
// Quick check: do we inherit AnyObject?
|
||||
if (anyObject)
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// RUN: %target-swift-emit-silgen -sdk %S/Inputs -I %S/Inputs -enable-source-import %s | %FileCheck %s
|
||||
|
||||
// XFAIL: noncopyable_generics
|
||||
|
||||
// REQUIRES: objc_interop
|
||||
|
||||
import Foundation
|
||||
|
||||
@@ -107,19 +107,19 @@
|
||||
"genericSig": "<τ_0_0 : cake.P1, τ_0_0 : cake.P2>",
|
||||
"sugared_genericSig": "<Self : cake.P1, Self : cake.P2>",
|
||||
"conformances": [
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "P1",
|
||||
"printedName": "P1",
|
||||
"usr": "s:4cake2P1P",
|
||||
"mangledName": "$s4cake2P1P"
|
||||
},
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "P2",
|
||||
"printedName": "P2",
|
||||
"usr": "s:4cake2P2P",
|
||||
"mangledName": "$s4cake2P2P"
|
||||
},
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "P1",
|
||||
"printedName": "P1",
|
||||
"usr": "s:4cake2P1P",
|
||||
"mangledName": "$s4cake2P1P"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -105,19 +105,19 @@
|
||||
"moduleName": "cake",
|
||||
"genericSig": "<Self : cake.P1, Self : cake.P2>",
|
||||
"conformances": [
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "P1",
|
||||
"printedName": "P1",
|
||||
"usr": "s:4cake2P1P",
|
||||
"mangledName": "$s4cake2P1P"
|
||||
},
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "P2",
|
||||
"printedName": "P2",
|
||||
"usr": "s:4cake2P2P",
|
||||
"mangledName": "$s4cake2P2P"
|
||||
},
|
||||
{
|
||||
"kind": "Conformance",
|
||||
"name": "P1",
|
||||
"printedName": "P1",
|
||||
"usr": "s:4cake2P1P",
|
||||
"mangledName": "$s4cake2P1P"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
@@ -19,25 +19,17 @@ package protocol PackageProto {
|
||||
associatedtype U
|
||||
}
|
||||
|
||||
// FIXME: With the current design, the below should not diagnose.
|
||||
//
|
||||
// However, it does, because we look at the bound decl in the
|
||||
// TypeRepr first, and it happens to already be set.
|
||||
//
|
||||
// FIXME: Once we no longer do that, come up with another strategy
|
||||
// to make the above diagnose.
|
||||
|
||||
extension PublicProto2 where Self.T : OuterClass, Self.U == Self.T.InnerClass {
|
||||
extension PublicProto2 where Self.T : OuterClass, Self.U == OuterClass.InnerClass {
|
||||
public func cannotBePublic() {}
|
||||
// expected-error@-1 {{cannot declare a public instance method in an extension with internal requirements}}
|
||||
}
|
||||
|
||||
package extension PublicProto2 where Self.T : OuterClass, Self.U == Self.T.PkgInnerClass {
|
||||
package extension PublicProto2 where Self.T : OuterClass, Self.U == OuterClass.PkgInnerClass {
|
||||
public func cannotBePublic() {}
|
||||
// expected-error@-1 {{cannot declare a public instance method in an extension with package requirements}}
|
||||
}
|
||||
|
||||
extension PackageProto where Self.T : OuterClass, Self.U == Self.T.InnerClass {
|
||||
extension PackageProto where Self.T : OuterClass, Self.U == OuterClass.InnerClass {
|
||||
package func cannotBePublic() {}
|
||||
// expected-error@-1 {{cannot declare a package instance method in an extension with internal requirements}}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
// RUN: %target-typecheck-verify-swift
|
||||
|
||||
// XFAIL: noncopyable_generics
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Using protocol requirements from inside protocol extensions
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
Reference in New Issue
Block a user