@@ -1060,6 +1060,23 @@ bool WitnessChecker::findBestWitness(
1060
1060
}
1061
1061
1062
1062
if (numViable == 0 ) {
1063
+ // Assume any missing value witnesses for a conformance in a textual
1064
+ // interface can be treated as opaque.
1065
+ // FIXME: ...but we should do something better about types.
1066
+ if (conformance && !conformance->isInvalid ()) {
1067
+ if (auto *SF = DC->getParentSourceFile ()) {
1068
+ if (SF->Kind == SourceFileKind::Interface) {
1069
+ auto match = matchWitness (TC, ReqEnvironmentCache, Proto,
1070
+ conformance, DC, requirement, requirement);
1071
+ assert (match.isViable ());
1072
+ numViable = 1 ;
1073
+ bestIdx = matches.size ();
1074
+ matches.push_back (std::move (match));
1075
+ return true ;
1076
+ }
1077
+ }
1078
+ }
1079
+
1063
1080
if (anyFromUnconstrainedExtension &&
1064
1081
conformance != nullptr &&
1065
1082
conformance->isInvalid ()) {
@@ -4598,8 +4615,9 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
4598
4615
currentDecl = cast<NominalTypeDecl>(dc);
4599
4616
}
4600
4617
4618
+ SourceFile *SF = dc->getParentSourceFile ();
4601
4619
ReferencedNameTracker *tracker = nullptr ;
4602
- if (SourceFile *SF = dc-> getParentSourceFile () )
4620
+ if (SF )
4603
4621
tracker = SF->getReferencedNameTracker ();
4604
4622
4605
4623
// Check each of the conformances associated with this context.
@@ -4804,85 +4822,88 @@ void TypeChecker::checkConformancesInContext(DeclContext *dc,
4804
4822
// If there were any unsatisfied requirements, check whether there
4805
4823
// are any near-matches we should diagnose.
4806
4824
if (!unsatisfiedReqs.empty () && !anyInvalid) {
4807
- // Find all of the members that aren't used to satisfy
4808
- // requirements, and check whether they are close to an
4809
- // unsatisfied or defaulted requirement.
4810
- for (auto member : idc->getMembers ()) {
4811
- // Filter out anything that couldn't satisfy one of the
4812
- // requirements or was used to satisfy a different requirement.
4813
- auto value = dyn_cast<ValueDecl>(member);
4814
- if (!value) continue ;
4815
- if (isa<TypeDecl>(value)) continue ;
4816
- if (!value->getFullName ()) continue ;
4817
-
4818
- // If this declaration overrides another declaration, the signature is
4819
- // fixed; don't complain about near misses.
4820
- if (value->getOverriddenDecl ()) continue ;
4821
-
4822
- // If this member is a witness to any @objc requirement, ignore it.
4823
- if (!findWitnessedObjCRequirements (value, /* anySingleRequirement=*/ true )
4824
- .empty ())
4825
- continue ;
4825
+ if (SF && SF->Kind != SourceFileKind::Interface) {
4826
+ // Find all of the members that aren't used to satisfy
4827
+ // requirements, and check whether they are close to an
4828
+ // unsatisfied or defaulted requirement.
4829
+ for (auto member : idc->getMembers ()) {
4830
+ // Filter out anything that couldn't satisfy one of the
4831
+ // requirements or was used to satisfy a different requirement.
4832
+ auto value = dyn_cast<ValueDecl>(member);
4833
+ if (!value) continue ;
4834
+ if (isa<TypeDecl>(value)) continue ;
4835
+ if (!value->getFullName ()) continue ;
4826
4836
4827
- // Find the unsatisfied requirements with the nearest-matching
4828
- // names.
4829
- SmallVector<ValueDecl *, 4 > bestOptionalReqs;
4830
- unsigned bestScore = UINT_MAX;
4831
- for (auto req : unsatisfiedReqs) {
4832
- // Skip unavailable requirements.
4833
- if (req->getAttrs ().isUnavailable (Context)) continue ;
4834
-
4835
- // Score this particular optional requirement.
4836
- auto score = scorePotentiallyMatching (*this , req, value, bestScore);
4837
- if (!score) continue ;
4838
-
4839
- // If the score is better than the best we've seen, update the best
4840
- // and clear out the list.
4841
- if (*score < bestScore) {
4842
- bestOptionalReqs.clear ();
4843
- bestScore = *score;
4844
- }
4837
+ // If this declaration overrides another declaration, the signature is
4838
+ // fixed; don't complain about near misses.
4839
+ if (value->getOverriddenDecl ()) continue ;
4845
4840
4846
- // If this score matches the (possible new) best score, record it.
4847
- if (*score == bestScore )
4848
- bestOptionalReqs. push_back (req);
4849
- }
4841
+ // If this member is a witness to any @objc requirement, ignore it.
4842
+ if (! findWitnessedObjCRequirements (value, /* anySingleRequirement= */ true )
4843
+ . empty ())
4844
+ continue ;
4850
4845
4851
- // If we found some requirements with nearly-matching names, diagnose
4852
- // the first one.
4853
- if (bestScore < UINT_MAX) {
4854
- bestOptionalReqs.erase (
4855
- std::remove_if (
4856
- bestOptionalReqs.begin (),
4857
- bestOptionalReqs.end (),
4858
- [&](ValueDecl *req) {
4859
- return !shouldWarnAboutPotentialWitness (groupChecker, req, value,
4860
- defaultAccess, bestScore);
4861
- }),
4862
- bestOptionalReqs.end ());
4863
- }
4846
+ // Find the unsatisfied requirements with the nearest-matching
4847
+ // names.
4848
+ SmallVector<ValueDecl *, 4 > bestOptionalReqs;
4849
+ unsigned bestScore = UINT_MAX;
4850
+ for (auto req : unsatisfiedReqs) {
4851
+ // Skip unavailable requirements.
4852
+ if (req->getAttrs ().isUnavailable (Context)) continue ;
4853
+
4854
+ // Score this particular optional requirement.
4855
+ auto score = scorePotentiallyMatching (*this , req, value, bestScore);
4856
+ if (!score) continue ;
4857
+
4858
+ // If the score is better than the best we've seen, update the best
4859
+ // and clear out the list.
4860
+ if (*score < bestScore) {
4861
+ bestOptionalReqs.clear ();
4862
+ bestScore = *score;
4863
+ }
4864
4864
4865
- // If we have something to complain about, do so.
4866
- if (!bestOptionalReqs.empty ()) {
4867
- auto req = bestOptionalReqs[0 ];
4868
- bool diagnosed = false ;
4869
- for (auto conformance : conformances) {
4870
- if (conformance->getProtocol () == req->getDeclContext ()) {
4871
- diagnosePotentialWitness (*this ,
4872
- conformance->getRootNormalConformance (),
4873
- req, value, defaultAccess);
4874
- diagnosed = true ;
4875
- break ;
4865
+ // If this score matches the (possible new) best score, record it.
4866
+ if (*score == bestScore)
4867
+ bestOptionalReqs.push_back (req);
4868
+ }
4869
+
4870
+ // If we found some requirements with nearly-matching names, diagnose
4871
+ // the first one.
4872
+ if (bestScore < UINT_MAX) {
4873
+ bestOptionalReqs.erase (
4874
+ std::remove_if (
4875
+ bestOptionalReqs.begin (),
4876
+ bestOptionalReqs.end (),
4877
+ [&](ValueDecl *req) {
4878
+ return !shouldWarnAboutPotentialWitness (groupChecker, req,
4879
+ value, defaultAccess,
4880
+ bestScore);
4881
+ }),
4882
+ bestOptionalReqs.end ());
4883
+ }
4884
+
4885
+ // If we have something to complain about, do so.
4886
+ if (!bestOptionalReqs.empty ()) {
4887
+ auto req = bestOptionalReqs[0 ];
4888
+ bool diagnosed = false ;
4889
+ for (auto conformance : conformances) {
4890
+ if (conformance->getProtocol () == req->getDeclContext ()) {
4891
+ diagnosePotentialWitness (*this ,
4892
+ conformance->getRootNormalConformance (),
4893
+ req, value, defaultAccess);
4894
+ diagnosed = true ;
4895
+ break ;
4896
+ }
4876
4897
}
4898
+ assert (diagnosed && " Failed to find conformance to diagnose?" );
4899
+ (void )diagnosed;
4900
+
4901
+ // Remove this requirement from the list. We don't want to
4902
+ // complain about it twice.
4903
+ unsatisfiedReqs.erase (std::find (unsatisfiedReqs.begin (),
4904
+ unsatisfiedReqs.end (),
4905
+ req));
4877
4906
}
4878
- assert (diagnosed && " Failed to find conformance to diagnose?" );
4879
- (void )diagnosed;
4880
-
4881
- // Remove this requirement from the list. We don't want to
4882
- // complain about it twice.
4883
- unsatisfiedReqs.erase (std::find (unsatisfiedReqs.begin (),
4884
- unsatisfiedReqs.end (),
4885
- req));
4886
4907
}
4887
4908
}
4888
4909
0 commit comments