Skip to content

Commit 7435c93

Browse files
authored
Merge pull request #58915 from xedin/multi-statement-closure-improvements
[ConstraintSystem] A couple of improvements to multi-statement closure handling
2 parents 07ffdde + f210442 commit 7435c93

File tree

5 files changed

+68
-19
lines changed

5 files changed

+68
-19
lines changed

lib/Sema/CSClosure.cpp

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -441,7 +441,7 @@ class SyntacticElementConstraintGenerator
441441

442442
cs.addConstraint(
443443
ConstraintKind::Conversion, elementType, initType,
444-
cs.getConstraintLocator(contextualLocator,
444+
cs.getConstraintLocator(sequenceLocator,
445445
ConstraintLocator::SequenceElementType));
446446

447447
// Reference the makeIterator witness.
@@ -450,9 +450,10 @@ class SyntacticElementConstraintGenerator
450450

451451
Type makeIteratorType =
452452
cs.createTypeVariable(locator, TVO_CanBindToNoEscape);
453-
cs.addValueWitnessConstraint(LValueType::get(sequenceType), makeIterator,
454-
makeIteratorType, context.getAsDeclContext(),
455-
FunctionRefKind::Compound, contextualLocator);
453+
cs.addValueWitnessConstraint(
454+
LValueType::get(sequenceType), makeIterator, makeIteratorType,
455+
context.getAsDeclContext(), FunctionRefKind::Compound,
456+
cs.getConstraintLocator(sequenceLocator, ConstraintLocator::Witness));
456457

457458
// After successful constraint generation, let's record
458459
// solution application target with all relevant information.

lib/Sema/CSDiagnostics.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1188,6 +1188,12 @@ class MissingMemberFailure : public InvalidMemberRefFailure {
11881188
: InvalidMemberRefFailure(solution, baseType, memberName, locator) {}
11891189

11901190
SourceLoc getLoc() const override {
1191+
auto *locator = getLocator();
1192+
1193+
if (locator->findLast<LocatorPathElt::SyntacticElement>()) {
1194+
return constraints::getLoc(getAnchor());
1195+
}
1196+
11911197
// Diagnostic should point to the member instead of its base expression.
11921198
return constraints::getLoc(getRawAnchor());
11931199
}

lib/Sema/CSStep.cpp

Lines changed: 31 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -942,13 +942,10 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
942942
// and scoring information.
943943
Snapshot.reset();
944944

945-
// Restore original scores of outer context before
946-
// trying to produce a combined solution.
947-
restoreOriginalScores();
948-
949945
// Apply all of the information deduced from the
950946
// conjunction (up to the point of ambiguity)
951947
// back to the outer context and form a joined solution.
948+
unsigned numSolutions = 0;
952949
for (auto &solution : Solutions) {
953950
ConstraintSystem::SolverScope scope(CS);
954951

@@ -958,24 +955,47 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
958955
// of the constraint system, so they have to be
959956
// restored right afterwards because score of the
960957
// element does contribute to the overall score.
961-
restoreOriginalScores();
958+
restoreBestScore();
959+
restoreCurrentScore(solution.getFixedScore());
960+
961+
// Transform all of the unbound outer variables into
962+
// placeholders since we are not going to solve for
963+
// each ambguous solution.
964+
{
965+
unsigned numHoles = 0;
966+
for (auto *typeVar : CS.getTypeVariables()) {
967+
if (!typeVar->getImpl().hasRepresentativeOrFixed()) {
968+
CS.assignFixedType(
969+
typeVar, PlaceholderType::get(CS.getASTContext(), typeVar));
970+
++numHoles;
971+
}
972+
}
973+
CS.increaseScore(SK_Hole, numHoles);
974+
}
975+
976+
if (CS.worseThanBestSolution())
977+
continue;
962978

963979
// Note that `worseThanBestSolution` isn't checked
964980
// here because `Solutions` were pre-filtered, and
965981
// outer score is the same for all of them.
966982
OuterSolutions.push_back(CS.finalize());
983+
++numSolutions;
967984
}
968985

969-
return done(/*isSuccess=*/true);
986+
return done(/*isSuccess=*/numSolutions > 0);
970987
}
971988

989+
auto solution = Solutions.pop_back_val();
990+
auto score = solution.getFixedScore();
991+
972992
// Restore outer type variables and prepare to solve
973993
// constraints associated with outer context together
974994
// with information deduced from the conjunction.
975-
Snapshot->setupOuterContext(Solutions.pop_back_val());
995+
Snapshot->setupOuterContext(std::move(solution));
976996

977997
// Pretend that conjunction never happened.
978-
restoreOuterState();
998+
restoreOuterState(score);
979999

9801000
// Now that all of the information from the conjunction has
9811001
// been applied, let's attempt to solve the outer scope.
@@ -987,10 +1007,11 @@ StepResult ConjunctionStep::resume(bool prevFailed) {
9871007
return take(prevFailed);
9881008
}
9891009

990-
void ConjunctionStep::restoreOuterState() const {
1010+
void ConjunctionStep::restoreOuterState(const Score &solutionScore) const {
9911011
// Restore best/current score, since upcoming step is going to
9921012
// work with outer scope in relation to the conjunction.
993-
restoreOriginalScores();
1013+
restoreBestScore();
1014+
restoreCurrentScore(solutionScore);
9941015

9951016
// Active all of the previously out-of-scope constraints
9961017
// because conjunction can propagate type information up

lib/Sema/CSStep.h

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,11 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
962962

963963
// Restore best score only if conjunction fails because
964964
// successful outcome should keep a score set by `restoreOuterState`.
965-
if (HadFailure)
966-
restoreOriginalScores();
965+
if (HadFailure) {
966+
auto solutionScore = Score();
967+
restoreBestScore();
968+
restoreCurrentScore(solutionScore);
969+
}
967970

968971
if (OuterTimeRemaining) {
969972
auto anchor = OuterTimeRemaining->first;
@@ -1015,16 +1018,19 @@ class ConjunctionStep : public BindingStep<ConjunctionElementProducer> {
10151018

10161019
private:
10171020
/// Restore best and current scores as they were before conjunction.
1018-
void restoreOriginalScores() const {
1019-
CS.solverState->BestScore = BestScore;
1021+
void restoreCurrentScore(const Score &solutionScore) const {
10201022
CS.CurrentScore = CurrentScore;
1023+
CS.increaseScore(SK_Fix, solutionScore.Data[SK_Fix]);
1024+
CS.increaseScore(SK_Hole, solutionScore.Data[SK_Hole]);
10211025
}
10221026

1027+
void restoreBestScore() const { CS.solverState->BestScore = BestScore; }
1028+
10231029
// Restore constraint system state before conjunction.
10241030
//
10251031
// Note that this doesn't include conjunction constraint
10261032
// itself because we don't want to re-solve it.
1027-
void restoreOuterState() const;
1033+
void restoreOuterState(const Score &solutionScore) const;
10281034
};
10291035

10301036
} // end namespace constraints

test/expr/closure/multi_statement.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,3 +350,18 @@ func test_no_crash_with_circular_ref_due_to_error() {
350350
return 0
351351
}
352352
}
353+
354+
func test_diagnosing_on_missing_member_in_case() {
355+
enum E {
356+
case one
357+
}
358+
359+
func test(_: (E) -> Void) {}
360+
361+
test {
362+
switch $0 {
363+
case .one: break
364+
case .unknown: break // expected-error {{type 'E' has no member 'unknown'}}
365+
}
366+
}
367+
}

0 commit comments

Comments
 (0)