@@ -616,6 +616,27 @@ static void simple_display(llvm::raw_ostream &out, ConditionalEffectKind kind) {
616616 llvm_unreachable (" Bad conditional effect kind" );
617617}
618618
619+ // / Remove the type erasure to an existential error, to extract the
620+ // / underlying error.
621+ static Expr *removeErasureToExistentialError (Expr *expr) {
622+ Type type = expr->getType ();
623+ if (!type)
624+ return expr;
625+
626+ ASTContext &ctx = type->getASTContext ();
627+ if (!ctx.LangOpts .hasFeature (Feature::FullTypedThrows) ||
628+ !ctx.LangOpts .hasFeature (Feature::TypedThrows))
629+ return expr;
630+
631+ // Look for an outer erasure expression.
632+ if (auto erasure = dyn_cast<ErasureExpr>(expr)) {
633+ if (type->isEqual (ctx.getErrorExistentialType ()))
634+ return erasure->getSubExpr ();
635+ }
636+
637+ return expr;
638+ }
639+
619640// / A type expressing the result of classifying whether a call or function
620641// / throws or is async.
621642class Classification {
@@ -989,6 +1010,10 @@ class ApplyClassifier {
9891010 if (!thrownValue)
9901011 return Classification::forInvalidCode ();
9911012
1013+ // If we are doing full typed throws, look through an existential
1014+ // conversion to find the underlying type.
1015+ thrownValue = removeErasureToExistentialError (thrownValue);
1016+
9921017 Type thrownType = thrownValue->getType ();
9931018 if (!thrownType)
9941019 return Classification::forInvalidCode ();
@@ -2893,6 +2918,18 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
28932918
28942919 if (!CurContext.handlesThrows (ConditionalEffectKind::Always))
28952920 CurContext.diagnoseUnhandledThrowStmt (Ctx.Diags , S);
2921+ else {
2922+ SourceLoc loc = S->getThrowLoc ();
2923+ Expr *thrownValue = S->getSubExpr ();
2924+ Type thrownErrorType = thrownValue->getType ();
2925+ Type caughtErrorType = getCaughtErrorTypeAt (loc);
2926+ if (!caughtErrorType->isEqual (thrownErrorType)) {
2927+ thrownValue = removeErasureToExistentialError (thrownValue);
2928+ Type thrownErrorType = thrownValue->getType ();
2929+ if (!checkThrownErrorType (loc, thrownErrorType))
2930+ S->setSubExpr (thrownValue);
2931+ }
2932+ }
28962933 }
28972934
28982935 return ShouldRecurse;
@@ -2978,16 +3015,19 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
29783015
29793016 // / Check the thrown error type against the type that can be caught or
29803017 // / rethrown by the context.
2981- void checkThrownErrorType (SourceLoc loc, Type thrownErrorType) {
3018+ // /
3019+ // / Returns \c true if an error occurred, false otherwise.
3020+ bool checkThrownErrorType (SourceLoc loc, Type thrownErrorType) {
29823021 Type caughtErrorType = getCaughtErrorTypeAt (loc);
29833022 if (caughtErrorType->isEqual (thrownErrorType))
2984- return ;
3023+ return false ;
29853024
29863025 OpaqueValueExpr *opaque = new (Ctx) OpaqueValueExpr (loc, thrownErrorType);
29873026 Expr *rethrowExpr = opaque;
2988- TypeChecker::typeCheckExpression (
3027+ Type resultType = TypeChecker::typeCheckExpression (
29893028 rethrowExpr, CurContext.getDeclContext (),
29903029 {caughtErrorType, /* FIXME:*/ CTP_ThrowStmt});
3030+ return resultType.isNull ();
29913031 }
29923032
29933033 ShouldRecurse_t checkAwait (AwaitExpr *E) {
0 commit comments