Skip to content

Commit e298fb5

Browse files
authored
Merge pull request #69116 from slavapestov/fix-apply-variadic-generic-args
Sema: Fix two bugs with type resolution of generic arguments
2 parents 0329545 + 73c18fb commit e298fb5

File tree

9 files changed

+150
-61
lines changed

9 files changed

+150
-61
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4420,10 +4420,21 @@ ERROR(cannot_specialize_self,none,
44204420
"cannot specialize 'Self'", ())
44214421
NOTE(specialize_explicit_type_instead,none,
44224422
"did you mean to explicitly reference %0 instead?", (Type))
4423-
ERROR(type_parameter_count_mismatch,none,
4424-
"generic type %0 specialized with %select{too many|too few}3 type "
4425-
"parameters (got %2, but expected %select{%1|at least %1}4)",
4426-
(Identifier, unsigned, unsigned, bool, bool))
4423+
ERROR(too_few_generic_arguments,none,
4424+
"generic type %0 specialized with too few type parameters "
4425+
"(got %1, but expected %2)",
4426+
(Identifier, unsigned, unsigned))
4427+
ERROR(too_few_generic_arguments_pack,none,
4428+
"generic type %0 specialized with too few type parameters "
4429+
"(got %1, but expected at least %2)",
4430+
(Identifier, unsigned, unsigned))
4431+
ERROR(too_many_generic_arguments,none,
4432+
"generic type %0 specialized with too many type parameters "
4433+
"(got %1, but expected %2)",
4434+
(Identifier, unsigned, unsigned))
4435+
ERROR(generic_argument_pack_mismatch,none,
4436+
"generic type %0 specialized with mismatched type parameter pack",
4437+
(Identifier))
44274438
ERROR(generic_type_requires_arguments,none,
44284439
"reference to generic type %0 requires arguments in <...>", (Type))
44294440
NOTE(descriptive_generic_type_declared_here,none,
@@ -5721,7 +5732,7 @@ ERROR(superclass_with_pack,none,
57215732
"cannot inherit from a generic class that declares a type pack", ())
57225733
ERROR(expansion_not_allowed,none,
57235734
"pack expansion %0 can only appear in a function parameter list, "
5724-
"tuple element, or generic argument list", (Type))
5735+
"tuple element, or generic argument of a variadic type", (Type))
57255736
ERROR(expansion_expr_not_allowed,none,
57265737
"value pack expansion can only appear inside a function argument list "
57275738
"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"
@@ -9313,7 +9314,9 @@ bool OutOfPlaceThenStmtFailure::diagnoseAsError() {
93139314
}
93149315

93159316
bool InvalidTypeSpecializationArity::diagnoseAsError() {
9316-
emitDiagnostic(diag::type_parameter_count_mismatch, D->getBaseIdentifier(),
9317-
NumParams, NumArgs, NumArgs < NumParams, HasParameterPack);
9317+
diagnoseInvalidGenericArguments(getLoc(), D,
9318+
NumArgs, NumParams,
9319+
HasParameterPack,
9320+
/*generic=*/nullptr);
93189321
return true;
93199322
}

lib/Sema/TypeCheckType.cpp

Lines changed: 71 additions & 30 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,
@@ -775,7 +823,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
775823
if (options.is(TypeResolverContext::ExistentialConstraint))
776824
options |= TypeResolutionFlags::DisallowOpaqueTypes;
777825
auto argOptions = options.withoutContext().withContext(
778-
TypeResolverContext::ProtocolGenericArgument);
826+
TypeResolverContext::ScalarGenericArgument);
779827
auto genericResolution = resolution.withOptions(argOptions);
780828

781829
// Resolve the generic arguments.
@@ -791,8 +839,6 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
791839
auto parameterized =
792840
ParameterizedProtocolType::get(ctx, protoType, argTys);
793841

794-
// Build ParameterizedProtocolType if the protocol has primary associated
795-
// types and we're in a supported context.
796842
if (resolution.getOptions().isConstraintImplicitExistential() &&
797843
!ctx.LangOpts.hasFeature(Feature::ImplicitSome)) {
798844
diags.diagnose(loc, diag::existential_requires_any, parameterized,
@@ -827,16 +873,20 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
827873
auto *unboundType = type->castTo<UnboundGenericType>();
828874
auto *decl = unboundType->getDecl();
829875

830-
// Make sure we have the right number of generic arguments.
831876
auto genericParams = decl->getGenericParams();
832877
auto hasParameterPack = llvm::any_of(
833878
*genericParams, [](auto *paramDecl) {
834879
return paramDecl->isParameterPack();
835880
});
836881

837-
// 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.
838886
auto argOptions = options.withoutContext().withContext(
839-
TypeResolverContext::GenericArgument);
887+
hasParameterPack
888+
? TypeResolverContext::VariadicGenericArgument
889+
: TypeResolverContext::ScalarGenericArgument);
840890
auto genericResolution = resolution.withOptions(argOptions);
841891

842892
// In SIL mode, Optional<T> interprets T as a SIL type.
@@ -848,6 +898,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
848898
}
849899
}
850900

901+
// Resolve the types of the generic arguments.
851902
SmallVector<Type, 2> args;
852903
for (auto tyR : genericArgs) {
853904
// Propagate failure.
@@ -858,21 +909,16 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
858909
args.push_back(substTy);
859910
}
860911

912+
// Make sure we have the right number of generic arguments.
861913
if (!hasParameterPack) {
862914
// For generic types without type parameter packs, we require
863915
// the number of declared generic parameters match the number of
864916
// arguments.
865917
if (genericArgs.size() != genericParams->size()) {
866918
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
867-
diags
868-
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
869-
genericParams->size(),
870-
genericArgs.size(),
871-
genericArgs.size() < genericParams->size(),
872-
/*hasParameterPack=*/0)
873-
.highlight(generic->getAngleBrackets());
874-
decl->diagnose(diag::kind_declname_declared_here,
875-
DescriptiveDeclKind::GenericType, decl->getName());
919+
diagnoseInvalidGenericArguments(
920+
loc, decl, genericArgs.size(), genericParams->size(),
921+
/*hasParameterPack=*/false, generic);
876922
}
877923
return ErrorType::get(ctx);
878924
}
@@ -890,17 +936,11 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
890936
}
891937

892938
PackMatcher matcher(params, args, ctx);
893-
if (matcher.match()) {
939+
if (matcher.match() || matcher.pairs.size() != params.size()) {
894940
if (!options.contains(TypeResolutionFlags::SilenceErrors)) {
895-
diags
896-
.diagnose(loc, diag::type_parameter_count_mismatch, decl->getName(),
897-
genericParams->size() - 1,
898-
genericArgs.size(),
899-
genericArgs.size() < genericParams->size(),
900-
/*hasParameterPack=*/1)
901-
.highlight(generic->getAngleBrackets());
902-
decl->diagnose(diag::kind_declname_declared_here,
903-
DescriptiveDeclKind::GenericType, decl->getName());
941+
diagnoseInvalidGenericArguments(
942+
loc, decl, genericArgs.size(), genericParams->size(),
943+
/*hasParameterPack=*/true, generic);
904944
}
905945
return ErrorType::get(ctx);
906946
}
@@ -936,6 +976,7 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
936976
}
937977
}
938978

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

@@ -4433,7 +4474,7 @@ NeverNullType
44334474
TypeResolver::resolveDictionaryType(DictionaryTypeRepr *repr,
44344475
TypeResolutionOptions options) {
44354476
auto argOptions = options.withoutContext().withContext(
4436-
TypeResolverContext::GenericArgument);
4477+
TypeResolverContext::ScalarGenericArgument);
44374478

44384479
auto keyTy = resolveType(repr->getKey(), argOptions);
44394480
if (keyTy->hasError()) {
@@ -4507,8 +4548,8 @@ NeverNullType TypeResolver::resolveImplicitlyUnwrappedOptionalType(
45074548
break;
45084549
case TypeResolverContext::PackElement:
45094550
case TypeResolverContext::TupleElement:
4510-
case TypeResolverContext::GenericArgument:
4511-
case TypeResolverContext::ProtocolGenericArgument:
4551+
case TypeResolverContext::ScalarGenericArgument:
4552+
case TypeResolverContext::VariadicGenericArgument:
45124553
case TypeResolverContext::VariadicFunctionInput:
45134554
case TypeResolverContext::ForEachStmt:
45144555
case TypeResolverContext::ExtensionBinding:

lib/Sema/TypeCheckType.h

Lines changed: 27 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ class PackElementTypeRepr;
3131
class GenericEnvironment;
3232
class GenericSignature;
3333
class SILTypeResolutionContext;
34+
class GenericIdentTypeRepr;
3435

3536
/// Flags that describe the context of type checking a pattern or
3637
/// type.
@@ -91,11 +92,17 @@ enum class TypeResolverContext : uint8_t {
9192
/// No special type handling is required.
9293
None,
9394

94-
/// Whether we are checking generic arguments of a bound generic type.
95-
GenericArgument,
95+
/// Whether we are checking generic arguments of a non-variadic bound generic
96+
/// type. This includes parameterized protocol types. We don't allow pack
97+
/// expansions here.
98+
ScalarGenericArgument,
9699

97-
/// Whether we are checking generic arguments of a parameterized protocol type.
98-
ProtocolGenericArgument,
100+
/// Whether we are checking generic arguments of a variadic generic type.
101+
/// We allow pack expansions in all argument positions, and then use the
102+
/// PackMatcher to ensure that scalar parameters line up with scalar
103+
/// arguments, and pack expansion parameters line up with pack expansion
104+
/// arguments.
105+
VariadicGenericArgument,
99106

100107
/// Whether we are checking a tuple element type.
101108
TupleElement,
@@ -261,8 +268,8 @@ class TypeResolutionOptions {
261268
case Context::ClosureExpr:
262269
return true;
263270
case Context::None:
264-
case Context::GenericArgument:
265-
case Context::ProtocolGenericArgument:
271+
case Context::ScalarGenericArgument:
272+
case Context::VariadicGenericArgument:
266273
case Context::TupleElement:
267274
case Context::PackElement:
268275
case Context::FunctionInput:
@@ -307,8 +314,8 @@ class TypeResolutionOptions {
307314
case Context::MetatypeBase:
308315
return false;
309316
case Context::None:
310-
case Context::GenericArgument:
311-
case Context::ProtocolGenericArgument:
317+
case Context::ScalarGenericArgument:
318+
case Context::VariadicGenericArgument:
312319
case Context::PackElement:
313320
case Context::TupleElement:
314321
case Context::InExpression:
@@ -341,11 +348,11 @@ class TypeResolutionOptions {
341348
case Context::VariadicFunctionInput:
342349
case Context::PackElement:
343350
case Context::TupleElement:
344-
case Context::GenericArgument:
351+
case Context::VariadicGenericArgument:
345352
return true;
346-
case Context::PatternBindingDecl:
347353
case Context::None:
348-
case Context::ProtocolGenericArgument:
354+
case Context::PatternBindingDecl:
355+
case Context::ScalarGenericArgument:
349356
case Context::Inherited:
350357
case Context::GenericParameterInherited:
351358
case Context::AssociatedTypeInherited:
@@ -390,8 +397,8 @@ class TypeResolutionOptions {
390397
case Context::FunctionInput:
391398
case Context::PackElement:
392399
case Context::TupleElement:
393-
case Context::GenericArgument:
394-
case Context::ProtocolGenericArgument:
400+
case Context::ScalarGenericArgument:
401+
case Context::VariadicGenericArgument:
395402
case Context::ExtensionBinding:
396403
case Context::TypeAliasDecl:
397404
case Context::GenericTypeAliasDecl:
@@ -655,6 +662,13 @@ class TypeResolution {
655662
ArrayRef<Type> genericArgs) const;
656663
};
657664

665+
void diagnoseInvalidGenericArguments(SourceLoc loc,
666+
ValueDecl *decl,
667+
unsigned argCount,
668+
unsigned paramCount,
669+
bool hasParameterPack,
670+
GenericIdentTypeRepr *generic);
671+
658672
} // end namespace swift
659673

660674
#endif /* SWIFT_SEMA_TYPE_CHECK_TYPE_H */

test/Constraints/pack-expansion-expressions.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,9 +36,9 @@ func coerceExpansion<each T>(_ value: repeat each T) {
3636

3737
func localValuePack<each T>(_ t: repeat each T) -> (repeat each T, repeat each T) {
3838
let local = repeat each t
39-
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
39+
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
4040
let localAnnotated: repeat each T = repeat each t
41-
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
41+
// expected-error@-1{{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
4242

4343
return (repeat each local, repeat each localAnnotated)
4444
}
@@ -92,7 +92,7 @@ func sameShapeDiagnostics<each T, each U>(t: repeat each T, u: repeat each U) {
9292
_ = (repeat (Array<each T>(), each u)) // expected-error {{pack expansion requires that 'each T' and 'each U' have the same shape}}
9393
}
9494

95-
func returnPackExpansionType<each T>(_ t: repeat each T) -> repeat each T { // expected-error {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
95+
func returnPackExpansionType<each T>(_ t: repeat each T) -> repeat each T { // expected-error {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
9696
fatalError()
9797
}
9898

test/Generics/rdar115538574.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,5 @@ protocol P<A> {
55
}
66

77
func f<each T>(_: some P<repeat each T>) {}
8-
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument list}}
8+
// expected-error@-1 {{pack expansion 'repeat each T' can only appear in a function parameter list, tuple element, or generic argument of a variadic type}}
99
// expected-error@-2 {{generic parameter 'T' is not used in function signature}}

0 commit comments

Comments
 (0)