Skip to content

Commit 20443ad

Browse files
authored
Merge pull request #29166 from xedin/port-array-dict-literal-diagnostics
[Diagnostics] Port diagnostics for array/dictionary literals
2 parents 60b4f38 + 83744d9 commit 20443ad

File tree

4 files changed

+24
-122
lines changed

4 files changed

+24
-122
lines changed

docs/TypeChecker.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -992,4 +992,3 @@ The things in the queue yet to be ported are:
992992
- ``diagnoseParameterErrors``
993993
- ``diagnoseSimpleErrors``
994994

995-
- Diagnostics related to array/dictionary literals: ``visit{Array, Dictionary}Expr``.

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -239,8 +239,6 @@ class FailureDiagnosis :public ASTVisitor<FailureDiagnosis, /*exprresult*/bool>{
239239
bool visitTryExpr(TryExpr *E);
240240

241241
bool visitUnresolvedDotExpr(UnresolvedDotExpr *UDE);
242-
bool visitArrayExpr(ArrayExpr *E);
243-
bool visitDictionaryExpr(DictionaryExpr *E);
244242
bool visitObjectLiteralExpr(ObjectLiteralExpr *E);
245243

246244
bool visitApplyExpr(ApplyExpr *AE);
@@ -1724,125 +1722,6 @@ visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E) {
17241722
return false;
17251723
}
17261724

1727-
bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) {
1728-
// If we had a contextual type, then it either conforms to
1729-
// ExpressibleByArrayLiteral or it is an invalid contextual type.
1730-
auto contextualType = CS.getContextualType();
1731-
if (!contextualType) {
1732-
return false;
1733-
}
1734-
1735-
// If our contextual type is an optional, look through them, because we're
1736-
// surely initializing whatever is inside.
1737-
contextualType = contextualType->lookThroughAllOptionalTypes();
1738-
1739-
// Validate that the contextual type conforms to ExpressibleByArrayLiteral and
1740-
// figure out what the contextual element type is in place.
1741-
auto ALC =
1742-
TypeChecker::getProtocol(CS.getASTContext(), E->getLoc(),
1743-
KnownProtocolKind::ExpressibleByArrayLiteral);
1744-
if (!ALC)
1745-
return visitExpr(E);
1746-
1747-
// Check to see if the contextual type conforms.
1748-
auto Conformance = TypeChecker::conformsToProtocol(
1749-
contextualType, ALC, CS.DC, ConformanceCheckFlags::InExpression);
1750-
if (Conformance) {
1751-
Type contextualElementType =
1752-
Conformance
1753-
.getTypeWitnessByName(contextualType,
1754-
CS.getASTContext().Id_ArrayLiteralElement)
1755-
->getDesugaredType();
1756-
1757-
// Type check each of the subexpressions in place, passing down the contextual
1758-
// type information if we have it.
1759-
for (auto elt : E->getElements()) {
1760-
if (typeCheckChildIndependently(elt, contextualElementType,
1761-
CTP_ArrayElement) == nullptr) {
1762-
return true;
1763-
}
1764-
}
1765-
1766-
return false;
1767-
}
1768-
1769-
ContextualFailure failure(CS, CS.getType(E), contextualType,
1770-
CS.getConstraintLocator(E));
1771-
if (failure.diagnoseConversionToDictionary())
1772-
return true;
1773-
1774-
// If that didn't turn up an issue, then we don't know what to do.
1775-
// TODO: When a contextual type is missing, we could try to diagnose cases
1776-
// where the element types mismatch... but theoretically they should type
1777-
// unify to Any, so that could never happen?
1778-
return false;
1779-
}
1780-
1781-
bool FailureDiagnosis::visitDictionaryExpr(DictionaryExpr *E) {
1782-
Type contextualKeyType, contextualValueType;
1783-
auto keyTypePurpose = CTP_Unused, valueTypePurpose = CTP_Unused;
1784-
1785-
// If we had a contextual type, then it either conforms to
1786-
// ExpressibleByDictionaryLiteral or it is an invalid contextual type.
1787-
if (auto contextualType = CS.getContextualType()) {
1788-
// If our contextual type is an optional, look through them, because we're
1789-
// surely initializing whatever is inside.
1790-
contextualType = contextualType->lookThroughAllOptionalTypes();
1791-
1792-
auto DLC = TypeChecker::getProtocol(
1793-
CS.getASTContext(), E->getLoc(),
1794-
KnownProtocolKind::ExpressibleByDictionaryLiteral);
1795-
if (!DLC) return visitExpr(E);
1796-
1797-
// Validate the contextual type conforms to ExpressibleByDictionaryLiteral
1798-
// and figure out what the contextual Key/Value types are in place.
1799-
auto Conformance = TypeChecker::conformsToProtocol(
1800-
contextualType, DLC, CS.DC, ConformanceCheckFlags::InExpression);
1801-
if (Conformance.isInvalid()) {
1802-
diagnose(E->getStartLoc(), diag::type_is_not_dictionary, contextualType)
1803-
.highlight(E->getSourceRange());
1804-
return true;
1805-
}
1806-
1807-
contextualKeyType =
1808-
Conformance
1809-
.getTypeWitnessByName(contextualType, CS.getASTContext().Id_Key)
1810-
->getDesugaredType();
1811-
1812-
contextualValueType =
1813-
Conformance
1814-
.getTypeWitnessByName(contextualType, CS.getASTContext().Id_Value)
1815-
->getDesugaredType();
1816-
1817-
assert(contextualKeyType && contextualValueType &&
1818-
"Could not find Key/Value DictionaryLiteral associated types from"
1819-
" contextual type conformance");
1820-
1821-
keyTypePurpose = CTP_DictionaryKey;
1822-
valueTypePurpose = CTP_DictionaryValue;
1823-
}
1824-
1825-
// Type check each of the subexpressions in place, passing down the contextual
1826-
// type information if we have it.
1827-
for (auto elt : E->getElements()) {
1828-
auto TE = dyn_cast<TupleExpr>(elt);
1829-
if (!TE || TE->getNumElements() != 2) continue;
1830-
1831-
if (!typeCheckChildIndependently(TE->getElement(0),
1832-
contextualKeyType, keyTypePurpose))
1833-
return true;
1834-
if (!typeCheckChildIndependently(TE->getElement(1),
1835-
contextualValueType, valueTypePurpose))
1836-
return true;
1837-
}
1838-
1839-
// If that didn't turn up an issue, then we don't know what to do.
1840-
// TODO: When a contextual type is missing, we could try to diagnose cases
1841-
// where the element types mismatch. There is no Any equivalent since they
1842-
// keys need to be hashable.
1843-
return false;
1844-
}
1845-
18461725
/// When an object literal fails to typecheck because its protocol's
18471726
/// corresponding default type has not been set in the global namespace (e.g.
18481727
/// _ColorLiteralType), suggest that the user import the appropriate module for

lib/Sema/CSDiagnostics.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -670,6 +670,19 @@ bool GenericArgumentsMismatchFailure::diagnoseAsError() {
670670
break;
671671
}
672672

673+
case ConstraintLocator::TupleElement: {
674+
auto *anchor = getRawAnchor();
675+
676+
if (isa<ArrayExpr>(anchor)) {
677+
diagnostic = getDiagnosticFor(CTP_ArrayElement);
678+
} else if (isa<DictionaryExpr>(anchor)) {
679+
auto eltLoc = last.castTo<LocatorPathElt::TupleElement>();
680+
diagnostic = getDiagnosticFor(
681+
eltLoc.getIndex() == 0 ? CTP_DictionaryKey : CTP_DictionaryValue);
682+
}
683+
break;
684+
}
685+
673686
default:
674687
return false;
675688
}

test/Constraints/generics.swift

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -835,3 +835,14 @@ func sr_11491(_ value: [String]) {
835835
arr.insert(value)
836836
// expected-error@-1 {{cannot convert value of type '[String]' to expected argument type 'String'}}
837837
}
838+
839+
func test_dictionary_with_generic_mismatch_in_key_or_value() {
840+
struct S<T> : Hashable {}
841+
// expected-note@-1 2 {{arguments to generic parameter 'T' ('Int' and 'Bool') are expected to be equal}}
842+
843+
let _: [Int: S<Bool>] = [0: S<Bool>(), 1: S<Int>()]
844+
// expected-error@-1 {{cannot convert value of type 'S<Int>' to expected dictionary value type 'S<Bool>'}}
845+
846+
let _: [S<Bool>: Int] = [S<Int>(): 42]
847+
// expected-error@-1 {{cannot convert value of type 'S<Int>' to expected dictionary key type 'S<Bool>'}}
848+
}

0 commit comments

Comments
 (0)