Skip to content

Commit ab3a8c3

Browse files
authored
Merge pull request #64335 from hamishknight/less-generic
Better enforce GenericFunctionType TypeVariableType invariant
2 parents 89083ee + c1d6f1c commit ab3a8c3

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
@@ -2358,6 +2358,13 @@ ConstraintSystem::getTypeOfMemberReference(
23582358
return { openedType, openedType, memberTy, memberTy };
23592359
}
23602360

2361+
if (isa<AbstractFunctionDecl>(value) || isa<EnumElementDecl>(value)) {
2362+
if (value->getInterfaceType()->is<ErrorType>()) {
2363+
auto genericErrorTy = ErrorType::get(getASTContext());
2364+
return { genericErrorTy, genericErrorTy, genericErrorTy, genericErrorTy };
2365+
}
2366+
}
2367+
23612368
// Figure out the declaration context to use when opening this type.
23622369
DeclContext *innerDC = value->getInnermostDeclContext();
23632370
DeclContext *outerDC = value->getDeclContext();
@@ -2366,18 +2373,22 @@ ConstraintSystem::getTypeOfMemberReference(
23662373
Type openedType;
23672374
OpenedTypeMap localReplacements;
23682375
auto &replacements = replacementsPtr ? *replacementsPtr : localReplacements;
2369-
unsigned numRemovedArgumentLabels = getNumRemovedArgumentLabels(
2370-
value, /*isCurriedInstanceReference*/ !hasAppliedSelf, functionRefKind);
23712376

2372-
AnyFunctionType *funcType;
2377+
// If we have a generic signature, open the parameters. We delay opening
2378+
// requirements to allow contextual types to affect the situation.
2379+
auto genericSig = innerDC->getGenericSignatureOfContext();
2380+
if (genericSig)
2381+
openGenericParameters(outerDC, genericSig, replacements, locator);
23732382

23742383
if (isa<AbstractFunctionDecl>(value) || isa<EnumElementDecl>(value)) {
2375-
if (auto ErrorTy = value->getInterfaceType()->getAs<ErrorType>()) {
2376-
auto genericErrorTy = ErrorType::get(ErrorTy->getASTContext());
2377-
return { genericErrorTy, genericErrorTy, genericErrorTy, genericErrorTy };
2378-
}
23792384
// This is the easy case.
2380-
funcType = value->getInterfaceType()->castTo<AnyFunctionType>();
2385+
openedType = value->getInterfaceType()->castTo<AnyFunctionType>();
2386+
2387+
if (auto *genericFn = openedType->getAs<GenericFunctionType>()) {
2388+
openedType = genericFn->substGenericArgs([&](Type type) {
2389+
return openType(type, replacements);
2390+
});
2391+
}
23812392
} else {
23822393
// For a property, build a type (Self) -> PropType.
23832394
// For a subscript, build a type (Self) -> (Indices...) -> ElementType.
@@ -2418,29 +2429,21 @@ ConstraintSystem::getTypeOfMemberReference(
24182429
!selfTy->hasError())
24192430
selfFlags = selfFlags.withInOut(true);
24202431

2421-
// If the storage is generic, add a generic signature.
2432+
// If the storage is generic, open the self and ref types.
2433+
if (genericSig) {
2434+
selfTy = openType(selfTy, replacements);
2435+
refType = openType(refType, replacements);
2436+
}
24222437
FunctionType::Param selfParam(selfTy, Identifier(), selfFlags);
2438+
24232439
// FIXME: Verify ExtInfo state is correct, not working by accident.
2424-
if (auto sig = innerDC->getGenericSignatureOfContext()) {
2425-
GenericFunctionType::ExtInfo info;
2426-
funcType = GenericFunctionType::get(sig, {selfParam}, refType, info);
2427-
} else {
2428-
FunctionType::ExtInfo info;
2429-
funcType = FunctionType::get({selfParam}, refType, info);
2430-
}
2440+
FunctionType::ExtInfo info;
2441+
openedType = FunctionType::get({selfParam}, refType, info);
24312442
}
2443+
assert(!openedType->hasTypeParameter());
24322444

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

24452448
openedType = openedType->removeArgumentLabels(numRemovedArgumentLabels);
24462449

@@ -2491,9 +2494,9 @@ ConstraintSystem::getTypeOfMemberReference(
24912494
// failing we'll get a generic requirement constraint failure
24922495
// if mismatch is related to generic parameters which is much
24932496
// easier to diagnose.
2494-
if (auto *genericFn = funcType->getAs<GenericFunctionType>()) {
2497+
if (genericSig) {
24952498
openGenericRequirements(
2496-
outerDC, genericFn->getGenericSignature(),
2499+
outerDC, genericSig,
24972500
/*skipProtocolSelfConstraint=*/true, locator,
24982501
[&](Type type) { return openType(type, replacements); });
24992502
}

0 commit comments

Comments
 (0)