22
22
#include " TypeCheckAvailability.h"
23
23
#include " TypeCheckConcurrency.h"
24
24
#include " TypeCheckDistributed.h"
25
+ #include " TypeCheckEffects.h"
25
26
#include " TypeCheckObjC.h"
26
27
#include " swift/AST/ASTContext.h"
27
28
#include " swift/AST/ASTMangler.h"
@@ -589,6 +590,8 @@ RequirementMatch swift::matchWitness(
589
590
// Perform basic matching of the requirement and witness.
590
591
bool decomposeFunctionType = false ;
591
592
bool ignoreReturnType = false ;
593
+ Type reqThrownError;
594
+ Type witnessThrownError;
592
595
if (isa<FuncDecl>(req) && isa<FuncDecl>(witness)) {
593
596
auto funcReq = cast<FuncDecl>(req);
594
597
auto funcWitness = cast<FuncDecl>(witness);
@@ -681,12 +684,36 @@ RequirementMatch swift::matchWitness(
681
684
MatchKind::MutatingConflict);
682
685
}
683
686
687
+ // Check for async mismatches.
688
+ if (!witnessASD->isLessEffectfulThan (reqASD, EffectKind::Async)) {
689
+ return RequirementMatch (
690
+ getStandinForAccessor (witnessASD, AccessorKind::Get),
691
+ MatchKind::AsyncConflict);
692
+ }
693
+
684
694
// Check that the witness has no more effects than the requirement.
685
695
if (auto problem = checkEffects (witnessASD, reqASD))
686
696
return problem.value ();
687
697
688
698
// Decompose the parameters for subscript declarations.
689
699
decomposeFunctionType = isa<SubscriptDecl>(req);
700
+
701
+ // Dig out the thrown error types from the getter so we can compare them
702
+ // later.
703
+ auto getThrownErrorType = [](AbstractStorageDecl *asd) -> Type {
704
+ if (auto getter = asd->getEffectfulGetAccessor ()) {
705
+ if (Type thrownErrorType = getter->getThrownInterfaceType ()) {
706
+ return thrownErrorType;
707
+ } else if (getter->hasThrows ()) {
708
+ return asd->getASTContext ().getAnyExistentialType ();
709
+ }
710
+ }
711
+
712
+ return asd->getASTContext ().getNeverType ();
713
+ };
714
+
715
+ reqThrownError = getThrownErrorType (reqASD);
716
+ witnessThrownError = getThrownErrorType (witnessASD);
690
717
} else if (isa<ConstructorDecl>(witness)) {
691
718
decomposeFunctionType = true ;
692
719
ignoreReturnType = true ;
@@ -831,12 +858,11 @@ RequirementMatch swift::matchWitness(
831
858
return RequirementMatch (witness, MatchKind::AsyncConflict);
832
859
}
833
860
834
- // If the witness is 'throws', the requirement must be.
835
- // FIXME: We need the same matching we do in the constraint solver,
836
- // with the same fast paths for obvious throws/nonthrows cases.
837
- if (witnessFnType->getExtInfo ().isThrowing () &&
838
- !reqFnType->getExtInfo ().isThrowing ()) {
839
- return RequirementMatch (witness, MatchKind::ThrowsConflict);
861
+ if (!reqThrownError) {
862
+ // Save the thrown error types of the requirement and witness so we
863
+ // can check them later.
864
+ reqThrownError = getEffectiveThrownErrorTypeOrNever (reqFnType);
865
+ witnessThrownError = getEffectiveThrownErrorTypeOrNever (witnessFnType);
840
866
}
841
867
}
842
868
} else {
@@ -859,6 +885,35 @@ RequirementMatch swift::matchWitness(
859
885
}
860
886
}
861
887
888
+ // Check the thrown error types. This includes 'any Error' and 'Never' for
889
+ // untyped throws and non-throwing cases as well.
890
+ if (reqThrownError && witnessThrownError) {
891
+ auto thrownErrorTypes = getTypesToCompare (
892
+ req, reqThrownError, false , witnessThrownError, false ,
893
+ VarianceKind::None);
894
+
895
+ Type reqThrownError = std::get<0 >(thrownErrorTypes);
896
+ Type witnessThrownError = std::get<1 >(thrownErrorTypes);
897
+ switch (compareThrownErrorsForSubtyping (witnessThrownError, reqThrownError,
898
+ dc)) {
899
+ case ThrownErrorSubtyping::DropsThrows:
900
+ case ThrownErrorSubtyping::Mismatch:
901
+ return RequirementMatch (witness, MatchKind::ThrowsConflict);
902
+
903
+ case ThrownErrorSubtyping::ExactMatch:
904
+ case ThrownErrorSubtyping::Subtype:
905
+ // All is well.
906
+ break ;
907
+
908
+ case ThrownErrorSubtyping::Dependent:
909
+ // We need to perform type matching
910
+ if (auto result = matchTypes (witnessThrownError, reqThrownError)) {
911
+ return std::move (result.value ());
912
+ }
913
+ break ;
914
+ }
915
+ }
916
+
862
917
// Now finalize the match.
863
918
auto result = finalize (anyRenaming, optionalAdjustments);
864
919
// Check if the requirement's `@differentiable` attributes are satisfied by
0 commit comments