Skip to content

Commit 3b81d27

Browse files
authored
Merge pull request #69129 from slavapestov/fix-apply-variadic-generic-args-5.10
Sema: Fix two bugs with type resolution of generic arguments [5.10]
2 parents 86c87a4 + 2f6d78b commit 3b81d27

File tree

9 files changed

+163
-91
lines changed

9 files changed

+163
-91
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4373,10 +4373,21 @@ ERROR(cannot_specialize_self,none,
43734373
"cannot specialize 'Self'", ())
43744374
NOTE(specialize_explicit_type_instead,none,
43754375
"did you mean to explicitly reference %0 instead?", (Type))
4376-
ERROR(type_parameter_count_mismatch,none,
4377-
"generic type %0 specialized with %select{too many|too few}3 type "
4378-
"parameters (got %2, but expected %select{%1|at least %1}4)",
4379-
(Identifier, unsigned, unsigned, bool, bool))
4376+
ERROR(too_few_generic_arguments,none,
4377+
"generic type %0 specialized with too few type parameters "
4378+
"(got %1, but expected %2)",
4379+
(Identifier, unsigned, unsigned))
4380+
ERROR(too_few_generic_arguments_pack,none,
4381+
"generic type %0 specialized with too few type parameters "
4382+
"(got %1, but expected at least %2)",
4383+
(Identifier, unsigned, unsigned))
4384+
ERROR(too_many_generic_arguments,none,
4385+
"generic type %0 specialized with too many type parameters "
4386+
"(got %1, but expected %2)",
4387+
(Identifier, unsigned, unsigned))
4388+
ERROR(generic_argument_pack_mismatch,none,
4389+
"generic type %0 specialized with mismatched type parameter pack",
4390+
(Identifier))
43804391
ERROR(generic_type_requires_arguments,none,
43814392
"reference to generic type %0 requires arguments in <...>", (Type))
43824393
NOTE(descriptive_generic_type_declared_here,none,
@@ -5658,7 +5669,7 @@ ERROR(superclass_with_pack,none,
56585669
"cannot inherit from a generic class that declares a type pack", ())
56595670
ERROR(expansion_not_allowed,none,
56605671
"pack expansion %0 can only appear in a function parameter list, "
5661-
"tuple element, or generic argument list", (Type))
5672+
"tuple element, or generic argument of a variadic type", (Type))
56625673
ERROR(expansion_expr_not_allowed,none,
56635674
"value pack expansion can only appear inside a function argument list "
56645675
"or tuple element", ())

lib/Sema/CSDiagnostics.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "CSDiagnostics.h"
1818
#include "MiscDiagnostics.h"
1919
#include "TypeCheckProtocol.h"
20+
#include "TypeCheckType.h"
2021
#include "TypoCorrection.h"
2122
#include "swift/AST/ASTContext.h"
2223
#include "swift/AST/ASTPrinter.h"
@@ -9173,7 +9174,9 @@ bool OutOfPlaceThenStmtFailure::diagnoseAsError() {
91739174
}
91749175

91759176
bool InvalidTypeSpecializationArity::diagnoseAsError() {
9176-
emitDiagnostic(diag::type_parameter_count_mismatch, D->getBaseIdentifier(),
9177-
NumParams, NumArgs, NumArgs < NumParams, HasParameterPack);
9177+
diagnoseInvalidGenericArguments(getLoc(), D,
9178+
NumArgs, NumParams,
9179+
HasParameterPack,
9180+
/*generic=*/nullptr);
91789181
return true;
91799182
}

lib/Sema/TypeCheckType.cpp

Lines changed: 84 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "swift/AST/SourceFile.h"
3939
#include "swift/AST/TypeCheckRequests.h"
4040
#include "swift/AST/TypeLoc.h"
41+
#include "swift/AST/TypeRepr.h"
4142
#include "swift/AST/TypeResolutionStage.h"
4243
#include "swift/Basic/SourceManager.h"
4344
#include "swift/Basic/Statistic.h"
@@ -143,8 +144,8 @@ static unsigned getGenericRequirementKind(TypeResolutionOptions options) {
143144
case TypeResolverContext::FunctionInput:
144145
case TypeResolverContext::PackElement:
145146
case TypeResolverContext::TupleElement:
146-
case TypeResolverContext::GenericArgument:
147-
case TypeResolverContext::ProtocolGenericArgument:
147+
case TypeResolverContext::ScalarGenericArgument:
148+
case TypeResolverContext::VariadicGenericArgument:
148149
case TypeResolverContext::ExtensionBinding:
149150
case TypeResolverContext::TypeAliasDecl:
150151
case TypeResolverContext::GenericTypeAliasDecl:
@@ -667,6 +668,51 @@ bool TypeChecker::checkContextualRequirements(GenericTypeDecl *decl,
667668
llvm_unreachable("invalid requirement check type");
668669
}
669670

671+
void swift::diagnoseInvalidGenericArguments(SourceLoc loc,
672+
ValueDecl *decl,
673+
unsigned argCount,
674+
unsigned paramCount,
675+
bool hasParameterPack,
676+
GenericIdentTypeRepr *generic) {
677+
auto &ctx = decl->getASTContext();
678+
auto &diags = ctx.Diags;
679+
680+
if (!hasParameterPack) {
681+
// For generic types without type parameter packs, we require
682+
// the number of declared generic parameters match the number of
683+
// arguments.
684+
if (argCount < paramCount) {
685+
auto diag = diags
686+
.diagnose(loc, diag::too_few_generic_arguments, decl->getBaseIdentifier(),
687+
argCount, paramCount);
688+
if (generic)
689+
diag.highlight(generic->getAngleBrackets());
690+
} else {
691+
auto diag = diags
692+
.diagnose(loc, diag::too_many_generic_arguments, decl->getBaseIdentifier(),
693+
argCount, paramCount);
694+
if (generic)
695+
diag.highlight(generic->getAngleBrackets());
696+
}
697+
} else {
698+
if (argCount < paramCount - 1) {
699+
auto diag = diags
700+
.diagnose(loc, diag::too_few_generic_arguments_pack, decl->getBaseIdentifier(),
701+
argCount, paramCount - 1);
702+
if (generic)
703+
diag.highlight(generic->getAngleBrackets());
704+
} else {
705+
auto diag = diags
706+
.diagnose(loc, diag::generic_argument_pack_mismatch, decl->getBaseIdentifier());
707+
if (generic)
708+
diag.highlight(generic->getAngleBrackets());
709+
}
710+
}
711+
712+
decl->diagnose(diag::kind_declname_declared_here,
713+
DescriptiveDeclKind::GenericType, decl->getName());
714+
}
715+
670716
/// Apply generic arguments to the given type.
671717
///
672718
/// If the type is itself not generic, this does nothing.
@@ -747,6 +793,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
747793

748794
auto genericArgs = generic->getGenericArgs();
749795

796+
// Parameterized protocol types have their own code path.
750797
if (auto *protoType = type->getAs<ProtocolType>()) {
751798
auto *protoDecl = protoType->getDecl();
752799

@@ -761,6 +808,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
761808
return ErrorType::get(ctx);
762809
}
763810

811+
// Make sure we have the right number of generic arguments.
764812
if (genericArgs.size() != assocTypes.size()) {
765813
diags.diagnose(loc,
766814
diag::parameterized_protocol_type_argument_count_mismatch,
@@ -770,45 +818,15 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
770818
return ErrorType::get(ctx);
771819
}
772820

773-
// Build ParameterizedProtocolType if the protocol has a primary associated
774-
// type and we're in a supported context.
775-
if (resolution.getOptions().isConstraintImplicitExistential() &&
776-
!ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
777-
778-
if (!genericArgs.empty()) {
779-
780-
SmallVector<Type, 2> argTys;
781-
for (auto *genericArg : genericArgs) {
782-
Type argTy = resolution.resolveType(genericArg);
783-
if (!argTy || argTy->hasError())
784-
return ErrorType::get(ctx);
785-
786-
argTys.push_back(argTy);
787-
}
788-
789-
auto parameterized =
790-
ParameterizedProtocolType::get(ctx, protoType, argTys);
791-
diags.diagnose(loc, diag::existential_requires_any, parameterized,
792-
ExistentialType::get(parameterized),
793-
/*isAlias=*/isa<TypeAliasType>(type.getPointer()));
794-
} else {
795-
diags.diagnose(loc, diag::existential_requires_any,
796-
protoDecl->getDeclaredInterfaceType(),
797-
protoDecl->getDeclaredExistentialType(),
798-
/*isAlias=*/isa<TypeAliasType>(type.getPointer()));
799-
}
800-
801-
return ErrorType::get(ctx);
802-
}
803-
804821
// Disallow opaque types anywhere in the structure of the generic arguments
805822
// to a parameterized existential type.
806823
if (options.is(TypeResolverContext::ExistentialConstraint))
807824
options |= TypeResolutionFlags::DisallowOpaqueTypes;
808825
auto argOptions = options.withoutContext().withContext(
809-
TypeResolverContext::ProtocolGenericArgument);
826+
TypeResolverContext::ScalarGenericArgument);
810827
auto genericResolution = resolution.withOptions(argOptions);
811828

829+
// Resolve the generic arguments.
812830
SmallVector<Type, 2> argTys;
813831
for (auto *genericArg : genericArgs) {
814832
Type argTy = genericResolution.resolveType(genericArg, silContext);
@@ -818,7 +836,18 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
818836
argTys.push_back(argTy);
819837
}
820838

821-
return ParameterizedProtocolType::get(ctx, protoType, argTys);
839+
auto parameterized =
840+
ParameterizedProtocolType::get(ctx, protoType, argTys);
841+
842+
if (resolution.getOptions().isConstraintImplicitExistential() &&
843+
!ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
844+
diags.diagnose(loc, diag::existential_requires_any, parameterized,
845+
ExistentialType::get(parameterized),
846+
/*isAlias=*/isa<TypeAliasType>(type.getPointer()));
847+
return ErrorType::get(ctx);
848+
}
849+
850+
return parameterized;
822851
}
823852

824853
// We must either have an unbound generic type, or a generic type alias.
@@ -844,16 +873,20 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
844873
auto *unboundType = type->castTo<UnboundGenericType>();
845874
auto *decl = unboundType->getDecl();
846875

847-
// Make sure we have the right number of generic arguments.
848876
auto genericParams = decl->getGenericParams();
849877
auto hasParameterPack = llvm::any_of(
850878
*genericParams, [](auto *paramDecl) {
851879
return paramDecl->isParameterPack();
852880
});
853881

854-
// Resolve the types of the generic arguments.
882+
// If the type declares at least one parameter pack, allow pack expansions
883+
// anywhere in the argument list. We'll use the PackMatcher to ensure that
884+
// everything lines up. Otherwise, don't allow pack expansions to appear
885+
// at all.
855886
auto argOptions = options.withoutContext().withContext(
856-
TypeResolverContext::GenericArgument);
887+
hasParameterPack
888+
? TypeResolverContext::VariadicGenericArgument
889+
: TypeResolverContext::ScalarGenericArgument);
857890
auto genericResolution = resolution.withOptions(argOptions);
858891

859892
// In SIL mode, Optional<T> interprets T as a SIL type.
@@ -865,6 +898,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
865898
}
866899
}
867900

901+
// Resolve the types of the generic arguments.
868902
SmallVector<Type, 2> args;
869903
for (auto tyR : genericArgs) {
870904
// Propagate failure.
@@ -875,21 +909,16 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
875909
args.push_back(substTy);
876910
}
877911

912+
// Make sure we have the right number of generic arguments.
878913
if (!hasParameterPack) {
879914
// For generic types without type parameter packs, we require
880915
// the number of declared generic parameters match the number of
881916
// arguments.
882917
if (genericArgs.size() != genericParams->size()) {
883918
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
884-
diags
885-
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
886-
genericParams->size(),
887-
genericArgs.size(),
888-
genericArgs.size() < genericParams->size(),
889-
/*hasParameterPack=*/0)
890-
.highlight(generic->getAngleBrackets());
891-
decl->diagnose(diag::kind_declname_declared_here,
892-
DescriptiveDeclKind::GenericType, decl->getName());
919+
diagnoseInvalidGenericArguments(
920+
loc, decl, genericArgs.size(), genericParams->size(),
921+
/*hasParameterPack=*/false, generic);
893922
}
894923
return ErrorType::get(ctx);
895924
}
@@ -907,17 +936,11 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
907936
}
908937

909938
PackMatcher matcher(params, args, ctx);
910-
if (matcher.match()) {
939+
if (matcher.match() || matcher.pairs.size() != params.size()) {
911940
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
912-
diags
913-
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
914-
genericParams->size() - 1,
915-
genericArgs.size(),
916-
genericArgs.size() < genericParams->size(),
917-
/*hasParameterPack=*/1)
918-
.highlight(generic->getAngleBrackets());
919-
decl->diagnose(diag::kind_declname_declared_here,
920-
DescriptiveDeclKind::GenericType, decl->getName());
941+
diagnoseInvalidGenericArguments(
942+
loc, decl, genericArgs.size(), genericParams->size(),
943+
/*hasParameterPack=*/true, generic);
921944
}
922945
return ErrorType::get(ctx);
923946
}
@@ -953,6 +976,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
953976
}
954977
}
955978

979+
// Construct the substituted type.
956980
const auto result = resolution.applyUnboundGenericArguments(
957981
decl, unboundType->getParent(), loc, args);
958982

@@ -4405,7 +4429,7 @@ NeverNullType
44054429
TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr,
44064430
TypeResolutionOptions options) {
44074431
auto argOptions = options.withoutContext().withContext(
4408-
TypeResolverContext::GenericArgument);
4432+
TypeResolverContext::ScalarGenericArgument);
44094433

44104434
auto keyTy = resolveType(repr->getKey(), argOptions);
44114435
if (keyTy->hasError()) {
@@ -4479,8 +4503,8 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
44794503
break;
44804504
case TypeResolverContext::PackElement:
44814505
case TypeResolverContext::TupleElement:
4482-
case TypeResolverContext::GenericArgument:
4483-
case TypeResolverContext::ProtocolGenericArgument:
4506+
case TypeResolverContext::ScalarGenericArgument:
4507+
case TypeResolverContext::VariadicGenericArgument:
44844508
case TypeResolverContext::VariadicFunctionInput:
44854509
case TypeResolverContext::ForEachStmt:
44864510
case TypeResolverContext::ExtensionBinding:

0 commit comments

Comments
 (0)