Skip to content

Commit c1d6f1c

Browse files
committed
Better enforce GenericFunctionType TypeVariableType invariant
Enforce that we don't have any type variables present in either the result or parameter types. To ensure the constraint system doesn't violate this invariant, refactor `getTypeOfMemberReference` slightly to avoid construction of a `GenericFunctionType` as a means of opening the generic parameters of the context for a VarDecl.
1 parent 60378e1 commit c1d6f1c

File tree

2 files changed

+39
-29
lines changed

2 files changed

+39
-29
lines changed

lib/AST/ASTContext.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4178,6 +4178,13 @@ GenericFunctionType *GenericFunctionType::get(GenericSignature sig,
41784178
Type result,
41794179
Optional<ExtInfo> info) {
41804180
assert(sig && "no generic signature for generic function type?!");
4181+
4182+
// We do not allow type variables in GenericFunctionTypes. Note that if this
4183+
// ever changes, we'll need to setup arena-specific allocation for
4184+
// GenericFunctionTypes.
4185+
assert(llvm::none_of(params, [](Param param) {
4186+
return param.getPlainType()->hasTypeVariable();
4187+
}));
41814188
assert(!result->hasTypeVariable());
41824189

41834190
llvm::FoldingSetNodeID id;

lib/Sema/ConstraintSystem.cpp

Lines changed: 32 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2364,6 +2364,13 @@ ConstraintSystem::getTypeOfMemberReference(
23642364
return { openedType, openedType, memberTy, memberTy };
23652365
}
23662366

2367+
if (isa<AbstractFunctionDecl>(value) || isa<EnumElementDecl>(value)) {
2368+
if (value->getInterfaceType()->is<ErrorType>()) {
2369+
auto genericErrorTy = ErrorType::get(getASTContext());
2370+
return { genericErrorTy, genericErrorTy, genericErrorTy, genericErrorTy };
2371+
}
2372+
}
2373+
23672374
// Figure out the declaration context to use when opening this type.
23682375
DeclContext *innerDC = value->getInnermostDeclContext();
23692376
DeclContext *outerDC = value->getDeclContext();
@@ -2372,18 +2379,22 @@ ConstraintSystem::getTypeOfMemberReference(
23722379
Type openedType;
23732380
OpenedTypeMap localReplacements;
23742381
auto &replacements = replacementsPtr ? *replacementsPtr : localReplacements;
2375-
unsigned numRemovedArgumentLabels = getNumRemovedArgumentLabels(
2376-
value, /*isCurriedInstanceReference*/ !hasAppliedSelf, functionRefKind);
23772382

2378-
AnyFunctionType *funcType;
2383+
// If we have a generic signature, open the parameters. We delay opening
2384+
// requirements to allow contextual types to affect the situation.
2385+
auto genericSig = innerDC->getGenericSignatureOfContext();
2386+
if (genericSig)
2387+
openGenericParameters(outerDC, genericSig, replacements, locator);
23792388

23802389
if (isa<AbstractFunctionDecl>(value) || isa<EnumElementDecl>(value)) {
2381-
if (auto ErrorTy = value->getInterfaceType()->getAs<ErrorType>()) {
2382-
auto genericErrorTy = ErrorType::get(ErrorTy->getASTContext());
2383-
return { genericErrorTy, genericErrorTy, genericErrorTy, genericErrorTy };
2384-
}
23852390
// This is the easy case.
2386-
funcType = value->getInterfaceType()->castTo<AnyFunctionType>();
2391+
openedType = value->getInterfaceType()->castTo<AnyFunctionType>();
2392+
2393+
if (auto *genericFn = openedType->getAs<GenericFunctionType>()) {
2394+
openedType = genericFn->substGenericArgs([&](Type type) {
2395+
return openType(type, replacements);
2396+
});
2397+
}
23872398
} else {
23882399
// For a property, build a type (Self) -> PropType.
23892400
// For a subscript, build a type (Self) -> (Indices...) -> ElementType.
@@ -2424,29 +2435,21 @@ ConstraintSystem::getTypeOfMemberReference(
24242435
!selfTy->hasError())
24252436
selfFlags = selfFlags.withInOut(true);
24262437

2427-
// If the storage is generic, add a generic signature.
2438+
// If the storage is generic, open the self and ref types.
2439+
if (genericSig) {
2440+
selfTy = openType(selfTy, replacements);
2441+
refType = openType(refType, replacements);
2442+
}
24282443
FunctionType::Param selfParam(selfTy, Identifier(), selfFlags);
2444+
24292445
// FIXME: Verify ExtInfo state is correct, not working by accident.
2430-
if (auto sig = innerDC->getGenericSignatureOfContext()) {
2431-
GenericFunctionType::ExtInfo info;
2432-
funcType = GenericFunctionType::get(sig, {selfParam}, refType, info);
2433-
} else {
2434-
FunctionType::ExtInfo info;
2435-
funcType = FunctionType::get({selfParam}, refType, info);
2436-
}
2446+
FunctionType::ExtInfo info;
2447+
openedType = FunctionType::get({selfParam}, refType, info);
24372448
}
2449+
assert(!openedType->hasTypeParameter());
24382450

2439-
// While opening member function type, let's delay opening requirements
2440-
// to allow contextual types to affect the situation.
2441-
if (auto *genericFn = funcType->getAs<GenericFunctionType>()) {
2442-
openGenericParameters(outerDC, genericFn->getGenericSignature(),
2443-
replacements, locator);
2444-
2445-
openedType = genericFn->substGenericArgs(
2446-
[&](Type type) { return openType(type, replacements); });
2447-
} else {
2448-
openedType = funcType;
2449-
}
2451+
unsigned numRemovedArgumentLabels = getNumRemovedArgumentLabels(
2452+
value, /*isCurriedInstanceReference*/ !hasAppliedSelf, functionRefKind);
24502453

24512454
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);
24522455

@@ -2497,9 +2500,9 @@ ConstraintSystem::getTypeOfMemberReference(
24972500
// failing we'll get a generic requirement constraint failure
24982501
// if mismatch is related to generic parameters which is much
24992502
// easier to diagnose.
2500-
if (auto *genericFn = funcType->getAs<GenericFunctionType>()) {
2503+
if (genericSig) {
25012504
openGenericRequirements(
2502-
outerDC, genericFn->getGenericSignature(),
2505+
outerDC, genericSig,
25032506
/*skipProtocolSelfConstraint=*/true, locator,
25042507
[&](Type type) { return openType(type, replacements); });
25052508
}

0 commit comments

Comments
 (0)