Skip to content

Commit 48d4887

Browse files
committed
TypeCheckType: Look through any and some in any syntax checker
1 parent 19fbe5b commit 48d4887

File tree

3 files changed

+65
-10
lines changed

3 files changed

+65
-10
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5922,21 +5922,46 @@ class ExistentialTypeSyntaxChecker : public ASTWalker {
59225922
if (T->isInvalid())
59235923
return Action::SkipNode();
59245924

5925-
// Arbitrary protocol constraints are OK on opaque types.
5926-
if (isa<OpaqueReturnTypeRepr>(T))
5927-
return Action::SkipNode();
5928-
5929-
// Arbitrary protocol constraints are okay for 'any' types.
5930-
if (isa<ExistentialTypeRepr>(T))
5931-
return Action::SkipNode();
5932-
59335925
reprStack.push_back(T);
59345926

59355927
auto *declRefTR = dyn_cast<DeclRefTypeRepr>(T);
59365928
if (!declRefTR) {
59375929
return Action::Continue();
59385930
}
59395931

5932+
// Determine whether this identifier type is a subject of a `some` or `any`
5933+
// type and, if so, ignore it, since it already has a keyword applied to it.
5934+
// For example, `P` is a subject of `any P` and `any Q & (P)`, but
5935+
// not `any Q<P>`.
5936+
if (reprStack.size() > 1) {
5937+
auto it = reprStack.end() - 1;
5938+
while (true) {
5939+
--it;
5940+
if (it == reprStack.begin()) {
5941+
break;
5942+
}
5943+
5944+
// Look through parens, metatypes, and compositions.
5945+
if (isa<TupleTypeRepr>(*it) || isa<CompositionTypeRepr>(*it) ||
5946+
isa<MetatypeTypeRepr>(*it)) {
5947+
continue;
5948+
}
5949+
5950+
// Look through '?' and '!' too; `any P?` et al. is diagnosed in the
5951+
// type resolver.
5952+
if (isa<OptionalTypeRepr>(*it) ||
5953+
isa<ImplicitlyUnwrappedOptionalTypeRepr>(*it)) {
5954+
continue;
5955+
}
5956+
5957+
break;
5958+
}
5959+
5960+
if (isa<OpaqueReturnTypeRepr>(*it) || isa<ExistentialTypeRepr>(*it)) {
5961+
return Action::Continue();
5962+
}
5963+
}
5964+
59405965
// We only care about the type of an outermost member type representation.
59415966
// For example, in `A<T>.B.C<U>`, check `C` and generic arguments `U` and
59425967
// `T`, but not `A` or `B`.

test/type/explicit_existential.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,10 @@ protocol HasAssoc {
5959
func foo()
6060
}
6161

62+
protocol HasAssocGeneric<Assoc> {
63+
associatedtype Assoc
64+
}
65+
6266
do {
6367
enum MyError: Error {
6468
case bad(Any)
@@ -320,6 +324,17 @@ func testAnyFixIt() {
320324
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-18=(any HasAssoc)}}
321325
let _: HasAssoc.Protocol? = (any HasAssoc).self
322326

327+
// https://github.com/apple/swift/issues/72588
328+
329+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{30-38=any HasAssoc}}
330+
let _: any HasAssocGeneric<HasAssoc>
331+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{31-39=any HasAssoc}}
332+
let _: any (HasAssocGeneric<HasAssoc>)
333+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{35-43=any HasAssoc}}
334+
func f1(_: some HasAssocGeneric<HasAssoc> & HasAssoc) {}
335+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{37-45=any HasAssoc}}
336+
func f2(_: some ((HasAssocGeneric<HasAssoc>)) & (HasAssoc)) {}
337+
323338
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc)?'}}{{10-23=(any HasAssoc)?}}
324339
let _: any HasAssoc? = nil
325340
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc.Type)?'}}{{10-28=(any HasAssoc.Type)?}}
@@ -361,4 +376,4 @@ var example1: any (any IteratorProtocol) = 5 // expected-error{{redundant 'any'
361376
protocol PP {}
362377
struct A : PP {}
363378
let _: any PP = A() // Ok
364-
let _: any (any PP) = A() // expected-error{{redundant 'any' in type 'any (any PP)'}} {{8-12=}}
379+
let _: any (any PP) = A() // expected-error{{redundant 'any' in type 'any (any PP)'}} {{8-12=}}

test/type/explicit_existential_swift6.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,10 @@ protocol HasAssoc {
6565
func foo()
6666
}
6767

68+
protocol HasAssocGeneric<Assoc> {
69+
associatedtype Assoc
70+
}
71+
6872
do {
6973
enum MyError: Error {
7074
case bad(Any)
@@ -92,7 +96,7 @@ func testHasAssoc(_ x: Any, _: any HasAssoc) {
9296

9397
func method() -> any HasAssoc {}
9498
func existentialArray() -> [any HasAssoc] {}
95-
func existentialcSequence() -> any Sequence<HasAssoc> {}
99+
func existentialcSequence() -> any Sequence<any HasAssoc> {}
96100
}
97101
}
98102

@@ -353,6 +357,17 @@ func testAnyFixIt() {
353357
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{10-18=(any HasAssoc)}}
354358
let _: HasAssoc.Protocol? = (any HasAssoc).self
355359

360+
// https://github.com/apple/swift/issues/72588
361+
362+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{30-38=any HasAssoc}}
363+
let _: any HasAssocGeneric<HasAssoc>
364+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{31-39=any HasAssoc}}
365+
let _: any (HasAssocGeneric<HasAssoc>)
366+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{35-43=any HasAssoc}}
367+
func f1(_: some HasAssocGeneric<HasAssoc> & HasAssoc) {}
368+
// expected-error@+1 {{use of protocol 'HasAssoc' as a type must be written 'any HasAssoc'}}{{37-45=any HasAssoc}}
369+
func f2(_: some ((HasAssocGeneric<HasAssoc>)) & (HasAssoc)) {}
370+
356371
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc)?'}}{{10-23=(any HasAssoc)?}}
357372
let _: any HasAssoc? = nil
358373
// expected-error@+1 {{optional 'any' type must be written '(any HasAssoc.Type)?'}}{{10-28=(any HasAssoc.Type)?}}

0 commit comments

Comments
 (0)