Skip to content

Commit 22793b4

Browse files
committed
Fixes for opaque return types on local functions.
- In Sema, don't traverse nested declarations while deducing the opaque return type. This would cause returns inside nested functions to clobber the return type of the outer function. - In IRGen, walk the list of opaque return types we keep in the SourceFile already for type reconstruction, instead of trying to visit them ad-hoc as part of walking the AST, since IRGen doesn't normally walk the bodies of function decls directly. Fixes rdar://problem/50459091
1 parent d0ae1d9 commit 22793b4

File tree

7 files changed

+25
-29
lines changed

7 files changed

+25
-29
lines changed

include/swift/AST/Module.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1000,6 +1000,7 @@ class SourceFile final : public FileUnit {
10001000
llvm::SetVector<TypeDecl *> LocalTypeDecls;
10011001

10021002
/// The set of validated opaque return type decls in the source file.
1003+
llvm::SmallVector<OpaqueTypeDecl *, 4> OpaqueReturnTypes;
10031004
llvm::StringMap<OpaqueTypeDecl *> ValidatedOpaqueReturnTypes;
10041005
/// The set of parsed decls with opaque return types that have not yet
10051006
/// been validated.

lib/AST/Module.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1792,8 +1792,11 @@ SourceFile::lookupOpaqueResultType(StringRef MangledName,
17921792
void SourceFile::markDeclWithOpaqueResultTypeAsValidated(ValueDecl *vd) {
17931793
UnvalidatedDeclsWithOpaqueReturnTypes.erase(vd);
17941794
if (auto opaqueDecl = vd->getOpaqueResultTypeDecl()) {
1795-
ValidatedOpaqueReturnTypes.insert(
1795+
auto inserted = ValidatedOpaqueReturnTypes.insert(
17961796
{opaqueDecl->getOpaqueReturnTypeIdentifier().str(), opaqueDecl});
1797+
if (inserted.second) {
1798+
OpaqueReturnTypes.push_back(opaqueDecl);
1799+
}
17971800
}
17981801
}
17991802

lib/IRGen/GenDecl.cpp

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -436,6 +436,8 @@ void IRGenModule::emitSourceFile(SourceFile &SF) {
436436
emitGlobalDecl(decl);
437437
for (auto *localDecl : SF.LocalTypeDecls)
438438
emitGlobalDecl(localDecl);
439+
for (auto *opaqueDecl : SF.OpaqueReturnTypes)
440+
maybeEmitOpaqueTypeDecl(opaqueDecl);
439441

440442
SF.collectLinkLibraries([this](LinkLibrary linkLib) {
441443
this->addLinkLibrary(linkLib);
@@ -1884,17 +1886,10 @@ void IRGenModule::emitGlobalDecl(Decl *D) {
18841886
return;
18851887

18861888
case DeclKind::Var:
1887-
emitAbstractStorageDecl(cast<AbstractStorageDecl>(D));
1888-
return;
1889-
18901889
case DeclKind::Accessor:
1890+
case DeclKind::Func:
18911891
// Handled in SIL.
18921892
return;
1893-
1894-
case DeclKind::Func:
1895-
// The function body itself is lowered to SIL, but there may be associated
1896-
// decls to emit.
1897-
return emitFuncDecl(cast<FuncDecl>(D));
18981893

18991894
case DeclKind::TopLevelCode:
19001895
// All the top-level code will be lowered separately.
@@ -3881,12 +3876,9 @@ void IRGenModule::emitNestedTypeDecls(DeclRange members) {
38813876
continue;
38823877

38833878
case DeclKind::Func:
3884-
emitFuncDecl(cast<FuncDecl>(member));
3885-
continue;
3886-
38873879
case DeclKind::Var:
38883880
case DeclKind::Subscript:
3889-
emitAbstractStorageDecl(cast<AbstractStorageDecl>(member));
3881+
// Handled in SIL.
38903882
continue;
38913883

38923884
case DeclKind::PatternBinding:

lib/IRGen/GenStruct.cpp

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -891,20 +891,6 @@ void IRGenModule::maybeEmitOpaqueTypeDecl(OpaqueTypeDecl *opaque) {
891891
}
892892
}
893893

894-
void IRGenModule::emitFuncDecl(FuncDecl *fd) {
895-
// If there's an opaque return type for this function, emit its descriptor.
896-
if (auto opaque = fd->getOpaqueResultTypeDecl()) {
897-
maybeEmitOpaqueTypeDecl(opaque);
898-
}
899-
}
900-
901-
void IRGenModule::emitAbstractStorageDecl(AbstractStorageDecl *fd) {
902-
// If there's an opaque return type for this function, emit its descriptor.
903-
if (auto opaque = fd->getOpaqueResultTypeDecl()) {
904-
maybeEmitOpaqueTypeDecl(opaque);
905-
}
906-
}
907-
908894
namespace {
909895
/// A type implementation for resilient struct types. This is not a
910896
/// StructTypeInfoBase at all, since we don't know anything about

lib/IRGen/IRGenModule.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1204,8 +1204,6 @@ private: \
12041204
void emitStructDecl(StructDecl *D);
12051205
void emitClassDecl(ClassDecl *D);
12061206
void emitExtension(ExtensionDecl *D);
1207-
void emitFuncDecl(FuncDecl *D);
1208-
void emitAbstractStorageDecl(AbstractStorageDecl *D);
12091207
void emitOpaqueTypeDecl(OpaqueTypeDecl *D);
12101208
void emitSILGlobalVariable(SILGlobalVariable *gv);
12111209
void emitCoverageMapping();

lib/Sema/MiscDiagnostics.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2333,6 +2333,11 @@ class OpaqueUnderlyingTypeChecker : public ASTWalker {
23332333

23342334
return {true, S};
23352335
}
2336+
2337+
// Don't descend into nested decls.
2338+
bool walkToDeclPre(Decl *D) override {
2339+
return false;
2340+
}
23362341
};
23372342

23382343
} // end anonymous namespace

test/IRGen/opaque_result_type.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,16 @@ func baz<T: P & Q>(z: T) -> some P & Q {
132132
return z
133133
}
134134

135+
// Ensure the local type's opaque descriptor gets emitted.
136+
// CHECK-LABEL: @"$s18opaque_result_type11localOpaqueQryF0D0L_QryFQOMQ" =
137+
func localOpaque() -> some P {
138+
func local() -> some P {
139+
return "local"
140+
}
141+
142+
return local()
143+
}
144+
135145
public func useFoo(x: String, y: C) {
136146
let p = foo(x: x)
137147
let pa = p.poo()
@@ -181,3 +191,4 @@ struct X<T: R, U: R>: R {
181191
return Wrapper(wrapped: u)
182192
}
183193
}
194+

0 commit comments

Comments
 (0)