Skip to content

Commit b499a4d

Browse files
authored
Merge pull request #10309 from DougGregor/typealias-of-nested-in-protocol-4.0
[4.0] [Type checker] Re-validate typealiases in protocols after protocol validation
2 parents bf823ee + d31d669 commit b499a4d

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;
@@ -552,6 +553,12 @@ class alignas(1 << TypeAlignInBits) TypeBase {
552553
return getRecursiveProperties().hasTypeParameter();
553554
}
554555

556+
/// Find any unresolved dependent member type within this type.
557+
///
558+
/// "Unresolved" dependent member types have no known associated type,
559+
/// and are only used transiently in the type checker.
560+
const DependentMemberType *findUnresolvedDependentMemberType();
561+
555562
/// Return the root generic parameter of this type parameter type.
556563
GenericTypeParamType *getRootGenericParam();
557564

lib/AST/ASTVerifier.cpp

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2562,18 +2562,8 @@ class Verifier : public ASTWalker {
25622562
// dependent member types.
25632563
// FIXME: This is a general property of the type system.
25642564
auto interfaceTy = AFD->getInterfaceType();
2565-
Type unresolvedDependentTy;
2566-
interfaceTy.findIf([&](Type type) -> bool {
2567-
if (auto dependent = type->getAs<DependentMemberType>()) {
2568-
if (dependent->getAssocType() == nullptr) {
2569-
unresolvedDependentTy = dependent;
2570-
return true;
2571-
}
2572-
}
2573-
return false;
2574-
});
2575-
2576-
if (unresolvedDependentTy) {
2565+
if (auto unresolvedDependentTy
2566+
= interfaceTy->findUnresolvedDependentMemberType()) {
25772567
Out << "Unresolved dependent member type ";
25782568
unresolvedDependentTy->print(Out);
25792569
abort();

lib/AST/GenericSignatureBuilder.cpp

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

52595259
// Drop requirements involving concrete types containing
52605260
// unresolved associated types.
5261-
if (repTy.findIf([](Type t) -> bool {
5262-
if (auto *depTy = dyn_cast<DependentMemberType>(t.getPointer()))
5263-
if (depTy->getAssocType() == nullptr)
5264-
return true;
5265-
return false;
5266-
})) {
5261+
if (repTy->findUnresolvedDependentMemberType())
52675262
return;
5268-
}
52695263
} else if (auto layoutConstraint = type.dyn_cast<LayoutConstraint>()) {
52705264
requirements.push_back(Requirement(kind, depTy, layoutConstraint));
52715265
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
@@ -7050,6 +7050,27 @@ static Optional<ObjCReason> shouldMarkClassAsObjC(TypeChecker &TC,
70507050
return None;
70517051
}
70527052

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

71597180
validateGenericTypeSignature(typeAlias);
7160-
7161-
TypeResolutionOptions options = TR_TypeAliasUnderlyingType;
7162-
if (typeAlias->getFormalAccess() <= Accessibility::FilePrivate)
7163-
options |= TR_KnownNonCascadingDependency;
7164-
7165-
if (typeAlias->getDeclContext()->isModuleScopeContext() &&
7166-
typeAlias->getGenericParams() == nullptr) {
7167-
IterativeTypeChecker ITC(*this);
7168-
ITC.satisfy(requestResolveTypeDecl(typeAlias));
7169-
} else {
7170-
if (validateType(typeAlias->getUnderlyingTypeLoc(),
7171-
typeAlias, options)) {
7172-
typeAlias->setInvalid();
7173-
typeAlias->getUnderlyingTypeLoc().setInvalidType(Context);
7174-
}
7175-
7176-
typeAlias->setUnderlyingType(typeAlias->getUnderlyingTypeLoc().getType());
7177-
}
7178-
7181+
validateTypealiasType(*this, typeAlias);
71797182
break;
71807183
}
71817184

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

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)