@@ -623,15 +623,41 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
623
623
auto *decl = unboundType->getDecl ();
624
624
625
625
// Make sure we have the right number of generic arguments.
626
+ //
627
+ // For generic types without type sequence parameters, we require
628
+ // the number of declared generic parameters match the number of
629
+ // arguments.
630
+ //
631
+ // For generic types with type sequence parameters, we only require
632
+ // that the number of arguments is enough to saturate the number of
633
+ // regular generic parameters. The type sequence parameter will absorb
634
+ // any excess parameters, or will have a substitution of `Void` if there
635
+ // is nothing to bind. This Void-binding behavior of type sequences
636
+ // also explains the offset of one that isn't otherwise present in
637
+ // the plain generic parameter case.
638
+ //
639
+ // struct Foo<Prefix, T..., Suffix> {}
640
+ // typealias X = Foo<String, Int, Float, Double> // Prefix -> String, Suffix
641
+ // -> Double, T... -> (Int, Float) typealias X = Foo<String, Int> // Prefix ->
642
+ // String, Suffix -> Int, T... -> Void typealias Y = Foo<String> // error: Not
643
+ // enough arguments to bind Suffix.
644
+ //
626
645
// FIXME: If we have fewer arguments than we need, that might be okay, if
627
- // we're allowed to deduce the remaining arguments from context.
646
+ // we're allowed to deduce the remaining arguments from context. The
647
+ // expression checker certainly only cares about the case where too many
648
+ // arguments are given.
628
649
auto genericArgs = generic->getGenericArgs ();
629
650
auto genericParams = decl->getGenericParams ();
630
- if (genericParams->size () != genericArgs.size ()) {
651
+ auto hasTypeSequence = llvm::any_of (
652
+ *genericParams, [](const auto *GPT) { return GPT->isTypeSequence (); });
653
+ if ((!hasTypeSequence && genericArgs.size () != genericParams->size ()) ||
654
+ (hasTypeSequence && genericArgs.size () < genericParams->size () - 1 )) {
631
655
if (!options.contains (TypeResolutionFlags::SilenceErrors)) {
632
- diags.diagnose (loc, diag::type_parameter_count_mismatch, decl->getName (),
633
- genericParams->size (), genericArgs.size (),
634
- genericArgs.size () < genericParams->size ())
656
+ diags
657
+ .diagnose (loc, diag::type_parameter_count_mismatch, decl->getName (),
658
+ genericParams->size () - (hasTypeSequence ? 1 : 0 ),
659
+ genericArgs.size (),
660
+ genericArgs.size () < genericParams->size (), hasTypeSequence)
635
661
.highlight (generic->getAngleBrackets ());
636
662
decl->diagnose (diag::kind_declname_declared_here,
637
663
DescriptiveDeclKind::GenericType, decl->getName ());
@@ -728,8 +754,15 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
728
754
Type TypeResolution::applyUnboundGenericArguments (
729
755
GenericTypeDecl *decl, Type parentTy, SourceLoc loc,
730
756
ArrayRef<Type> genericArgs) const {
731
- assert (genericArgs.size () == decl->getGenericParams ()->size () &&
732
- " invalid arguments, use applyGenericArguments for diagnostic emitting" );
757
+ const bool hasTypeSequence =
758
+ llvm::any_of (*decl->getGenericParams (),
759
+ [](const auto *GPT) { return GPT->isTypeSequence (); });
760
+ assert (
761
+ ((!hasTypeSequence &&
762
+ genericArgs.size () == decl->getGenericParams ()->size ()) ||
763
+ (hasTypeSequence &&
764
+ genericArgs.size () >= decl->getGenericParams ()->size () - 1 )) &&
765
+ " invalid arguments, use applyGenericArguments for diagnostic emitting" );
733
766
734
767
auto genericSig = decl->getGenericSignature ();
735
768
assert (!genericSig.isNull ());
@@ -777,16 +810,62 @@ Type TypeResolution::applyUnboundGenericArguments(
777
810
778
811
// Realize the types of the generic arguments and add them to the
779
812
// substitution map.
780
- for (const unsigned i : indices (genericArgs)) {
781
- auto origTy = genericSig.getInnermostGenericParams ()[i];
782
- auto substTy = genericArgs[i];
813
+ auto innerParams = genericSig.getInnermostGenericParams ();
814
+ for (unsigned i = 0 ; i < innerParams.size (); ++i) {
815
+ auto origTy = innerParams[i];
816
+ auto origGP = origTy->getCanonicalType ()->castTo <GenericTypeParamType>();
817
+
818
+ if (!origGP->isTypeSequence ()) {
819
+ auto substTy = genericArgs[i];
820
+
821
+ // Enter a substitution.
822
+ subs[origGP] = substTy;
823
+
824
+ skipRequirementsCheck |=
825
+ substTy->hasTypeVariable () || substTy->hasUnboundGenericType ();
826
+
827
+ continue ;
828
+ }
783
829
784
- // Enter a substitution.
785
- subs[origTy->getCanonicalType ()->castTo <GenericTypeParamType>()] =
786
- substTy;
830
+ // Scan backwards to find the bounds of the longest run of
831
+ // types we can bind to this type sequence parameter.
832
+ unsigned tail;
833
+ for (tail = 1 ; tail <= innerParams.size (); ++tail) {
834
+ auto tailTy = innerParams[innerParams.size () - tail];
835
+ auto tailGP = tailTy->getCanonicalType ()->castTo <GenericTypeParamType>();
836
+ if (tailGP->isTypeSequence ()) {
837
+ assert (tailGP->isEqual (origGP) &&
838
+ " Found multiple type sequence parameters!" );
787
839
788
- skipRequirementsCheck |=
789
- substTy->hasTypeVariable () || substTy->hasUnboundGenericType ();
840
+ // Saturate the type sequence. Take care that if the prefix and suffix
841
+ // have bound all available arguments that we bind the type sequence
842
+ // parameter to `Void`.
843
+ const size_t sequenceLength = tail + i <= genericArgs.size ()
844
+ ? genericArgs.size () - tail - i + 1
845
+ : 0 ;
846
+
847
+ auto substTy = PackType::get (getASTContext (),
848
+ genericArgs.slice (i, sequenceLength));
849
+
850
+ // Enter a substitution.
851
+ subs[origGP] = substTy;
852
+
853
+ skipRequirementsCheck |=
854
+ substTy->hasTypeVariable () || substTy->hasUnboundGenericType ();
855
+
856
+ break ;
857
+ }
858
+
859
+ auto substTy = genericArgs[genericArgs.size () - tail];
860
+
861
+ // Enter a substitution.
862
+ subs[tailGP] = substTy;
863
+
864
+ skipRequirementsCheck |=
865
+ substTy->hasTypeVariable () || substTy->hasUnboundGenericType ();
866
+ }
867
+
868
+ break ;
790
869
}
791
870
792
871
// Check the generic arguments against the requirements of the declaration's
0 commit comments