Skip to content

Yet more typed throws fixes #69824

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Nov 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 24 additions & 13 deletions lib/AST/Type.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5065,6 +5065,28 @@ case TypeKind::Id:
isUnchanged = false;
}

llvm::Optional<ASTExtInfo> extInfo;
if (function->hasExtInfo()) {
extInfo = function->getExtInfo()
.withGlobalActor(globalActorType)
.withThrows(function->isThrowing(), thrownError);

// If there was a generic thrown error and it substituted with
// 'any Error' or 'Never', map to 'throws' or non-throwing rather than
// maintaining the sugar.
if (auto origThrownError = function->getThrownError()) {
if (origThrownError->isTypeParameter() ||
origThrownError->isTypeVariableOrMember()) {
// 'any Error'
if (thrownError->isEqual(
thrownError->getASTContext().getErrorExistentialType()))
extInfo = extInfo->withThrows(true, Type());
else if (thrownError->isNever())
extInfo = extInfo->withThrows(false, Type());
}
}
}

if (auto genericFnType = dyn_cast<GenericFunctionType>(base)) {
#ifndef NDEBUG
// Check that generic parameters won't be transformed.
Expand All @@ -5080,24 +5102,13 @@ case TypeKind::Id:
if (isUnchanged) return *this;

auto genericSig = genericFnType->getGenericSignature();
if (!function->hasExtInfo())
return GenericFunctionType::get(genericSig, substParams, resultTy);
return GenericFunctionType::get(
genericSig, substParams, resultTy,
function->getExtInfo()
.withGlobalActor(globalActorType)
.withThrows(function->isThrowing(), thrownError));
genericSig, substParams, resultTy, extInfo);
}

if (isUnchanged) return *this;

if (!function->hasExtInfo())
return FunctionType::get(substParams, resultTy);
return FunctionType::get(
substParams, resultTy,
function->getExtInfo()
.withGlobalActor(globalActorType)
.withThrows(function->isThrowing(), thrownError));
return FunctionType::get(substParams, resultTy, extInfo);
}

case TypeKind::ArraySlice: {
Expand Down
19 changes: 14 additions & 5 deletions lib/SILOptimizer/LoopTransforms/ForEachLoopUnroll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -483,10 +483,11 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
// targets must be taking a phi argument.
SILBasicBlock *normalBB = forEachCall->getNormalBB();
SILBasicBlock *errorBB = forEachCall->getErrorBB();
assert(errorBB->getSILPhiArguments().size() == 1 &&
normalBB->getSILPhiArguments().size() == 1);
assert(normalBB->getSILPhiArguments().size() == 1);
SILPhiArgument *normalArgument = normalBB->getSILPhiArguments()[0];
SILPhiArgument *errorArgument = errorBB->getSILPhiArguments()[0];
SILPhiArgument *errorArgument = nullptr;
if (errorBB->getSILPhiArguments().size() == 1)
errorArgument = errorBB->getSILPhiArguments()[0];

// A generator for creating a basic block for use as the target of the
// "normal" branch of a try_apply.
Expand All @@ -503,8 +504,12 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
auto errorTargetGenerator = [&](SILBasicBlock *insertionBlock,
SILValue borrowedElem, SILValue storeBorrow) {
SILBasicBlock *newErrorBB = fun->createBasicBlockBefore(insertionBlock);
SILValue argument = newErrorBB->createPhiArgument(
SILValue argument;
if (errorArgument) {
argument = newErrorBB->createPhiArgument(
errorArgument->getType(), errorArgument->getOwnershipKind());
}

// Make the errorBB jump to the error target of the original forEach.
SILBuilderWithScope builder(newErrorBB, forEachCall);
if (storeBorrow) {
Expand All @@ -513,7 +518,11 @@ static void unrollForEach(ArrayInfo &arrayInfo, TryApplyInst *forEachCall,
if (borrowedElem) {
builder.createEndBorrow(forEachLoc, borrowedElem);
}
builder.createBranch(forEachLoc, errorBB, argument);

if (argument)
builder.createBranch(forEachLoc, errorBB, argument);
else
builder.createBranch(forEachLoc, errorBB);
return newErrorBB;
};

Expand Down
3 changes: 2 additions & 1 deletion lib/SILOptimizer/Mandatory/TransferNonSendable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -647,7 +647,8 @@ class PartitionOpTranslator {

if (auto tryApplyInst = dyn_cast<TryApplyInst>(inst)) {
foundResults.emplace_back(tryApplyInst->getNormalBB()->getArgument(0));
foundResults.emplace_back(tryApplyInst->getErrorBB()->getArgument(0));
if (tryApplyInst->getErrorBB()->getNumArguments() > 0)
foundResults.emplace_back(tryApplyInst->getErrorBB()->getArgument(0));
return;
}

Expand Down
16 changes: 12 additions & 4 deletions lib/SILOptimizer/Transforms/SpeculativeDevirtualizer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -239,11 +239,19 @@ static FullApplySite speculateMonomorphicTarget(FullApplySite AI,
// Split critical edges resulting from VirtAI.
if (auto *TAI = dyn_cast<TryApplyInst>(VirtAI)) {
auto *ErrorBB = TAI->getFunction()->createBasicBlock();
ErrorBB->createPhiArgument(TAI->getErrorBB()->getArgument(0)->getType(),
OwnershipKind::Owned);
SILArgument *ErrorArg = nullptr;
if (TAI->getErrorBB()->getNumArguments() == 1) {
ErrorArg = TAI->getErrorBB()->getArgument(0);
ErrorBB->createPhiArgument(ErrorArg->getType(), OwnershipKind::Owned);
}
Builder.setInsertionPoint(ErrorBB);
Builder.createBranch(TAI->getLoc(), TAI->getErrorBB(),
{ErrorBB->getArgument(0)});

if (ErrorArg) {
Builder.createBranch(TAI->getLoc(), TAI->getErrorBB(),
{ErrorBB->getArgument(0)});
} else {
Builder.createBranch(TAI->getLoc(), TAI->getErrorBB());
}

auto *NormalBB = TAI->getFunction()->createBasicBlock();
NormalBB->createPhiArgument(TAI->getNormalBB()->getArgument(0)->getType(),
Expand Down
11 changes: 11 additions & 0 deletions test/decl/func/typed_throws.swift
Original file line number Diff line number Diff line change
Expand Up @@ -179,3 +179,14 @@ func fromRethrows(body: () throws -> Void) rethrows {
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}}
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}}
}

// Substitution involving 'any Error' or 'Never' thrown error types should
// use untyped throws or be non-throwing.
enum G_E<T> {
case tuple((x: T, y: T))
}

func testArrMap(arr: [String]) {
_ = mapArray(arr, body: G_E<Int>.tuple)
// expected-error@-1{{cannot convert value of type '((x: Int, y: Int)) -> G_E<Int>' to expected argument type '(String) -> G_E<Int>'}}
}