Skip to content

Commit e53fa3f

Browse files
committed
Make unconstrained extensions use the generic signature of extended type.
An unconstrained extension will always have the same generic signature as the nominal type it extends. Rather can constructing a new generic signature builder to tell us that, just re-use the generic signature. Improves type-checking performance of the standard library by 15%.
1 parent 9fa2a8b commit e53fa3f

File tree

3 files changed

+94
-66
lines changed

3 files changed

+94
-66
lines changed

lib/Sema/TypeCheckDecl.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -827,7 +827,8 @@ TypeChecker::handleSILGenericParams(GenericParamList *genericParams,
827827
prepareGenericParamList(genericParams, DC);
828828

829829
parentEnv = checkGenericEnvironment(genericParams, DC, parentSig,
830-
/*allowConcreteGenericParams=*/true);
830+
/*allowConcreteGenericParams=*/true,
831+
/*ext=*/nullptr);
831832
parentSig = parentEnv->getGenericSignature();
832833

833834
// Compute the final set of archetypes.
@@ -8047,7 +8048,7 @@ checkExtensionGenericParams(TypeChecker &tc, ExtensionDecl *ext, Type type,
80478048
auto *env = tc.checkGenericEnvironment(genericParams,
80488049
ext->getDeclContext(), nullptr,
80498050
/*allowConcreteGenericParams=*/true,
8050-
inferExtendedTypeReqs);
8051+
ext, inferExtendedTypeReqs);
80518052

80528053
// Validate the generic parameters for the last time, to splat down
80538054
// actual archetypes.

lib/Sema/TypeCheckGeneric.cpp

Lines changed: 84 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,85 +1087,104 @@ static void visitOuterToInner(
10871087
visitor(genericParams);
10881088
}
10891089

1090+
/// Retrieve the generic parameter depth of the extended type.
1091+
static unsigned getExtendedTypeGenericDepth(ExtensionDecl *ext) {
1092+
auto nominal = ext->getAsNominalTypeOrNominalTypeExtensionContext();
1093+
if (!nominal) return static_cast<unsigned>(-1);
1094+
1095+
auto sig = nominal->getGenericSignatureOfContext();
1096+
if (!sig) return static_cast<unsigned>(-1);
1097+
1098+
return sig->getGenericParams().back()->getDepth();
1099+
}
1100+
10901101
GenericEnvironment *TypeChecker::checkGenericEnvironment(
10911102
GenericParamList *genericParams,
10921103
DeclContext *dc,
10931104
GenericSignature *parentSig,
10941105
bool allowConcreteGenericParams,
1106+
ExtensionDecl *ext,
10951107
llvm::function_ref<void(GenericSignatureBuilder &)>
10961108
inferRequirements) {
10971109
assert(genericParams && "Missing generic parameters?");
10981110
bool recursivelyVisitGenericParams =
10991111
genericParams->getOuterParameters() && !parentSig;
11001112

1101-
// Collect the generic parameters.
1102-
SmallVector<GenericTypeParamType *, 4> allGenericParams;
1103-
if (recursivelyVisitGenericParams) {
1104-
visitOuterToInner(genericParams,
1105-
[&](GenericParamList *gpList) {
1106-
addGenericParamTypes(gpList, allGenericParams);
1107-
});
1108-
} else {
1109-
if (parentSig) {
1110-
allGenericParams.append(parentSig->getGenericParams().begin(),
1111-
parentSig->getGenericParams().end());
1113+
GenericSignature *sig;
1114+
if (!ext || ext->getTrailingWhereClause() ||
1115+
getExtendedTypeGenericDepth(ext) != genericParams->getDepth()) {
1116+
// Collect the generic parameters.
1117+
SmallVector<GenericTypeParamType *, 4> allGenericParams;
1118+
if (recursivelyVisitGenericParams) {
1119+
visitOuterToInner(genericParams,
1120+
[&](GenericParamList *gpList) {
1121+
addGenericParamTypes(gpList, allGenericParams);
1122+
});
1123+
} else {
1124+
if (parentSig) {
1125+
allGenericParams.append(parentSig->getGenericParams().begin(),
1126+
parentSig->getGenericParams().end());
1127+
}
1128+
1129+
addGenericParamTypes(genericParams, allGenericParams);
11121130
}
11131131

1114-
addGenericParamTypes(genericParams, allGenericParams);
1115-
}
1132+
// Create the generic signature builder.
1133+
GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
11161134

1117-
// Create the generic signature builder.
1118-
ModuleDecl *module = dc->getParentModule();
1119-
GenericSignatureBuilder builder(Context, LookUpConformance(*this, dc));
1135+
// Type check the generic parameters, treating all generic type
1136+
// parameters as dependent, unresolved.
1137+
DependentGenericTypeResolver dependentResolver;
1138+
if (recursivelyVisitGenericParams) {
1139+
visitOuterToInner(genericParams,
1140+
[&](GenericParamList *gpList) {
1141+
checkGenericParamList(&builder, gpList, nullptr, &dependentResolver);
1142+
});
1143+
} else {
1144+
checkGenericParamList(&builder, genericParams, parentSig,
1145+
&dependentResolver);
1146+
}
11201147

1121-
// Type check the generic parameters, treating all generic type
1122-
// parameters as dependent, unresolved.
1123-
DependentGenericTypeResolver dependentResolver;
1124-
if (recursivelyVisitGenericParams) {
1125-
visitOuterToInner(genericParams,
1126-
[&](GenericParamList *gpList) {
1127-
checkGenericParamList(&builder, gpList, nullptr, &dependentResolver);
1128-
});
1129-
} else {
1130-
checkGenericParamList(&builder, genericParams, parentSig,
1131-
&dependentResolver);
1132-
}
1148+
/// Perform any necessary requirement inference.
1149+
inferRequirements(builder);
11331150

1134-
/// Perform any necessary requirement inference.
1135-
inferRequirements(builder);
1151+
// Finalize the generic requirements.
1152+
(void)builder.finalize(genericParams->getSourceRange().Start,
1153+
allGenericParams,
1154+
allowConcreteGenericParams);
11361155

1137-
// Finalize the generic requirements.
1138-
(void)builder.finalize(genericParams->getSourceRange().Start,
1139-
allGenericParams,
1140-
allowConcreteGenericParams);
1156+
// The generic signature builder now has all of the requirements, although
1157+
// there might still be errors that have not yet been diagnosed. Revert the
1158+
// signature and type-check it again, completely.
1159+
if (recursivelyVisitGenericParams) {
1160+
visitOuterToInner(genericParams,
1161+
[&](GenericParamList *gpList) {
1162+
revertGenericParamList(gpList);
1163+
});
1164+
} else {
1165+
revertGenericParamList(genericParams);
1166+
}
11411167

1142-
// The generic signature builder now has all of the requirements, although
1143-
// there might still be errors that have not yet been diagnosed. Revert the
1144-
// signature and type-check it again, completely.
1145-
if (recursivelyVisitGenericParams) {
1146-
visitOuterToInner(genericParams,
1147-
[&](GenericParamList *gpList) {
1148-
revertGenericParamList(gpList);
1149-
});
1150-
} else {
1151-
revertGenericParamList(genericParams);
1152-
}
1168+
// Record the generic type parameter types and the requirements.
1169+
sig = builder.getGenericSignature();
11531170

1154-
// Record the generic type parameter types and the requirements.
1155-
auto sig = builder.getGenericSignature();
1156-
1157-
// Debugging of the generic signature builder and generic signature
1158-
// generation.
1159-
if (Context.LangOpts.DebugGenericSignatures) {
1160-
dc->printContext(llvm::errs());
1161-
llvm::errs() << "\n";
1162-
builder.dump(llvm::errs());
1163-
llvm::errs() << "Generic signature: ";
1164-
sig->print(llvm::errs());
1165-
llvm::errs() << "\n";
1166-
llvm::errs() << "Canonical generic signature: ";
1167-
sig->getCanonicalSignature()->print(llvm::errs());
1168-
llvm::errs() << "\n";
1171+
// Debugging of the generic signature builder and generic signature
1172+
// generation.
1173+
if (Context.LangOpts.DebugGenericSignatures) {
1174+
dc->printContext(llvm::errs());
1175+
llvm::errs() << "\n";
1176+
builder.dump(llvm::errs());
1177+
llvm::errs() << "Generic signature: ";
1178+
sig->print(llvm::errs());
1179+
llvm::errs() << "\n";
1180+
llvm::errs() << "Canonical generic signature: ";
1181+
sig->getCanonicalSignature()->print(llvm::errs());
1182+
llvm::errs() << "\n";
1183+
}
1184+
} else {
1185+
// Re-use the signature of the type being extended.
1186+
sig = ext->getAsNominalTypeOrNominalTypeExtensionContext()
1187+
->getGenericSignatureOfContext();
11691188
}
11701189

11711190
CompleteGenericTypeResolver completeResolver(*this, sig,
@@ -1181,6 +1200,7 @@ GenericEnvironment *TypeChecker::checkGenericEnvironment(
11811200
}
11821201

11831202
// Form the generic environment.
1203+
ModuleDecl *module = dc->getParentModule();
11841204
return sig->createGenericEnvironment(*module);
11851205
}
11861206

@@ -1205,8 +1225,10 @@ void TypeChecker::validateGenericTypeSignature(GenericTypeDecl *typeDecl) {
12051225
proto->computeRequirementSignature();
12061226
}
12071227

1208-
auto *env = checkGenericEnvironment(gp, dc, dc->getGenericSignatureOfContext(),
1209-
/*allowConcreteGenericParams=*/false);
1228+
auto *env = checkGenericEnvironment(gp, dc,
1229+
dc->getGenericSignatureOfContext(),
1230+
/*allowConcreteGenericParams=*/false,
1231+
/*ext=*/nullptr);
12101232
typeDecl->setGenericEnvironment(env);
12111233
}
12121234

lib/Sema/TypeChecker.h

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1367,6 +1367,9 @@ class TypeChecker final : public LazyResolver {
13671367
/// context, if not available as part of the \c dc argument (used
13681368
/// for SIL parsing).
13691369
///
1370+
/// \param ext The extension for which we're checking the generic
1371+
/// environment, or null if we're not checking an extension.
1372+
///
13701373
/// \param inferRequirements When non-empty, callback that will be invoked
13711374
/// to perform any additional requirement inference that contributes to the
13721375
/// generic environment..
@@ -1377,6 +1380,7 @@ class TypeChecker final : public LazyResolver {
13771380
DeclContext *dc,
13781381
GenericSignature *outerSignature,
13791382
bool allowConcreteGenericParams,
1383+
ExtensionDecl *ext,
13801384
llvm::function_ref<void(GenericSignatureBuilder &)>
13811385
inferRequirements);
13821386

@@ -1394,9 +1398,10 @@ class TypeChecker final : public LazyResolver {
13941398
GenericParamList *genericParams,
13951399
DeclContext *dc,
13961400
GenericSignature *outerSignature,
1397-
bool allowConcreteGenericParams) {
1401+
bool allowConcreteGenericParams,
1402+
ExtensionDecl *ext) {
13981403
return checkGenericEnvironment(genericParams, dc, outerSignature,
1399-
allowConcreteGenericParams,
1404+
allowConcreteGenericParams, ext,
14001405
[&](GenericSignatureBuilder &) { });
14011406
}
14021407

0 commit comments

Comments
 (0)