@@ -499,15 +499,12 @@ checkEffects(AbstractStorageDecl *witness, AbstractStorageDecl *req) {
499499 return std::nullopt ; // OK
500500}
501501
502- RequirementMatch swift::matchWitness (
503- DeclContext *dc, ValueDecl *req, ValueDecl *witness,
504- llvm::function_ref<
505- std::tuple<std::optional<RequirementMatch>, Type, Type>(void )>
506- setup,
507- llvm::function_ref<std::optional<RequirementMatch>(Type, Type)> matchTypes,
508- llvm::function_ref<RequirementMatch(bool , ArrayRef<OptionalAdjustment>)>
509- finalize) {
510-
502+ // / Implementation of `matchWitnessStructure` that also sets a few out paramters
503+ // / to be used by `matchWitness`.
504+ static std::optional<RequirementMatch>
505+ matchWitnessStructureImpl (ValueDecl *req, ValueDecl *witness,
506+ bool &decomposeFunctionType, bool &ignoreReturnType,
507+ Type &reqThrownError, Type &witnessThrownError) {
511508 assert (!req->isInvalid () && " Cannot have an invalid requirement here" );
512509
513510 // / Make sure the witness is of the same kind as the requirement.
@@ -530,7 +527,7 @@ RequirementMatch swift::matchWitness(
530527 if (witness->isRecursiveValidation ()) {
531528 return RequirementMatch (witness, MatchKind::Circularity);
532529 }
533-
530+
534531 // If the witness is invalid, record that and stop now.
535532 if (witness->isInvalid ()) {
536533 return RequirementMatch (witness, MatchKind::WitnessInvalid);
@@ -541,10 +538,6 @@ RequirementMatch swift::matchWitness(
541538 const auto &witnessAttrs = witness->getAttrs ();
542539
543540 // Perform basic matching of the requirement and witness.
544- bool decomposeFunctionType = false ;
545- bool ignoreReturnType = false ;
546- Type reqThrownError;
547- Type witnessThrownError;
548541 if (isa<FuncDecl>(req) && isa<FuncDecl>(witness)) {
549542 auto funcReq = cast<FuncDecl>(req);
550543 auto funcWitness = cast<FuncDecl>(witness);
@@ -617,7 +610,7 @@ RequirementMatch swift::matchWitness(
617610 decomposeFunctionType = true ;
618611 } else if (auto *witnessASD = dyn_cast<AbstractStorageDecl>(witness)) {
619612 auto *reqASD = cast<AbstractStorageDecl>(req);
620-
613+
621614 // Check that the static-ness matches.
622615 if (reqASD->isStatic () != witnessASD->isStatic ())
623616 return RequirementMatch (witness, MatchKind::StaticNonStaticConflict);
@@ -701,8 +694,42 @@ RequirementMatch swift::matchWitness(
701694 // If the requirement is @objc, the witness must not be marked with @nonobjc.
702695 // @objc-ness will be inferred (separately) and the selector will be checked
703696 // later.
704- if (req->isObjC () && witness->getAttrs ().hasAttribute <NonObjCAttr>())
697+ if (req->isObjC () && witness->getAttrs ().hasAttribute <NonObjCAttr>()) {
705698 return RequirementMatch (witness, MatchKind::NonObjC);
699+ }
700+ return std::nullopt ;
701+ }
702+
703+ bool swift::TypeChecker::witnessStructureMatches (ValueDecl *req,
704+ const ValueDecl *witness) {
705+ bool decomposeFunctionType = false ;
706+ bool ignoreReturnType = false ;
707+ Type reqThrownError;
708+ Type witnessThrownError;
709+ return matchWitnessStructureImpl (req, const_cast <ValueDecl *>(witness),
710+ decomposeFunctionType, ignoreReturnType,
711+ reqThrownError,
712+ witnessThrownError) == std::nullopt ;
713+ }
714+
715+ RequirementMatch swift::matchWitness (
716+ DeclContext *dc, ValueDecl *req, ValueDecl *witness,
717+ llvm::function_ref<
718+ std::tuple<std::optional<RequirementMatch>, Type, Type>(void )>
719+ setup,
720+ llvm::function_ref<std::optional<RequirementMatch>(Type, Type)> matchTypes,
721+ llvm::function_ref<RequirementMatch(bool , ArrayRef<OptionalAdjustment>)>
722+ finalize) {
723+ bool decomposeFunctionType = false ;
724+ bool ignoreReturnType = false ;
725+ Type reqThrownError;
726+ Type witnessThrownError;
727+
728+ if (auto StructuralMismatch = matchWitnessStructureImpl (
729+ req, witness, decomposeFunctionType, ignoreReturnType, reqThrownError,
730+ witnessThrownError)) {
731+ return *StructuralMismatch;
732+ }
706733
707734 // Set up the match, determining the requirement and witness types
708735 // in the process.
0 commit comments