Skip to content

Commit cf76fcf

Browse files
committed
Sema: Don't allow parameterized protocol types that specify too few type arguments
1 parent 8c47cd7 commit cf76fcf

File tree

4 files changed

+20
-48
lines changed

4 files changed

+20
-48
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3776,13 +3776,13 @@ ERROR(protocol_declares_unknown_primary_assoc_type,none,
37763776
ERROR(protocol_declares_duplicate_primary_assoc_type,none,
37773777
"duplicate primary associated type name %0", (Identifier))
37783778
ERROR(parameterized_protocol_not_supported,none,
3779-
"protocol type with generic arguments can only be used as a generic constraint", ())
3779+
"protocol type with type arguments can only be used as a generic constraint", ())
37803780
ERROR(protocol_does_not_have_primary_assoc_type,none,
37813781
"cannot specialize protocol type %0", (Type))
3782-
ERROR(parameterized_protocol_too_many_type_arguments,none,
3783-
"protocol type %0 can specialized with too many type parameters "
3784-
"(got %1, but expected at most %2)",
3785-
(Type, unsigned, unsigned))
3782+
ERROR(parameterized_protocol_type_argument_count_mismatch,none,
3783+
"protocol type %0 specialized with %select{too many|too few}3 type arguments "
3784+
"(got %1, but expected %2)",
3785+
(Type, unsigned, unsigned, unsigned))
37863786
ERROR(cannot_specialize_self,none,
37873787
"cannot specialize 'Self'", ())
37883788
NOTE(specialize_explicit_type_instead,none,

lib/Sema/TypeCheckType.cpp

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -649,9 +649,11 @@ static Type applyGenericArguments(Type type, TypeResolution resolution,
649649

650650
auto genericArgs = generic->getGenericArgs();
651651

652-
if (genericArgs.size() > assocTypes.size()) {
653-
diags.diagnose(loc, diag::parameterized_protocol_too_many_type_arguments,
654-
protoType, genericArgs.size(), assocTypes.size());
652+
if (genericArgs.size() != assocTypes.size()) {
653+
diags.diagnose(loc,
654+
diag::parameterized_protocol_type_argument_count_mismatch,
655+
protoType, genericArgs.size(), assocTypes.size(),
656+
(genericArgs.size() < assocTypes.size()) ? 1 : 0);
655657

656658
return ErrorType::get(ctx);
657659
}

test/SILGen/existential_parameters.swift

Lines changed: 4 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -44,48 +44,16 @@ func upupupupcast(_ x: S) -> any P {
4444
// CHECK: store [[CONCRETE_VAL]] to [trivial] [[INIT_INT_STRING_FLOAT]] : $*S
4545
// CHECK: [[OPEN_INT_STRING_FLOAT:%.*]] = open_existential_addr immutable_access %3 : $*P<Int, String, Float> to $*[[OPENED_P_INT_STRING_FLOAT:@opened(.*) P<Int, String, Float>]]
4646

47-
// CHECK: [[P_INT_STRING:%.*]] = alloc_stack $P<Int, String>
48-
// CHECK: [[INIT_INT_STRING:%.*]] = init_existential_addr [[P_INT_STRING]] : $*P<Int, String>, $[[OPENED_P_INT_STRING_FLOAT]]
49-
// CHECK: copy_addr [[OPEN_INT_STRING_FLOAT]] to [initialization] [[INIT_INT_STRING]] : $*[[OPENED_P_INT_STRING_FLOAT]]
50-
// CHECK: [[OPEN_INT_STRING:%.*]] = open_existential_addr immutable_access [[P_INT_STRING]] : $*P<Int, String> to $*[[OPENED_P_INT_STRING:@opened(.*) P<Int, String>]]
51-
52-
// CHECK: [[P_INT:%.*]] = alloc_stack $P<Int>
53-
// CHECK: [[INIT_INT:%.*]] = init_existential_addr [[P_INT]] : $*P<Int>, $[[OPENED_P_INT_STRING]]
54-
// CHECK: copy_addr [[OPEN_INT_STRING]] to [initialization] [[INIT_INT]] : $*[[OPENED_P_INT_STRING]]
55-
// CHECK: [[OPEN_INT:%.*]] = open_existential_addr immutable_access [[P_INT]] : $*P<Int> to $*[[OPENED_P_INT:@opened(.*) P<Int>]]
56-
57-
// CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*P, $[[OPENED_P_INT]]
58-
// CHECK: copy_addr [[OPEN_INT]] to [initialization] [[RESULT_INIT]] : $*[[OPENED_P_INT]]
59-
return x as any P<Int, String, Float> as any P<Int, String> as any P<Int> as any P
47+
// CHECK: [[RESULT_INIT:%.*]] = init_existential_addr [[RESULT_PARAM]] : $*P, $[[OPENED_P_INT_STRING_FLOAT]]
48+
// CHECK: copy_addr [[OPEN_INT_STRING_FLOAT]] to [initialization] [[RESULT_INIT]] : $*[[OPENED_P_INT_STRING_FLOAT]]
49+
return x as any P<Int, String, Float> as any P
6050
}
6151

6252
func use(_ k: (S) -> Void) {}
6353

6454
// CHECK-LABEL: sil hidden [ossa] @$s13parameterized11upcastInputyyF : $@convention(thin) () -> () {
6555
func upcastInput() {
66-
// CHECK: [[INT_STRING_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pySiSSXPXEfU_ : $@convention(thin) (@in_guaranteed P<Int, String>) -> ()
67-
// CHECK: [[NOESCAPE_INT_STRING_FN:%.*]] = convert_function [[INT_STRING_FN]] : $@convention(thin) (@in_guaranteed P<Int, String>) -> () to $@convention(thin) @noescape (@in_guaranteed P<Int, String>) -> ()
68-
// CHECK: [[THICK_INT_STRING_FN:%.*]] = thin_to_thick_function [[NOESCAPE_INT_STRING_FN]] : $@convention(thin) @noescape (@in_guaranteed P<Int, String>) -> () to $@noescape @callee_guaranteed (@in_guaranteed P<Int, String>) -> ()
69-
// CHECK: [[S_TO_INT_STRING_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pySiSSXPIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int, String>) -> ()) -> ()
70-
// CHECK: [[PARTIAL_INT_STRING_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_INT_STRING_THUNK_FN]]([[THICK_INT_STRING_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int, String>) -> ()) -> ()
71-
// CHECK: [[NOESCAPE_INT_STRING_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_INT_STRING_THUNK_FN]] : $@callee_guaranteed (S) -> () to $@noescape @callee_guaranteed (S) -> ()
72-
// CHECK: [[USE_FN:%.*]] = function_ref @$s13parameterized3useyyyAA1SVXEF : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> ()
73-
// CHECK: {{%.*}} = apply [[USE_FN]]([[NOESCAPE_INT_STRING_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> ()
74-
75-
use({ (p: any P<Int, String>) -> Void in })
76-
77-
// CHECK: [[INT_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pySiXPXEfU0_ : $@convention(thin) (@in_guaranteed P<Int>) -> ()
78-
// CHECK: [[NOESCAPE_INT_FN:%.*]] = convert_function [[INT_FN]] : $@convention(thin) (@in_guaranteed P<Int>) -> () to $@convention(thin) @noescape (@in_guaranteed P<Int>) -> ()
79-
// CHECK: [[THICK_INT_FN:%.*]] = thin_to_thick_function [[NOESCAPE_INT_FN]] : $@convention(thin) @noescape (@in_guaranteed P<Int>) -> () to $@noescape @callee_guaranteed (@in_guaranteed P<Int>) -> ()
80-
// CHECK: [[S_TO_INT_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pySiXPIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int>) -> ()) -> ()
81-
// CHECK: [[PARTIAL_INT_THUNK_FN:%.*]] = partial_apply [callee_guaranteed] [[S_TO_INT_THUNK_FN]]([[THICK_INT_FN]]) : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P<Int>) -> ()) -> ()
82-
// CHECK: [[NOESCAPE_INT_THUNK_FN:%.*]] = convert_escape_to_noescape [not_guaranteed] [[PARTIAL_INT_THUNK_FN]] : $@callee_guaranteed (S) -> () to $@noescape @callee_guaranteed (S) -> ()
83-
// CHECK: [[USE_FN:%.*]] = function_ref @$s13parameterized3useyyyAA1SVXEF : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> ()
84-
// CHECK: {{%.*}} = apply [[USE_FN]]([[NOESCAPE_INT_THUNK_FN]]) : $@convention(thin) (@noescape @callee_guaranteed (S) -> ()) -> ()
85-
86-
use({ (p: any P<Int>) -> Void in })
87-
88-
// CHECK: [[P_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pXEfU1_ : $@convention(thin) (@in_guaranteed P) -> ()
56+
// CHECK: [[P_FN:%.*]] = function_ref @$s13parameterized11upcastInputyyFyAA1P_pXEfU_ : $@convention(thin) (@in_guaranteed P) -> ()
8957
// CHECK: [[NOESCAPE_P_FN:%.*]] = convert_function [[P_FN]] : $@convention(thin) (@in_guaranteed P) -> () to $@convention(thin) @noescape (@in_guaranteed P) -> ()
9058
// CHECK: [[THICK_P_FN:%.*]] = thin_to_thick_function [[NOESCAPE_P_FN]] : $@convention(thin) @noescape (@in_guaranteed P) -> () to $@noescape @callee_guaranteed (@in_guaranteed P) -> ()
9159
// CHECK: [[S_TO_P_THUNK_FN:%.*]] = function_ref @$s13parameterized1P_pIgn_AA1SVIegy_TR : $@convention(thin) (S, @noescape @callee_guaranteed (@in_guaranteed P) -> ()) -> ()

test/type/parameterized_protocol.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -132,8 +132,10 @@ protocol Collection<Element, Index> : Sequence {
132132
}
133133

134134
func testCollectionBad1<T : Collection<String>>(_: T) {}
135+
// expected-error@-1 {{protocol type 'Collection' specialized with too few type arguments (got 1, but expected 2)}}
136+
135137
func testCollectionBad2<T : Collection<String, Int, Float>>(_: T) {}
136-
// expected-error@-1 {{protocol type 'Collection' can specialized with too many type parameters (got 3, but expected at most 2)}}
138+
// expected-error@-1 {{protocol type 'Collection' specialized with too many type arguments (got 3, but expected 2)}}
137139

138140
// CHECK-LABEL: .testCollectionGood@
139141
// CHECK-NEXT: Generic signature: <T where T : Collection, T.[Sequence]Element == String, T.[Collection]Index == Int>
@@ -181,18 +183,18 @@ extension Sequence<Int> {
181183
/// Cannot use parameterized protocol as the type of a value
182184

183185
func takesSequenceOfInt1(_: Sequence<Int>) {}
184-
// expected-error@-1 {{protocol type with generic arguments can only be used as a generic constraint}}
186+
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}
185187

186188
func returnsSequenceOfInt1() -> Sequence<Int> {}
187-
// expected-error@-1 {{protocol type with generic arguments can only be used as a generic constraint}}
189+
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}
188190

189191
func takesSequenceOfInt2(_: any Sequence<Int>) {}
190192

191193
func returnsSequenceOfInt2() -> any Sequence<Int> {}
192194

193195
func typeExpr() {
194196
_ = Sequence<Int>.self
195-
// expected-error@-1 {{protocol type with generic arguments can only be used as a generic constraint}}
197+
// expected-error@-1 {{protocol type with type arguments can only be used as a generic constraint}}
196198
}
197199

198200
/// Not supported as a protocol composition term for now

0 commit comments

Comments
 (0)