Skip to content

Commit a9841fc

Browse files
authored
Merge pull request #10308 from DougGregor/typealias-of-nested-in-protocol
2 parents 78106ef + 6a2b6c2 commit a9841fc

File tree

7 files changed

+89
-39
lines changed

7 files changed

+89
-39
lines changed

include/swift/AST/Types.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ namespace swift {
4545
class AssociatedTypeDecl;
4646
class ASTContext;
4747
class ClassDecl;
48+
class DependentMemberType;
4849
class GenericTypeParamDecl;
4950
class GenericTypeParamType;
5051
class GenericParamList;
@@ -534,6 +535,12 @@ class alignas(1 << TypeAlignInBits) TypeBase {
534535
return getRecursiveProperties().hasTypeParameter();
535536
}
536537

538+
/// Find any unresolved dependent member type within this type.
539+
///
540+
/// "Unresolved" dependent member types have no known associated type,
541+
/// and are only used transiently in the type checker.
542+
const DependentMemberType *findUnresolvedDependentMemberType();
543+
537544
/// Return the root generic parameter of this type parameter type.
538545
GenericTypeParamType *getRootGenericParam();
539546

lib/AST/ASTVerifier.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2575,18 +2575,8 @@ class Verifier : public ASTWalker {
25752575
// dependent member types.
25762576
// FIXME: This is a general property of the type system.
25772577
auto interfaceTy = AFD->getInterfaceType();
2578-
Type unresolvedDependentTy;
2579-
interfaceTy.findIf([&](Type type) -> bool {
2580-
if (auto dependent = type->getAs<DependentMemberType>()) {
2581-
if (dependent->getAssocType() == nullptr) {
2582-
unresolvedDependentTy = dependent;
2583-
return true;
2584-
}
2585-
}
2586-
return false;
2587-
});
2588-
2589-
if (unresolvedDependentTy) {
2578+
if (auto unresolvedDependentTy
2579+
= interfaceTy->findUnresolvedDependentMemberType()) {
25902580
Out << "Unresolved dependent member type ";
25912581
unresolvedDependentTy->print(Out);
25922582
abort();

lib/AST/GenericSignatureBuilder.cpp

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5266,14 +5266,8 @@ static void collectRequirements(GenericSignatureBuilder &builder,
52665266

52675267
// Drop requirements involving concrete types containing
52685268
// unresolved associated types.
5269-
if (repTy.findIf([](Type t) -> bool {
5270-
if (auto *depTy = dyn_cast<DependentMemberType>(t.getPointer()))
5271-
if (depTy->getAssocType() == nullptr)
5272-
return true;
5273-
return false;
5274-
})) {
5269+
if (repTy->findUnresolvedDependentMemberType())
52755270
return;
5276-
}
52775271
} else if (auto layoutConstraint = type.dyn_cast<LayoutConstraint>()) {
52785272
requirements.push_back(Requirement(kind, depTy, layoutConstraint));
52795273
return;

lib/AST/Type.cpp

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3156,6 +3156,24 @@ Type Type::substDependentTypesWithErrorTypes() const {
31563156
SubstFlags::UseErrorType));
31573157
}
31583158

3159+
const DependentMemberType *TypeBase::findUnresolvedDependentMemberType() {
3160+
if (!hasTypeParameter()) return nullptr;
3161+
3162+
const DependentMemberType *unresolvedDepMemTy = nullptr;
3163+
Type(this).findIf([&](Type type) -> bool {
3164+
if (auto depMemTy = type->getAs<DependentMemberType>()) {
3165+
if (depMemTy->getAssocType() == nullptr) {
3166+
unresolvedDepMemTy = depMemTy;
3167+
return true;
3168+
}
3169+
}
3170+
return false;
3171+
});
3172+
3173+
return unresolvedDepMemTy;
3174+
}
3175+
3176+
31593177
Type TypeBase::getSuperclassForDecl(const ClassDecl *baseClass) {
31603178
Type t(this);
31613179
while (t) {
@@ -3623,6 +3641,9 @@ case TypeKind::Id:
36233641
case TypeKind::NameAlias: {
36243642
auto alias = cast<NameAliasType>(base);
36253643
auto underlyingTy = Type(alias->getSinglyDesugaredType());
3644+
if (!underlyingTy)
3645+
return Type();
3646+
36263647
auto transformedTy = underlyingTy.transformRec(fn);
36273648
if (!transformedTy)
36283649
return Type();

lib/Sema/TypeCheckDecl.cpp

Lines changed: 43 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7054,6 +7054,27 @@ static Optional<ObjCReason> shouldMarkClassAsObjC(TypeChecker &TC,
70547054
return None;
70557055
}
70567056

7057+
/// Validate the underlying type of the given typealias.
7058+
static void validateTypealiasType(TypeChecker &tc, TypeAliasDecl *typeAlias) {
7059+
TypeResolutionOptions options = TR_TypeAliasUnderlyingType;
7060+
if (typeAlias->getFormalAccess() <= Accessibility::FilePrivate)
7061+
options |= TR_KnownNonCascadingDependency;
7062+
7063+
if (typeAlias->getDeclContext()->isModuleScopeContext() &&
7064+
typeAlias->getGenericParams() == nullptr) {
7065+
IterativeTypeChecker ITC(tc);
7066+
ITC.satisfy(requestResolveTypeDecl(typeAlias));
7067+
} else {
7068+
if (tc.validateType(typeAlias->getUnderlyingTypeLoc(),
7069+
typeAlias, options)) {
7070+
typeAlias->setInvalid();
7071+
typeAlias->getUnderlyingTypeLoc().setInvalidType(tc.Context);
7072+
}
7073+
7074+
typeAlias->setUnderlyingType(typeAlias->getUnderlyingTypeLoc().getType());
7075+
}
7076+
}
7077+
70577078
void TypeChecker::validateDecl(ValueDecl *D) {
70587079
// Generic parameters are validated as part of their context.
70597080
if (isa<GenericTypeParamDecl>(D))
@@ -7161,25 +7182,7 @@ void TypeChecker::validateDecl(ValueDecl *D) {
71617182
SWIFT_DEFER { typeAlias->setIsBeingValidated(false); };
71627183

71637184
validateGenericTypeSignature(typeAlias);
7164-
7165-
TypeResolutionOptions options = TR_TypeAliasUnderlyingType;
7166-
if (typeAlias->getFormalAccess() <= Accessibility::FilePrivate)
7167-
options |= TR_KnownNonCascadingDependency;
7168-
7169-
if (typeAlias->getDeclContext()->isModuleScopeContext() &&
7170-
typeAlias->getGenericParams() == nullptr) {
7171-
IterativeTypeChecker ITC(*this);
7172-
ITC.satisfy(requestResolveTypeDecl(typeAlias));
7173-
} else {
7174-
if (validateType(typeAlias->getUnderlyingTypeLoc(),
7175-
typeAlias, options)) {
7176-
typeAlias->setInvalid();
7177-
typeAlias->getUnderlyingTypeLoc().setInvalidType(Context);
7178-
}
7179-
7180-
typeAlias->setUnderlyingType(typeAlias->getUnderlyingTypeLoc().getType());
7181-
}
7182-
7185+
validateTypealiasType(*this, typeAlias);
71837186
break;
71847187
}
71857188

@@ -7246,8 +7249,28 @@ void TypeChecker::validateDecl(ValueDecl *D) {
72467249
// FIXME: Hopefully this can all go away with the ITC.
72477250
for (auto member : proto->getMembers()) {
72487251
if (auto *aliasDecl = dyn_cast<TypeAliasDecl>(member)) {
7249-
if (!aliasDecl->isGeneric())
7252+
if (!aliasDecl->isGeneric()) {
72507253
aliasDecl->setGenericEnvironment(proto->getGenericEnvironment());
7254+
7255+
// If the underlying alias declaration has a type parameter,
7256+
// we have unresolved dependent member types we will need to deal
7257+
// with. Wipe out the types and validate them again.
7258+
// FIXME: We never should have recorded such a type in the first
7259+
// place.
7260+
if (!aliasDecl->getUnderlyingTypeLoc().getType() ||
7261+
aliasDecl->getUnderlyingTypeLoc().getType()
7262+
->findUnresolvedDependentMemberType()) {
7263+
aliasDecl->getUnderlyingTypeLoc().setType(Type(),
7264+
/*validated=*/false);
7265+
validateAccessibility(aliasDecl);
7266+
7267+
// Check generic parameters, if needed.
7268+
aliasDecl->setIsBeingValidated();
7269+
SWIFT_DEFER { aliasDecl->setIsBeingValidated(false); };
7270+
7271+
validateTypealiasType(*this, aliasDecl);
7272+
}
7273+
}
72517274
}
72527275
}
72537276

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,7 @@ Type CompleteGenericTypeResolver::resolveDependentMemberType(
218218
if (auto proto =
219219
concrete->getDeclContext()
220220
->getAsProtocolOrProtocolExtensionContext()) {
221+
TC.validateDecl(proto);
221222
auto subMap = SubstitutionMap::getProtocolSubstitutions(
222223
proto, baseTy, ProtocolConformanceRef(proto));
223224
return concrete->getDeclaredInterfaceType().subst(subMap);
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
// RUN: %target-swift-frontend %s -emit-ir
2+
struct X<T: Q> {
3+
func f(_: T.Z) { }
4+
}
5+
6+
protocol P {
7+
associatedtype A
8+
associatedtype B
9+
}
10+
11+
protocol Q {
12+
associatedtype C: P
13+
typealias Z = (C.A, C.B)
14+
}

0 commit comments

Comments
 (0)