Skip to content

Commit eb3d7c5

Browse files
committed
Drop throws(any Error) and throws(Never) sugar after substitution
When substitution into a function type with `throws(E)` produces either `throws(any Error)` or `throws(Never)`, adjust the resulting function type to the equivalent `throws` or non-throwing.
1 parent 254ecb6 commit eb3d7c5

File tree

2 files changed

+35
-13
lines changed

2 files changed

+35
-13
lines changed

lib/AST/Type.cpp

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5065,6 +5065,28 @@ case TypeKind::Id:
50655065
isUnchanged = false;
50665066
}
50675067

5068+
llvm::Optional<ASTExtInfo> extInfo;
5069+
if (function->hasExtInfo()) {
5070+
extInfo = function->getExtInfo()
5071+
.withGlobalActor(globalActorType)
5072+
.withThrows(function->isThrowing(), thrownError);
5073+
5074+
// If there was a generic thrown error and it substituted with
5075+
// 'any Error' or 'Never', map to 'throws' or non-throwing rather than
5076+
// maintaining the sugar.
5077+
if (auto origThrownError = function->getThrownError()) {
5078+
if (origThrownError->isTypeParameter() ||
5079+
origThrownError->isTypeVariableOrMember()) {
5080+
// 'any Error'
5081+
if (thrownError->isEqual(
5082+
thrownError->getASTContext().getErrorExistentialType()))
5083+
extInfo = extInfo->withThrows(true, Type());
5084+
else if (thrownError->isNever())
5085+
extInfo = extInfo->withThrows(false, Type());
5086+
}
5087+
}
5088+
}
5089+
50685090
if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
50695091
#ifndef NDEBUG
50705092
// Check that generic parameters won't be transformed.
@@ -5080,24 +5102,13 @@ case TypeKind::Id:
50805102
if (isUnchanged) return *this;
50815103

50825104
auto genericSig = genericFnType->getGenericSignature();
5083-
if (!function->hasExtInfo())
5084-
return GenericFunctionType::get(genericSig, substParams, resultTy);
50855105
return GenericFunctionType::get(
5086-
genericSig, substParams, resultTy,
5087-
function->getExtInfo()
5088-
.withGlobalActor(globalActorType)
5089-
.withThrows(function->isThrowing(), thrownError));
5106+
genericSig, substParams, resultTy, extInfo);
50905107
}
50915108

50925109
if (isUnchanged) return *this;
50935110

5094-
if (!function->hasExtInfo())
5095-
return FunctionType::get(substParams, resultTy);
5096-
return FunctionType::get(
5097-
substParams, resultTy,
5098-
function->getExtInfo()
5099-
.withGlobalActor(globalActorType)
5100-
.withThrows(function->isThrowing(), thrownError));
5111+
return FunctionType::get(substParams, resultTy, extInfo);
51015112
}
51025113

51035114
case TypeKind::ArraySlice: {

test/decl/func/typed_throws.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,3 +179,14 @@ func fromRethrows(body: () throws -> Void) rethrows {
179179
try notRethrowsLike2(body) // expected-error{{call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does}}
180180
try notRethrowsLike3(body) // expected-error{{call can throw, but the error is not handled; a function declared 'rethrows' may only throw if its parameter does}}
181181
}
182+
183+
// Substitution involving 'any Error' or 'Never' thrown error types should
184+
// use untyped throws or be non-throwing.
185+
enum G_E<T> {
186+
case tuple((x: T, y: T))
187+
}
188+
189+
func testArrMap(arr: [String]) {
190+
_ = mapArray(arr, body: G_E<Int>.tuple)
191+
// expected-error@-1{{cannot convert value of type '((x: Int, y: Int)) -> G_E<Int>' to expected argument type '(String) -> G_E<Int>'}}
192+
}

0 commit comments

Comments
 (0)