Skip to content

Commit fb8e23e

Browse files
committed
Propagate Failures Explicitly in Opaque Type Resolution
This code should not yield the null Type() on failure. Instead, diagnose the failure and yield an ErrorType. This matches what clients of this function expect to signal failure. Include a regression test that exercises a common failure mode if we don't do this: module interface loading crashes. rdar://62745419
1 parent 2938466 commit fb8e23e

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

lib/Sema/TypeCheckType.cpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2657,17 +2657,21 @@ Type TypeResolver::resolveOpaqueReturnType(TypeRepr *repr,
26572657
if (auto generic = dyn_cast<GenericIdentTypeRepr>(repr)) {
26582658
for (auto argRepr : generic->getGenericArgs()) {
26592659
auto argTy = resolveType(argRepr, options);
2660-
if (!argTy)
2661-
return Type();
2660+
// If we cannot resolve the generic parameter, propagate the error out.
2661+
if (!argTy || argTy->hasError()) {
2662+
return ErrorType::get(Context);
2663+
}
26622664
TypeArgsBuf.push_back(argTy);
26632665
}
26642666
}
26652667

26662668
// Use type reconstruction to summon the opaque type decl.
26672669
Demangler demangle;
26682670
auto definingDeclNode = demangle.demangleSymbol(mangledName);
2669-
if (!definingDeclNode)
2670-
return Type();
2671+
if (!definingDeclNode) {
2672+
diagnose(repr->getLoc(), diag::no_opaque_return_type_of);
2673+
return ErrorType::get(Context);
2674+
}
26712675
if (definingDeclNode->getKind() == Node::Kind::Global)
26722676
definingDeclNode = definingDeclNode->getChild(0);
26732677
ASTBuilder builder(Context);
@@ -2677,8 +2681,9 @@ Type TypeResolver::resolveOpaqueReturnType(TypeRepr *repr,
26772681

26782682
auto TypeArgs = ArrayRef<Type>(TypeArgsBuf);
26792683
auto ty = builder.resolveOpaqueType(opaqueNode, TypeArgs, ordinal);
2680-
if (!ty) {
2684+
if (!ty || ty->hasError()) {
26812685
diagnose(repr->getLoc(), diag::no_opaque_return_type_of);
2686+
return ErrorType::get(Context);
26822687
}
26832688
return ty;
26842689
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Test that we emit a diagnostic (and don't crash) when we cannot resolve
2+
// an opaque result type reference.
3+
//
4+
// First, emit an empty module interface:
5+
//
6+
// RUN: %empty-directory(%t)
7+
// RUN: echo "" | %target-swift-frontend -typecheck -emit-module-interface-path %t/InvalidOpaqueResultType.swiftinterface -enable-library-evolution -swift-version 5 -module-name InvalidOpaqueResultType -
8+
//
9+
// Then, blit some invalid opaque result types into the interface
10+
//
11+
// Test that we reject broken type parameters
12+
// RUN: echo "public typealias SomeGenericBalderdash = @_opaqueReturnTypeOf(\"$somesuchnonsense\", 0) 🦸<InvalidParameter>" >> %t/InvalidOpaqueResultType.swiftinterface
13+
// Test that we reject types we cannot demangle
14+
// RUN: echo "public typealias SomesuchNonsense = @_opaqueReturnTypeOf(\"$somesuchnonsense\", 0) 🦸" >> %t/InvalidOpaqueResultType.swiftinterface
15+
//
16+
// The stage is set:
17+
//
18+
// RUN: not %target-swift-frontend -typecheck %s -I %t 2>&1 | %FileCheck %s
19+
20+
// CHECK: cannot find type 'InvalidParameter' in scope
21+
// CHECK: unable to resolve type for _opaqueReturnTypeOf attribute
22+
// CHECK: failed to build module 'InvalidOpaqueResultType' from its module interface
23+
import InvalidOpaqueResultType

0 commit comments

Comments
 (0)