Skip to content

Commit d083c66

Browse files
committed
[ConstraintSystem] Before matching tuple types, add each complete tuple
type to the locator. This will provide context for tuple element mismatch diagnostics, instead of attempting to compute the full tuple type in diagnostics code with a pile of special cases (see getStructuralTypeContext in CSFix.cpp).
1 parent 939a861 commit d083c66

File tree

4 files changed

+29
-18
lines changed

4 files changed

+29
-18
lines changed

lib/Sema/CSDiagnostics.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3177,7 +3177,7 @@ bool TupleContextualFailure::diagnoseAsError() {
31773177
auto purpose = getContextualTypePurpose();
31783178
if (isNumElementsMismatch())
31793179
diagnostic = diag::tuple_types_not_convertible_nelts;
3180-
else if ((purpose == CTP_Initialization) && !getContextualType(getAnchor()))
3180+
else if (purpose == CTP_Unused)
31813181
diagnostic = diag::tuple_types_not_convertible;
31823182
else if (auto diag = getDiagnosticFor(purpose, getToType()))
31833183
diagnostic = *diag;

lib/Sema/CSFix.cpp

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -453,26 +453,19 @@ bool AllowTupleTypeMismatch::coalesceAndDiagnose(
453453
indices.push_back(*tupleFix->Index);
454454
}
455455

456-
auto &cs = getConstraintSystem();
457456
auto *locator = getLocator();
458457
ContextualTypePurpose purpose;
459-
Type fromType;
460-
Type toType;
461-
462-
if (getFromType()->is<TupleType>() && getToType()->is<TupleType>()) {
463-
purpose = cs.getContextualTypePurpose(locator->getAnchor());
464-
fromType = getFromType();
465-
toType = getToType();
466-
} else if (auto contextualTypeInfo =
467-
getStructuralTypeContext(solution, locator)) {
468-
std::tie(purpose, fromType, toType) = *contextualTypeInfo;
458+
if (isExpr<CoerceExpr>(locator->getAnchor())) {
459+
purpose = CTP_CoerceOperand;
460+
} else if (auto *assignExpr = getAsExpr<AssignExpr>(locator->getAnchor())) {
461+
purpose = isa<SubscriptExpr>(assignExpr->getDest()) ? CTP_SubscriptAssignSource
462+
: CTP_AssignSource;
469463
} else {
470-
return false;
464+
auto &cs = getConstraintSystem();
465+
purpose = cs.getContextualTypePurpose(locator->getAnchor());
471466
}
472467

473-
TupleContextualFailure failure(solution, purpose,
474-
fromType->lookThroughAllOptionalTypes(),
475-
toType->lookThroughAllOptionalTypes(),
468+
TupleContextualFailure failure(solution, purpose, getFromType(), getToType(),
476469
indices, locator);
477470
return failure.diagnose(asNote);
478471
}

lib/Sema/CSSimplify.cpp

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1547,6 +1547,9 @@ ConstraintSystem::matchTupleTypes(TupleType *tuple1, TupleType *tuple2,
15471547
SmallVector<LocatorPathElt, 4> path;
15481548
(void)locator.getLocatorParts(path);
15491549

1550+
while (!path.empty() && path.back().is<LocatorPathElt::TupleType>())
1551+
path.pop_back();
1552+
15501553
if (!path.empty()) {
15511554
// Direct pattern matching between tuple pattern and tuple type.
15521555
if (path.back().is<LocatorPathElt::PatternMatch>()) {
@@ -4723,6 +4726,15 @@ bool ConstraintSystem::repairFailures(
47234726
// mismatches within the same tuple type can be coalesced later.
47244727
auto index = elt.getAs<LocatorPathElt::TupleElement>()->getIndex();
47254728
path.pop_back();
4729+
4730+
// Drop the tuple type path elements too, but extract each tuple type first.
4731+
if (path.back().is<LocatorPathElt::TupleType>()) {
4732+
rhs = path.back().getAs<LocatorPathElt::TupleType>()->getType();
4733+
path.pop_back();
4734+
lhs = path.back().getAs<LocatorPathElt::TupleType>()->getType();
4735+
path.pop_back();
4736+
}
4737+
47264738
auto *tupleLocator = getConstraintLocator(locator.getAnchor(), path);
47274739

47284740
// Let this fail if it's a contextual mismatch with sequence element types,
@@ -5225,9 +5237,15 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
52255237
}
52265238

52275239
case TypeKind::Tuple: {
5240+
// Add each tuple type to the locator before matching the element types.
5241+
// This is useful for diagnostics, because the error message can use the
5242+
// full tuple type for several element mismatches. Use the original types
5243+
// to preserve sugar such as typealiases.
5244+
auto tmpTupleLoc = locator.withPathElement(LocatorPathElt::TupleType(type1));
5245+
auto tupleLoc = tmpTupleLoc.withPathElement(LocatorPathElt::TupleType(type2));
52285246
auto result = matchTupleTypes(cast<TupleType>(desugar1),
52295247
cast<TupleType>(desugar2),
5230-
kind, subflags, locator);
5248+
kind, subflags, tupleLoc);
52315249
if (result != SolutionKind::Error)
52325250
return result;
52335251

test/Constraints/diagnostics.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ func r22263468(_ a : String?) {
573573
// TODO(diagnostics): This is a regression from diagnosing missing optional unwrap for `a`, we have to
574574
// re-think the way errors in tuple elements are detected because it's currently impossible to detect
575575
// exactly what went wrong here and aggregate fixes for different elements at the same time.
576-
_ = MyTuple(42, a) // expected-error {{tuple type 'MyTuple' (aka '(Int, String)') is not convertible to tuple type '(Int, String?)'}}
576+
_ = MyTuple(42, a) // expected-error {{tuple type '(Int, String?)' is not convertible to tuple type 'MyTuple' (aka '(Int, String)')}}
577577
}
578578

579579

0 commit comments

Comments
 (0)