Skip to content

Commit b70f8a8

Browse files
committed
Sema: Improve the infinite opaque return type check
Now look through other opaque return types that appear in the underlying type. This catches various forms of recursion that otherwise would cause a SILGen or SILOptimizer crash. - Fixes rdar://82992151.
1 parent 103428f commit b70f8a8

File tree

4 files changed

+100
-28
lines changed

4 files changed

+100
-28
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 26 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "swift/AST/DiagnosticsSema.h"
2828
#include "swift/AST/ExistentialLayout.h"
2929
#include "swift/AST/Expr.h"
30+
#include "swift/AST/InFlightSubstitution.h"
3031
#include "swift/AST/NameLookup.h"
3132
#include "swift/AST/NameLookupRequests.h"
3233
#include "swift/AST/Pattern.h"
@@ -3670,12 +3671,33 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
36703671

36713672
// The underlying type can't be defined recursively
36723673
// in terms of the opaque type itself.
3673-
auto opaqueTypeInContext = Implementation->mapTypeIntoContext(
3674-
OpaqueDecl->getDeclaredInterfaceType());
36753674
for (auto genericParam : OpaqueDecl->getOpaqueGenericParams()) {
36763675
auto underlyingType = Type(genericParam).subst(substitutions);
3677-
auto isSelfReferencing = underlyingType.findIf(
3678-
[&](Type t) -> bool { return t->isEqual(opaqueTypeInContext); });
3676+
3677+
// Look through underlying types of other opaque archetypes known to
3678+
// us. This is not something the type checker is allowed to do in
3679+
// general, since the intent is that the underlying type is completely
3680+
// hidden from view at the type system level. However, here we're
3681+
// trying to catch recursive underlying types before we proceed to
3682+
// SIL, so we specifically want to erase opaque archetypes just
3683+
// for the purpose of this check.
3684+
ReplaceOpaqueTypesWithUnderlyingTypes replacer(
3685+
OpaqueDecl->getDeclContext(),
3686+
ResilienceExpansion::Maximal,
3687+
/*isWholeModuleContext=*/false);
3688+
InFlightSubstitution IFS(replacer, replacer,
3689+
SubstFlags::SubstituteOpaqueArchetypes |
3690+
SubstFlags::PreservePackExpansionLevel);
3691+
auto simplifiedUnderlyingType = underlyingType.subst(IFS);
3692+
3693+
auto isSelfReferencing =
3694+
(IFS.wasLimitReached() ||
3695+
simplifiedUnderlyingType.findIf([&](Type t) -> bool {
3696+
if (auto *other = t->getAs<OpaqueTypeArchetypeType>()) {
3697+
return other->getDecl() == OpaqueDecl;
3698+
}
3699+
return false;
3700+
}));
36793701

36803702
if (isSelfReferencing) {
36813703
Ctx.Diags.diagnose(std::get<0>(candidate)->getLoc(),
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
// RUN: %target-typecheck-verify-swift
2+
3+
func concrete1() -> some Any {
4+
// expected-error@-1 {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
5+
return concrete1()
6+
}
7+
8+
func concrete2() -> some Any {
9+
return [concrete2()] // expected-error {{function opaque return type was inferred as '[some Any]', which defines the opaque type in terms of itself}}
10+
}
11+
12+
13+
func concrete1a() -> some Any {
14+
return concrete1b() // expected-error {{function opaque return type was inferred as 'some Any', which defines the opaque type in terms of itself}}
15+
}
16+
17+
func concrete1b() -> some Any {
18+
return concrete1a()
19+
}
20+
21+
22+
func concrete2a() -> some Any {
23+
return [concrete2b()] // expected-error {{function opaque return type was inferred as '[some Any]', which defines the opaque type in terms of itself}}
24+
}
25+
26+
func concrete2b() -> some Any {
27+
return [concrete2a()]
28+
}
29+
30+
31+
func generic1<T>(_ t: T) -> some Any {
32+
// expected-error@-1 {{function declares an opaque return type, but has no return statements in its body from which to infer an underlying type}}
33+
return generic1(t)
34+
}
35+
36+
func generic2<T>(_ t: T) -> some Any {
37+
return [generic2(t)] // expected-error {{function opaque return type was inferred as '[some Any]', which defines the opaque type in terms of itself}}
38+
}
39+
40+
41+
func generic1a<T>(_ t: T) -> some Any {
42+
return generic1b(t) // expected-error {{function opaque return type was inferred as 'some Any', which defines the opaque type in terms of itself}}
43+
}
44+
45+
func generic1b<T>(_ t: T) -> some Any {
46+
return generic1a(t)
47+
}
48+
49+
50+
func generic2a<T>(_ t: T) -> some Any {
51+
return [generic2b(t)] // expected-error {{function opaque return type was inferred as '[some Any]', which defines the opaque type in terms of itself}}
52+
}
53+
54+
func generic2b<T>(_ t: T) -> some Any {
55+
return [generic2a(t)]
56+
}
57+
58+
59+
func generic3a<T>(_ t: T) -> some Any {
60+
return [generic3b(t)] // expected-error {{function opaque return type was inferred as '[some Any]', which defines the opaque type in terms of itself}}
61+
}
62+
63+
func generic3b<T>(_ t: T) -> some Any {
64+
return [generic3a([t])]
65+
}
66+
67+
func very_wide1() -> some Any {
68+
return (very_wide2(), very_wide2()) // expected-error {{function opaque return type was inferred as '(some Any, some Any)', which defines the opaque type in terms of itself}}
69+
}
70+
71+
func very_wide2() -> some Any {
72+
return (very_wide1(), very_wide1())
73+
}

test/type/opaque.swift

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-swift-frontend -disable-availability-checking -typecheck -verify %s
1+
// RUN: %target-swift-frontend -target %target-swift-5.1-abi-triple -typecheck -verify %s
22

33
protocol P {
44
func paul()
@@ -205,13 +205,6 @@ struct MismatchedReturnTypesSubscript {
205205
}
206206
}
207207

208-
func jan() -> some P {
209-
return [marcia(), marcia(), marcia()]
210-
}
211-
func marcia() -> some P {
212-
return [marcia(), marcia(), marcia()] // expected-error{{defines the opaque type in terms of itself}} {{documentation-file=opaque-type-inference}}
213-
}
214-
215208
protocol R {
216209
associatedtype S: P, Q // expected-note*{{}}
217210

validation-test/compiler_crashers_2_fixed/rdar87121502.swift

Lines changed: 0 additions & 16 deletions
This file was deleted.

0 commit comments

Comments
 (0)