Skip to content

Commit 0fa9ec3

Browse files
committed
Diagnostics: Changed tuple mismatch fix constraint generation to use matchTupleTypes
1 parent a3b56c2 commit 0fa9ec3

File tree

5 files changed

+48
-34
lines changed

5 files changed

+48
-34
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1149,8 +1149,7 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
11491149
if (fromTT->getNumElements() != toTT->getNumElements()) {
11501150
auto failure = TupleContextualFailure(anchor, CS, fromTT, toTT,
11511151
CS.getConstraintLocator(expr));
1152-
failure.diagnoseAsError();
1153-
return true;
1152+
return failure.diagnoseAsError();
11541153
}
11551154

11561155
SmallVector<TupleTypeElt, 4> FromElts;
@@ -1168,8 +1167,7 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){
11681167
toTT->getElements(), sources)) {
11691168
auto failure = TupleContextualFailure(anchor, CS, fromTT, toTT,
11701169
CS.getConstraintLocator(expr));
1171-
failure.diagnoseAsError();
1172-
return true;
1170+
return failure.diagnoseAsError();
11731171
}
11741172
}
11751173

lib/Sema/CSDiagnostics.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -769,10 +769,10 @@ class TupleContextualFailure final : public ContextualFailure {
769769
bool diagnoseAsError() override;
770770

771771
bool isNumElementsMismatch() const {
772-
auto lhsTy = dyn_cast<TupleType>(getFromType().getPointer());
773-
auto rhsTy = dyn_cast<TupleType>(getToType().getPointer());
772+
auto lhsTy = getFromType()->castTo<TupleType>();
773+
auto rhsTy = getToType()->castTo<TupleType>();
774774
assert(lhsTy && rhsTy);
775-
return lhsTy->getElements().size() != rhsTy->getElements().size();
775+
return lhsTy->getNumElements() != rhsTy->getNumElements();
776776
}
777777
};
778778

lib/Sema/CSFix.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -230,14 +230,16 @@ ContextualMismatch *ContextualMismatch::create(ConstraintSystem &cs, Type lhs,
230230
}
231231

232232
bool AllowTupleTypeMismatch::diagnose(Expr *root, bool asNote) const {
233-
auto failure = TupleContextualFailure(root, getConstraintSystem(), LHS, RHS,
234-
getLocator());
233+
auto failure = TupleContextualFailure(
234+
root, getConstraintSystem(), getFromType(), getToType(), getLocator());
235235
return failure.diagnose(asNote);
236236
}
237237

238238
AllowTupleTypeMismatch *
239239
AllowTupleTypeMismatch::create(ConstraintSystem &cs, Type lhs, Type rhs,
240240
ConstraintLocator *locator) {
241+
assert(lhs->is<TupleType>() && rhs->is<TupleType>() &&
242+
"lhs and rhs must be tuple types");
241243
return new (cs.getAllocator()) AllowTupleTypeMismatch(cs, lhs, rhs, locator);
242244
}
243245

lib/Sema/CSFix.h

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,8 @@ enum class FixKind : uint8_t {
136136
/// referenced constructor must be required.
137137
AllowInvalidInitRef,
138138

139-
/// Allow a tuple to be destructured with a mismatched number of
140-
/// elements, or mismatched types.
139+
/// Allow a tuple to be destructured with mismatched arity, or mismatched
140+
/// types.
141141
AllowTupleTypeMismatch,
142142

143143
/// Allow an invalid member access on a value of protocol type as if
@@ -498,6 +498,9 @@ class ContextualMismatch : public ConstraintFix {
498498
ConstraintLocator *locator)
499499
: ConstraintFix(cs, FixKind::ContextualMismatch, locator), LHS(lhs),
500500
RHS(rhs) {}
501+
ContextualMismatch(ConstraintSystem &cs, FixKind kind, Type lhs, Type rhs,
502+
ConstraintLocator *locator)
503+
: ConstraintFix(cs, kind, locator), LHS(lhs), RHS(rhs) {}
501504

502505
public:
503506
std::string getName() const override { return "fix contextual mismatch"; }
@@ -866,20 +869,18 @@ class AllowInvalidInitRef final : public ConstraintFix {
866869
ConstraintLocator *locator);
867870
};
868871

869-
class AllowTupleTypeMismatch final : public ConstraintFix {
870-
Type LHS, RHS;
871-
872+
class AllowTupleTypeMismatch final : public ContextualMismatch {
872873
AllowTupleTypeMismatch(ConstraintSystem &cs, Type lhs, Type rhs,
873874
ConstraintLocator *locator)
874-
: ConstraintFix(cs, FixKind::AllowTupleTypeMismatch, locator), LHS(lhs),
875-
RHS(rhs) {}
875+
: ContextualMismatch(cs, FixKind::AllowTupleTypeMismatch, lhs, rhs,
876+
locator) {}
876877

877878
public:
878879
static AllowTupleTypeMismatch *create(ConstraintSystem &cs, Type lhs,
879880
Type rhs, ConstraintLocator *locator);
880881

881882
std::string getName() const override {
882-
return "allow invalid tuple destructuring";
883+
return "fix tuple mismatches in type and arity";
883884
}
884885

885886
bool diagnose(Expr *root, bool asNote = false) const override;

lib/Sema/CSSimplify.cpp

Lines changed: 30 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6964,29 +6964,42 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyFixConstraint(
69646964
}
69656965

69666966
case FixKind::AllowTupleTypeMismatch: {
6967-
auto lhs = dyn_cast<TupleType>(type1.getPointer());
6968-
auto rhs = dyn_cast<TupleType>(type2.getPointer());
6969-
auto lhsLarger = lhs->getElements().size() >= rhs->getElements().size();
6967+
auto lhs = type1->castTo<TupleType>();
6968+
auto rhs = type2->castTo<TupleType>();
6969+
// Create a new tuple type the size of the smaller tuple with elements
6970+
// from the larger tuple whenever either side contains a type variable.
6971+
// For example (A, $0, B, $2) and (X, Y, $1) produces: (X, $0, B).
6972+
// This allows us to guarentee that the types will match, and all
6973+
// type variables will get bound to something as long as we default
6974+
// excess types in the larger tuple to Any. In the prior example,
6975+
// when the tuples (X, Y, $1) and (X, $0, B) get matched, $0 is equated
6976+
// to Y, $1 is equated to B, and $2 is defaulted to Any.
6977+
auto lhsLarger = lhs->getNumElements() >= rhs->getNumElements();
69706978
auto larger = lhsLarger ? lhs : rhs;
69716979
auto smaller = lhsLarger ? rhs : lhs;
6972-
if (lhs && rhs && getContextualTypePurpose() == CTP_Initialization) {
6973-
// Match up the tuple type elements, and match any
6974-
for (unsigned i = 0; i < larger->getElements().size(); ++i) {
6975-
auto largerTy = larger->getElement(i).getType();
6976-
if (i < smaller->getElements().size()) {
6977-
auto smallerTy = smaller->getElement(i).getType();
6978-
if (smallerTy->isTypeVariableOrMember() ||
6979-
largerTy->isTypeVariableOrMember())
6980-
addConstraint(ConstraintKind::Bind, largerTy, smallerTy,
6981-
getConstraintLocator(locator));
6982-
} else {
6983-
addConstraint(ConstraintKind::Defaultable, largerTy,
6980+
llvm::SmallVector<TupleTypeElt, 4> newTupleTypes;
6981+
6982+
for (unsigned i = 0; i < larger->getNumElements(); ++i) {
6983+
auto largerElt = larger->getElement(i);
6984+
if (i < smaller->getNumElements()) {
6985+
auto smallerElt = smaller->getElement(i);
6986+
if (largerElt.getType()->isTypeVariableOrMember() ||
6987+
smallerElt.getType()->isTypeVariableOrMember())
6988+
newTupleTypes.push_back(largerElt);
6989+
else
6990+
newTupleTypes.push_back(smallerElt);
6991+
} else {
6992+
if (largerElt.getType()->isTypeVariableOrMember())
6993+
addConstraint(ConstraintKind::Defaultable, largerElt.getType(),
69846994
getASTContext().TheAnyType,
69856995
getConstraintLocator(locator));
6986-
}
69876996
}
69886997
}
6989-
return recordFix(fix) ? SolutionKind::Error : SolutionKind::Solved;
6998+
auto matchingType =
6999+
TupleType::get(newTupleTypes, getASTContext())->castTo<TupleType>();
7000+
if (recordFix(fix))
7001+
return SolutionKind::Error;
7002+
return matchTupleTypes(matchingType, smaller, matchKind, subflags, locator);
69907003
}
69917004

69927005
case FixKind::InsertCall:

0 commit comments

Comments
 (0)