Skip to content

Commit 1020b70

Browse files
committed
Sema: Refactor handling of type packs in apply{Unbound,}GenericArguments()
1 parent b2285f5 commit 1020b70

File tree

2 files changed

+89
-114
lines changed

2 files changed

+89
-114
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 88 additions & 113 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include "swift/AST/ForeignErrorConvention.h"
3131
#include "swift/AST/GenericEnvironment.h"
3232
#include "swift/AST/NameLookup.h"
33+
#include "swift/AST/PackExpansionMatcher.h"
3334
#include "swift/AST/ParameterList.h"
3435
#include "swift/AST/PrettyStackTrace.h"
3536
#include "swift/AST/ProtocolConformance.h"
@@ -726,6 +727,8 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
726727
auto &ctx = dc->getASTContext();
727728
auto &diags = ctx.Diags;
728729

730+
auto genericArgs = generic->getGenericArgs();
731+
729732
if (auto *protoType = type->getAs<ProtocolType>()) {
730733
auto *protoDecl = protoType->getDecl();
731734

@@ -741,8 +744,6 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
741744
return ErrorType::get(ctx);
742745
}
743746

744-
auto genericArgs = generic->getGenericArgs();
745-
746747
if (genericArgs.size() != assocTypes.size()) {
747748
diags.diagnose(loc,
748749
diag::parameterized_protocol_type_argument_count_mismatch,
@@ -809,68 +810,26 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
809810
auto *decl = unboundType->getDecl();
810811

811812
// Make sure we have the right number of generic arguments.
812-
//
813-
// For generic types without type parameter packs, we require
814-
// the number of declared generic parameters match the number of
815-
// arguments.
816-
//
817-
// For generic types with type parameter packs, we only require
818-
// that the number of arguments is enough to saturate the number of
819-
// regular generic parameters. The parameter pack will absorb
820-
// any excess parameters, or will have a substitution of `Void` if there
821-
// is nothing to bind. This Void-binding behavior of parameter packs
822-
// also explains the offset of one that isn't otherwise present in
823-
// the plain generic parameter case.
824-
//
825-
// struct Foo<Prefix, T..., Suffix> {}
826-
// typealias X = Foo<String, Int, Float, Double> // Prefix -> String, Suffix
827-
// -> Double, T... -> (Int, Float) typealias X = Foo<String, Int> // Prefix ->
828-
// String, Suffix -> Int, T... -> Void typealias Y = Foo<String> // error: Not
829-
// enough arguments to bind Suffix.
830-
//
831-
// FIXME: If we have fewer arguments than we need, that might be okay, if
832-
// we're allowed to deduce the remaining arguments from context. The
833-
// expression checker certainly only cares about the case where too many
834-
// arguments are given.
835-
auto genericArgs = generic->getGenericArgs();
836813
auto genericParams = decl->getGenericParams();
837814
auto hasParameterPack = llvm::any_of(
838-
*genericParams, [](const auto *GPT) { return GPT->isParameterPack(); });
839-
if ((!hasParameterPack && genericArgs.size() != genericParams->size()) ||
840-
(hasParameterPack && genericArgs.size() < genericParams->size() - 1)) {
841-
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
842-
diags
843-
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
844-
genericParams->size() - (hasParameterPack ? 1 : 0),
845-
genericArgs.size(),
846-
genericArgs.size() < genericParams->size(), hasParameterPack)
847-
.highlight(generic->getAngleBrackets());
848-
decl->diagnose(diag::kind_declname_declared_here,
849-
DescriptiveDeclKind::GenericType, decl->getName());
850-
}
851-
return ErrorType::get(ctx);
852-
}
815+
*genericParams, [](auto *paramDecl) {
816+
return paramDecl->isParameterPack();
817+
});
818+
819+
// Resolve the types of the generic arguments.
820+
auto argOptions = options.withoutContext().withContext(
821+
TypeResolverContext::GenericArgument);
822+
auto genericResolution = resolution.withOptions(argOptions);
853823

854824
// In SIL mode, Optional<T> interprets T as a SIL type.
855825
if (options.contains(TypeResolutionFlags::SILType)) {
856826
if (auto nominal = dyn_cast<NominalTypeDecl>(decl)) {
857827
if (nominal->isOptionalDecl()) {
858-
// Validate the generic argument.
859-
Type objectType = resolution.resolveType(genericArgs[0], silParams);
860-
if (objectType->hasError()) {
861-
return ErrorType::get(ctx);
862-
}
863-
864-
return BoundGenericType::get(nominal, /*parent*/ Type(), objectType);
828+
genericResolution = resolution;
865829
}
866-
}
830+
}
867831
}
868832

869-
// Resolve the types of the generic arguments.
870-
auto argOptions = options.withoutContext().withContext(
871-
TypeResolverContext::GenericArgument);
872-
auto genericResolution = resolution.withOptions(argOptions);
873-
874833
SmallVector<Type, 2> args;
875834
for (auto tyR : genericArgs) {
876835
// Propagate failure.
@@ -881,6 +840,69 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
881840
args.push_back(substTy);
882841
}
883842

843+
if (!hasParameterPack) {
844+
// For generic types without type parameter packs, we require
845+
// the number of declared generic parameters match the number of
846+
// arguments.
847+
if (genericArgs.size() != genericParams->size()) {
848+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
849+
diags
850+
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
851+
genericParams->size(),
852+
genericArgs.size(),
853+
genericArgs.size() < genericParams->size(),
854+
/*hasParameterPack=*/0)
855+
.highlight(generic->getAngleBrackets());
856+
decl->diagnose(diag::kind_declname_declared_here,
857+
DescriptiveDeclKind::GenericType, decl->getName());
858+
}
859+
return ErrorType::get(ctx);
860+
}
861+
} else {
862+
// For generic types with type parameter packs, we only require
863+
// that the number of arguments is enough to saturate the number of
864+
// regular generic parameters. The parameter pack will absorb
865+
// zero or arguments.
866+
SmallVector<Type, 2> params;
867+
for (auto paramDecl : genericParams->getParams()) {
868+
auto paramType = paramDecl->getDeclaredInterfaceType();
869+
params.push_back(paramDecl->isParameterPack()
870+
? PackExpansionType::get(paramType, paramType)
871+
: paramType);
872+
}
873+
874+
PackMatcher matcher(params, args, ctx);
875+
if (matcher.match()) {
876+
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
877+
diags
878+
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
879+
genericParams->size() - 1,
880+
genericArgs.size(),
881+
genericArgs.size() < genericParams->size(),
882+
/*hasParameterPack=*/1)
883+
.highlight(generic->getAngleBrackets());
884+
decl->diagnose(diag::kind_declname_declared_here,
885+
DescriptiveDeclKind::GenericType, decl->getName());
886+
}
887+
return ErrorType::get(ctx);
888+
}
889+
890+
args.clear();
891+
for (unsigned i : indices(params)) {
892+
auto found = std::find_if(matcher.pairs.begin(),
893+
matcher.pairs.end(),
894+
[&](const MatchedPair &pair) -> bool {
895+
return pair.lhsIdx == i;
896+
});
897+
assert(found != matcher.pairs.end());
898+
899+
auto arg = found->rhs;
900+
if (auto *expansionType = arg->getAs<PackExpansionType>())
901+
arg = expansionType->getPatternType();
902+
args.push_back(arg);
903+
}
904+
}
905+
884906
const auto result = resolution.applyUnboundGenericArguments(
885907
decl, unboundType->getParent(), loc, args);
886908

@@ -941,15 +963,9 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
941963
Type TypeResolution::applyUnboundGenericArguments(
942964
GenericTypeDecl *decl, Type parentTy, SourceLoc loc,
943965
ArrayRef<Type> genericArgs) const {
944-
const bool hasParameterPack =
945-
llvm::any_of(*decl->getGenericParams(),
946-
[](const auto *GPT) { return GPT->isParameterPack(); });
947-
assert(
948-
((!hasParameterPack &&
949-
genericArgs.size() == decl->getGenericParams()->size()) ||
950-
(hasParameterPack &&
951-
genericArgs.size() >= decl->getGenericParams()->size() - 1)) &&
952-
"invalid arguments, use applyGenericArguments for diagnostic emitting");
966+
assert(genericArgs.size() == decl->getGenericParams()->size() &&
967+
"invalid arguments, use applyGenericArguments to emit diagnostics "
968+
"and collect arguments to pack generic parameters");
953969

954970
TypeSubstitutionMap subs;
955971

@@ -986,6 +1002,10 @@ Type TypeResolution::applyUnboundGenericArguments(
9861002
}
9871003

9881004
skipRequirementsCheck |= parentTy->hasTypeVariable();
1005+
1006+
// Fill in substitutions for outer generic parameters if we have a local
1007+
// type in generic context. This isn't actually supported all the way,
1008+
// but we have to put something here so we don't crash.
9891009
} else if (auto parentSig =
9901010
decl->getDeclContext()->getGenericSignatureOfContext()) {
9911011
for (auto gp : parentSig.getGenericParams()) {
@@ -1000,58 +1020,13 @@ Type TypeResolution::applyUnboundGenericArguments(
10001020
auto origTy = innerParams[i]->getDeclaredInterfaceType();
10011021
auto origGP = origTy->getCanonicalType()->castTo<GenericTypeParamType>();
10021022

1003-
if (!origGP->isParameterPack()) {
1004-
auto substTy = genericArgs[i];
1005-
1006-
// Enter a substitution.
1007-
subs[origGP] = substTy;
1008-
1009-
skipRequirementsCheck |=
1010-
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
1023+
auto substTy = genericArgs[i];
10111024

1012-
continue;
1013-
}
1014-
1015-
// Scan backwards to find the bounds of the longest run of
1016-
// types we can bind to this parameter pack.
1017-
unsigned tail;
1018-
for (tail = 1; tail <= innerParams.size(); ++tail) {
1019-
auto tailTy = innerParams[innerParams.size() - tail]
1020-
->getDeclaredInterfaceType();
1021-
auto tailGP = tailTy->getCanonicalType()->castTo<GenericTypeParamType>();
1022-
if (tailGP->isParameterPack()) {
1023-
assert(tailGP->isEqual(origGP) &&
1024-
"Found multiple type parameter packs!");
1025-
1026-
// Saturate the parameter pack. Take care that if the prefix and suffix
1027-
// have bound all available arguments that we bind the parameter
1028-
// pack to `Void`.
1029-
const size_t sequenceLength = tail + i <= genericArgs.size()
1030-
? genericArgs.size() - tail - i + 1
1031-
: 0;
1025+
// Enter a substitution.
1026+
subs[origGP] = substTy;
10321027

1033-
auto substTy = PackType::get(getASTContext(),
1034-
genericArgs.slice(i, sequenceLength));
1035-
1036-
// Enter a substitution.
1037-
subs[origGP] = substTy;
1038-
1039-
skipRequirementsCheck |=
1040-
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
1041-
1042-
break;
1043-
}
1044-
1045-
auto substTy = genericArgs[genericArgs.size() - tail];
1046-
1047-
// Enter a substitution.
1048-
subs[tailGP] = substTy;
1049-
1050-
skipRequirementsCheck |=
1051-
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
1052-
}
1053-
1054-
break;
1028+
skipRequirementsCheck |=
1029+
substTy->hasTypeVariable() || substTy->hasUnboundGenericType();
10551030
}
10561031

10571032
// Check the generic arguments against the requirements of the declaration's

test/decl/typealias/generic.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ func takesSugaredType2(m: GenericClass<Int>.TA<Float>) {
337337
// parameters of A<>.
338338
extension A {}
339339

340-
extension A<T> {} // expected-error {{generic type 'A' specialized with too few type parameters (got 1, but expected 2)}}
340+
extension A<Int> {} // expected-error {{generic type 'A' specialized with too few type parameters (got 1, but expected 2)}}
341341
extension A<Float,Int> {}
342342
extension C<T> {} // expected-error {{cannot find type 'T' in scope}}
343343
extension C<Int> {}

0 commit comments

Comments
 (0)