Skip to content

Commit a5d7469

Browse files
authored
Merge pull request #71628 from DougGregor/throws-shadows-typed-throws
Allow a throwing function to shadow a typed-throws one
2 parents 0558bde + e008a4f commit a5d7469

File tree

2 files changed

+65
-1
lines changed

2 files changed

+65
-1
lines changed

lib/AST/NameLookup.cpp

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -733,6 +733,53 @@ static void recordShadowedDeclsAfterTypeMatch(
733733
}
734734
}
735735

736+
/// Return an extended info for a function types that removes the use of
737+
/// the thrown error type, if present.
738+
///
739+
/// Returns \c None when no adjustment is needed.
740+
static std::optional<ASTExtInfo>
741+
extInfoRemovingThrownError(AnyFunctionType *fnType) {
742+
if (!fnType->hasExtInfo())
743+
return std::nullopt;
744+
745+
auto extInfo = fnType->getExtInfo();
746+
if (!extInfo.isThrowing() || !extInfo.getThrownError())
747+
return std::nullopt;
748+
749+
return extInfo.withThrows(true, Type());
750+
}
751+
752+
/// Remove the thrown error type.
753+
static CanType removeThrownError(Type type) {
754+
ASTContext &ctx = type->getASTContext();
755+
756+
return type.transformRec([](TypeBase *type) -> std::optional<Type> {
757+
if (auto funcTy = dyn_cast<FunctionType>(type)) {
758+
if (auto newExtInfo = extInfoRemovingThrownError(funcTy)) {
759+
return FunctionType::get(
760+
funcTy->getParams(), funcTy->getResult(), *newExtInfo)
761+
->getCanonicalType();
762+
}
763+
764+
return std::nullopt;
765+
}
766+
767+
if (auto genericFuncTy = dyn_cast<GenericFunctionType>(type)) {
768+
if (auto newExtInfo = extInfoRemovingThrownError(genericFuncTy)) {
769+
return GenericFunctionType::get(
770+
genericFuncTy->getGenericSignature(),
771+
genericFuncTy->getParams(), genericFuncTy->getResult(),
772+
*newExtInfo)
773+
->getCanonicalType();
774+
}
775+
776+
return std::nullopt;
777+
}
778+
779+
return std::nullopt;
780+
})->getCanonicalType();
781+
}
782+
736783
/// Given a set of declarations whose names and generic signatures have matched,
737784
/// figure out which of these declarations have been shadowed by others.
738785
static void recordShadowedDeclsAfterSignatureMatch(
@@ -757,7 +804,7 @@ static void recordShadowedDeclsAfterSignatureMatch(
757804
if (auto asd = dyn_cast<AbstractStorageDecl>(decl))
758805
type = asd->getOverloadSignatureType();
759806
else
760-
type = decl->getInterfaceType()->getCanonicalType();
807+
type = removeThrownError(decl->getInterfaceType()->getCanonicalType());
761808

762809
// Record this declaration based on its signature.
763810
auto &known = collisions[type];

test/decl/func/typed_throws.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,20 @@ func testArrMap(arr: [String]) {
190190
_ = mapArray(arr, body: G_E<Int>.tuple)
191191
// expected-error@-1{{cannot convert value of type '((x: Int, y: Int)) -> G_E<Int>' to expected argument type '(String) -> G_E<Int>'}}
192192
}
193+
194+
// Shadowing of typed-throws Result.get() addresses a source compatibility
195+
// issue with the introduction of typed throws.
196+
extension Result {
197+
public func dematerialize() throws -> Success {
198+
return try get()
199+
}
200+
201+
public func get() throws -> Success {
202+
switch self {
203+
case let .success(value):
204+
return value
205+
case let .failure(error):
206+
throw error
207+
}
208+
}
209+
}

0 commit comments

Comments
 (0)