@@ -616,6 +616,27 @@ static void simple_display(llvm::raw_ostream &out, ConditionalEffectKind kind) {
616
616
llvm_unreachable (" Bad conditional effect kind" );
617
617
}
618
618
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
+
619
640
// / A type expressing the result of classifying whether a call or function
620
641
// / throws or is async.
621
642
class Classification {
@@ -989,6 +1010,10 @@ class ApplyClassifier {
989
1010
if (!thrownValue)
990
1011
return Classification::forInvalidCode ();
991
1012
1013
+ // If we are doing full typed throws, look through an existential
1014
+ // conversion to find the underlying type.
1015
+ thrownValue = removeErasureToExistentialError (thrownValue);
1016
+
992
1017
Type thrownType = thrownValue->getType ();
993
1018
if (!thrownType)
994
1019
return Classification::forInvalidCode ();
@@ -2893,6 +2918,18 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
2893
2918
2894
2919
if (!CurContext.handlesThrows (ConditionalEffectKind::Always))
2895
2920
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
+ }
2896
2933
}
2897
2934
2898
2935
return ShouldRecurse;
@@ -2978,16 +3015,19 @@ class CheckEffectsCoverage : public EffectsHandlingWalker<CheckEffectsCoverage>
2978
3015
2979
3016
// / Check the thrown error type against the type that can be caught or
2980
3017
// / 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) {
2982
3021
Type caughtErrorType = getCaughtErrorTypeAt (loc);
2983
3022
if (caughtErrorType->isEqual (thrownErrorType))
2984
- return ;
3023
+ return false ;
2985
3024
2986
3025
OpaqueValueExpr *opaque = new (Ctx) OpaqueValueExpr (loc, thrownErrorType);
2987
3026
Expr *rethrowExpr = opaque;
2988
- TypeChecker::typeCheckExpression (
3027
+ Type resultType = TypeChecker::typeCheckExpression (
2989
3028
rethrowExpr, CurContext.getDeclContext (),
2990
3029
{caughtErrorType, /* FIXME:*/ CTP_ThrowStmt});
3030
+ return resultType.isNull ();
2991
3031
}
2992
3032
2993
3033
ShouldRecurse_t checkAwait (AwaitExpr *E) {
0 commit comments