Skip to content

Commit e36011d

Browse files
committed
[Type checker] Delay the diagnosis of missing witnesses further.
The handling of "global" missing witnesses would diagnose a missing witness (showing "almost" matches) and then, later, provide the Fix-It to add the declaration if the user wants it. Delay the diagnostic part until later, when we add the missing witness. While here, correct an existing issue with memory corruption that occurs because we would diagnose some of these witnesses, then clear a "global" witness list, while still iterating through parts of that list.
1 parent 3972a13 commit e36011d

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

lib/Sema/TypeCheckProtocol.cpp

Lines changed: 25 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1607,7 +1607,8 @@ void MultiConformanceChecker::checkAllConformances() {
16071607
for (auto It = AllUsedCheckers.rbegin(); It != AllUsedCheckers.rend();
16081608
++It) {
16091609
if (!It->getLocalMissingWitness().empty()) {
1610-
It->diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::FixItOnly);
1610+
if (It->diagnoseMissingWitnesses(MissingWitnessDiagnosisKind::FixItOnly))
1611+
break;
16111612
}
16121613
}
16131614
}
@@ -3099,13 +3100,30 @@ filterProtocolRequirements(
30993100
return Filtered;
31003101
}
31013102

3102-
void ConformanceChecker::
3103+
bool ConformanceChecker::
31033104
diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind) {
31043105
auto LocalMissing = getLocalMissingWitness();
31053106

31063107
// If this conformance has nothing to complain, return.
31073108
if (LocalMissing.empty())
3108-
return;
3109+
return false;
3110+
3111+
// Diagnose the missing witnesses.
3112+
for (auto &Missing : LocalMissing) {
3113+
auto requirement = Missing.requirement;
3114+
auto matches = Missing.matches;
3115+
auto nominal = Adoptee->getAnyNominal();
3116+
diagnoseOrDefer(requirement, true,
3117+
[requirement, matches, nominal](NormalProtocolConformance *conformance) {
3118+
auto dc = conformance->getDeclContext();
3119+
auto *protocol = conformance->getProtocol();
3120+
// Possibly diagnose reason for automatic derivation failure
3121+
DerivedConformance::tryDiagnoseFailedDerivation(dc, nominal, protocol);
3122+
// Diagnose each of the matches.
3123+
for (const auto &match : matches)
3124+
diagnoseMatch(dc->getParentModule(), conformance, requirement, match);
3125+
});
3126+
}
31093127

31103128
const auto InsertFixit = [](
31113129
NormalProtocolConformance *Conf, SourceLoc ComplainLoc, bool EditorMode,
@@ -3226,19 +3244,19 @@ diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind) {
32263244
});
32273245
}
32283246
clearGlobalMissingWitnesses();
3229-
return;
3247+
return true;
32303248
}
32313249
case MissingWitnessDiagnosisKind::ErrorOnly: {
32323250
diagnoseOrDefer(
32333251
LocalMissing[0].requirement, true, [](NormalProtocolConformance *) {});
3234-
return;
3252+
return true;
32353253
}
32363254
case MissingWitnessDiagnosisKind::FixItOnly:
32373255
InsertFixit(Conformance, Loc, IsEditorMode,
32383256
filterProtocolRequirements(GlobalMissingWitnesses.getArrayRef(),
32393257
Adoptee));
32403258
clearGlobalMissingWitnesses();
3241-
return;
3259+
return true;
32423260
}
32433261
}
32443262

@@ -3744,17 +3762,7 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) {
37443762
if (!numViable) {
37453763
// Save the missing requirement for later diagnosis.
37463764
GlobalMissingWitnesses.insert({requirement, matches});
3747-
diagnoseOrDefer(requirement, true,
3748-
[requirement, matches, nominal](NormalProtocolConformance *conformance) {
3749-
auto dc = conformance->getDeclContext();
3750-
auto *protocol = conformance->getProtocol();
3751-
// Possibly diagnose reason for automatic derivation failure
3752-
DerivedConformance::tryDiagnoseFailedDerivation(dc, nominal, protocol);
3753-
// Diagnose each of the matches.
3754-
for (const auto &match : matches)
3755-
diagnoseMatch(dc->getParentModule(), conformance, requirement, match);
3756-
});
3757-
return ResolveWitnessResult::ExplicitFailed;
3765+
return ResolveWitnessResult::Missing;
37583766
}
37593767

37603768
diagnoseOrDefer(requirement, true,

lib/Sema/TypeCheckProtocol.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,10 @@ class ConformanceChecker : public WitnessChecker {
789789

790790
public:
791791
/// Call this to diagnose currently known missing witnesses.
792-
void diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind);
792+
///
793+
/// \returns true if any witnesses were diagnosed.
794+
bool diagnoseMissingWitnesses(MissingWitnessDiagnosisKind Kind);
795+
793796
/// Emit any diagnostics that have been delayed.
794797
void emitDelayedDiags();
795798

0 commit comments

Comments
 (0)