Skip to content

Commit 0fcc7cd

Browse files
committed
Check the underlying type of get-only computed properties with opaque return types.
1 parent 59fd141 commit 0fcc7cd

File tree

3 files changed

+48
-7
lines changed

3 files changed

+48
-7
lines changed

lib/Sema/MiscDiagnostics.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2804,6 +2804,13 @@ void swift::performAbstractFuncDeclDiagnostics(TypeChecker &TC,
28042804
// to determine the underlying type.
28052805
if (auto opaqueResultTy = AFD->getOpaqueResultTypeDecl()) {
28062806
OpaqueUnderlyingTypeChecker(TC, AFD, opaqueResultTy).check();
2807+
} else if (auto accessor = dyn_cast<AccessorDecl>(AFD)) {
2808+
if (accessor->isGetter()) {
2809+
if (auto opaqueResultTy
2810+
= accessor->getStorage()->getOpaqueResultTypeDecl()) {
2811+
OpaqueUnderlyingTypeChecker(TC, AFD, opaqueResultTy).check();
2812+
}
2813+
}
28072814
}
28082815
}
28092816

lib/Sema/TypeCheckStmt.cpp

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -468,11 +468,26 @@ class StmtChecker : public StmtVisitor<StmtChecker, Stmt*> {
468468

469469
// If the result type is an opaque type, this is an opportunity to resolve
470470
// the underlying type.
471+
auto isOpaqueReturnTypeOfCurrentFunc = [&](OpaqueTypeDecl *opaque) -> bool {
472+
// Closures currently don't support having opaque types.
473+
auto funcDecl = TheFunc->getAbstractFunctionDecl();
474+
if (!funcDecl)
475+
return false;
476+
// Either the function is declared with its own opaque return type...
477+
if (opaque->getNamingDecl() == funcDecl)
478+
return true;
479+
// ...or the function is a getter for a property or subscript with an
480+
// opaque return type.
481+
if (auto accessor = dyn_cast<AccessorDecl>(funcDecl)) {
482+
return accessor->isGetter()
483+
&& opaque->getNamingDecl() == accessor->getStorage();
484+
}
485+
return false;
486+
};
487+
471488
if (auto opaque = ResultTy->getAs<OpaqueTypeArchetypeType>()) {
472-
if (auto funcDecl = TheFunc->getAbstractFunctionDecl()) {
473-
if (opaque->getDecl()->getNamingDecl() == funcDecl) {
474-
options |= TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType;
475-
}
489+
if (isOpaqueReturnTypeOfCurrentFunc(opaque->getDecl())) {
490+
options |= TypeCheckExprFlags::ConvertTypeIsOpaqueReturnType;
476491
}
477492
}
478493

test/type/opaque.swift

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,23 @@ class D: C, P, Q { func paul() {}; func priscilla() {}; func quinn() {} }
1515
// TODO: Should be valid
1616

1717
let property: some P = 1 // TODO expected-error{{cannot convert}}
18+
let deflessProperty: some P // TODO e/xpected-error{{butz}}
1819

1920
struct GenericProperty<T: P> {
2021
var x: T
2122
var property: some P {
22-
return x // TODO expected-error{{cannot convert}}
23+
return x
2324
}
2425
}
2526

2627
let (bim, bam): some P = (1, 2) // expected-error{{'some' type can only be declared on a single property declaration}}
2728
var computedProperty: some P {
28-
get { return 1 } // TODO expected-error{{cannot convert}}
29+
get { return 1 }
2930
set { _ = newValue + 1 } // TODO expected-error{{}} expected-note{{}}
3031
}
3132
struct SubscriptTest {
3233
subscript(_ x: Int) -> some P {
33-
return x // TODO expected-error{{cannot convert}}
34+
return x
3435
}
3536
}
3637

@@ -183,6 +184,24 @@ func mismatchedReturnTypes(_ x: Bool, _ y: Int, _ z: String) -> some P { // expe
183184
}
184185
}
185186

187+
var mismatchedReturnTypesProperty: some P { // expected-error{{do not have matching underlying types}}
188+
if true {
189+
return 0 // expected-note{{underlying type 'Int'}}
190+
} else {
191+
return "" // expected-note{{underlying type 'String'}}
192+
}
193+
}
194+
195+
struct MismatchedReturnTypesSubscript {
196+
subscript(x: Bool, y: Int, z: String) -> some P { // expected-error{{do not have matching underlying types}}
197+
if x {
198+
return y // expected-note{{underlying type 'Int'}}
199+
} else {
200+
return z // expected-note{{underlying type 'String'}}
201+
}
202+
}
203+
}
204+
186205
func jan() -> some P {
187206
return [marcia(), marcia(), marcia()]
188207
}

0 commit comments

Comments
 (0)