Skip to content

Commit 0fcdf3b

Browse files
committed
---
yaml --- r: 349448 b: refs/heads/master-next c: e2b9754 h: refs/heads/master
1 parent bab91bc commit 0fcdf3b

File tree

10 files changed

+220
-132
lines changed

10 files changed

+220
-132
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
---
22
refs/heads/master: 3574c513bbc5578dd9346b4ea9ab5995c5927bb5
3-
refs/heads/master-next: 3869e829fa4d1762a0b4f24b9ce456eb7ed9e8bc
3+
refs/heads/master-next: e2b9754e5a3086e33fc4c6235afea7fc26740167
44
refs/tags/osx-passed: b6b74147ef8a386f532cf9357a1bde006e552c54
55
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-a: 6bb18e013c2284f2b45f5f84f2df2887dc0f7dea
66
refs/tags/swift-2.2-SNAPSHOT-2015-12-01-b: 66d897bfcf64a82cb9a87f5e663d889189d06d07

branches/master-next/lib/Sema/CSDiag.cpp

Lines changed: 16 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -1677,73 +1677,29 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
16771677
return failure.diagnose();
16781678
}
16791679

1680-
// Try to find the contextual type in a variety of ways. If the constraint
1681-
// system had a contextual type specified, we use it - it will have a purpose
1682-
// indicator which allows us to give a very "to the point" diagnostic.
1683-
Diag<Type> nilDiag;
1684-
std::function<void(void)> nilFollowup;
1680+
// If we don't have a type for the expression, then we cannot use it in
1681+
// conversion constraint diagnostic generation. If the types match, then it
1682+
// must not be the contextual type that is the problem.
1683+
if (isUnresolvedOrTypeVarType(exprType) || exprType->isEqual(contextualType))
1684+
return false;
16851685

16861686
// If this is conversion failure due to a return statement with an argument
16871687
// that cannot be coerced to the result type of the function, emit a
16881688
// specific error.
1689-
switch (CTP) {
1690-
case CTP_Unused:
1691-
case CTP_CannotFail:
1692-
llvm_unreachable("These contextual type purposes cannot fail with a "
1693-
"conversion type specified!");
1694-
case CTP_CalleeResult:
1695-
llvm_unreachable("CTP_CalleeResult does not actually install a "
1696-
"contextual type");
1697-
case CTP_Initialization:
1698-
nilDiag = diag::cannot_convert_initializer_value_nil;
1699-
nilFollowup = [this] {
1700-
TypeRepr *patternTR = CS.getContextualTypeLoc().getTypeRepr();
1701-
if (!patternTR)
1702-
return;
1703-
auto diag = diagnose(patternTR->getLoc(), diag::note_make_optional,
1704-
OptionalType::get(CS.getContextualType()));
1705-
if (patternTR->isSimple()) {
1706-
diag.fixItInsertAfter(patternTR->getEndLoc(), "?");
1707-
} else {
1708-
diag.fixItInsert(patternTR->getStartLoc(), "(");
1709-
diag.fixItInsertAfter(patternTR->getEndLoc(), ")?");
1710-
}
1711-
};
1712-
break;
1713-
case CTP_ReturnSingleExpr:
1714-
case CTP_ReturnStmt:
1715-
// Special case the "conversion to void" case.
1716-
if (contextualType->isVoid()) {
1717-
diagnose(expr->getLoc(), diag::cannot_return_value_from_void_func)
1718-
.highlight(expr->getSourceRange());
1719-
return true;
1720-
}
1721-
1722-
nilDiag = diag::cannot_convert_to_return_type_nil;
1723-
break;
1724-
case CTP_ThrowStmt: {
1725-
if (isa<NilLiteralExpr>(expr->getValueProvidingExpr())) {
1726-
diagnose(expr->getLoc(), diag::cannot_throw_nil);
1727-
return true;
1728-
}
1729-
1730-
if (isUnresolvedOrTypeVarType(exprType) ||
1731-
exprType->isEqual(contextualType))
1732-
return false;
1733-
1689+
if (CTP == CTP_ThrowStmt) {
17341690
// If we tried to throw the error code of an error type, suggest object
17351691
// construction.
17361692
auto &TC = CS.getTypeChecker();
17371693
if (auto errorCodeProtocol =
17381694
TC.Context.getProtocol(KnownProtocolKind::ErrorCodeProtocol)) {
1739-
if (auto conformance =
1740-
TypeChecker::conformsToProtocol(CS.getType(expr), errorCodeProtocol, CS.DC,
1741-
ConformanceCheckFlags::InExpression)) {
1695+
if (auto conformance = TypeChecker::conformsToProtocol(
1696+
CS.getType(expr), errorCodeProtocol, CS.DC,
1697+
ConformanceCheckFlags::InExpression)) {
17421698
Type errorCodeType = CS.getType(expr);
17431699
Type errorType =
1744-
conformance->getTypeWitnessByName(errorCodeType,
1745-
TC.Context.Id_ErrorType)
1746-
->getCanonicalType();
1700+
conformance
1701+
->getTypeWitnessByName(errorCodeType, TC.Context.Id_ErrorType)
1702+
->getCanonicalType();
17471703
if (errorType) {
17481704
auto diag = diagnose(expr->getLoc(), diag::cannot_throw_error_code,
17491705
errorCodeType, errorType);
@@ -1760,18 +1716,11 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
17601716
// if this ever expands, this should be a specific form like () is for
17611717
// return.
17621718
diagnose(expr->getLoc(), diag::cannot_convert_thrown_type, exprType)
1763-
.highlight(expr->getSourceRange());
1719+
.highlight(expr->getSourceRange());
17641720
return true;
17651721
}
17661722

1767-
case CTP_EnumCaseRawValue:
1768-
nilDiag = diag::cannot_convert_raw_initializer_value_nil;
1769-
break;
1770-
case CTP_DefaultParameter:
1771-
nilDiag = diag::cannot_convert_default_arg_value_nil;
1772-
break;
1773-
1774-
case CTP_YieldByReference:
1723+
if (CTP == CTP_YieldByReference) {
17751724
if (auto contextualLV = contextualType->getAs<LValueType>())
17761725
contextualType = contextualLV->getObjectType();
17771726
if (auto exprLV = exprType->getAs<LValueType>()) {
@@ -1781,58 +1730,10 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
17811730
diagnose(expr->getLoc(), diag::cannot_yield_rvalue_by_reference_same_type,
17821731
exprType);
17831732
} else {
1784-
diagnose(expr->getLoc(), diag::cannot_yield_rvalue_by_reference,
1785-
exprType, contextualType);
1733+
diagnose(expr->getLoc(), diag::cannot_yield_rvalue_by_reference, exprType,
1734+
contextualType);
17861735
}
17871736
return true;
1788-
case CTP_YieldByValue:
1789-
nilDiag = diag::cannot_convert_yield_value_nil;
1790-
break;
1791-
case CTP_CallArgument:
1792-
nilDiag = diag::cannot_convert_argument_value_nil;
1793-
break;
1794-
case CTP_ClosureResult:
1795-
nilDiag = diag::cannot_convert_closure_result_nil;
1796-
break;
1797-
case CTP_ArrayElement:
1798-
nilDiag = diag::cannot_convert_array_element_nil;
1799-
break;
1800-
case CTP_DictionaryKey:
1801-
nilDiag = diag::cannot_convert_dict_key_nil;
1802-
break;
1803-
case CTP_DictionaryValue:
1804-
nilDiag = diag::cannot_convert_dict_value_nil;
1805-
break;
1806-
case CTP_CoerceOperand:
1807-
nilDiag = diag::cannot_convert_coerce_nil;
1808-
break;
1809-
case CTP_AssignSource:
1810-
nilDiag = diag::cannot_convert_assign_nil;
1811-
break;
1812-
case CTP_SubscriptAssignSource:
1813-
nilDiag = diag::cannot_convert_subscript_assign_nil;
1814-
break;
1815-
}
1816-
1817-
// If we're diagnostic an issue with 'nil', produce a specific diagnostic,
1818-
// instead of uttering ExpressibleByNilLiteral.
1819-
if (isa<NilLiteralExpr>(expr->getValueProvidingExpr())) {
1820-
// If the source type is some kind of optional, the contextual conversion
1821-
// to 'nil' didn't fail, something else did.
1822-
if (contextualType->getOptionalObjectType())
1823-
return false;
1824-
diagnose(expr->getLoc(), nilDiag, contextualType);
1825-
if (nilFollowup)
1826-
nilFollowup();
1827-
return true;
1828-
}
1829-
1830-
// If we don't have a type for the expression, then we cannot use it in
1831-
// conversion constraint diagnostic generation. If the types match, then it
1832-
// must not be the contextual type that is the problem.
1833-
if (isUnresolvedOrTypeVarType(exprType) ||
1834-
exprType->isEqual(contextualType)) {
1835-
return false;
18361737
}
18371738

18381739
exprType = exprType->getRValueType();

branches/master-next/lib/Sema/CSDiagnostics.cpp

Lines changed: 165 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1841,6 +1841,18 @@ bool ContextualFailure::diagnoseAsError() {
18411841
auto *anchor = getAnchor();
18421842
auto path = getLocator()->getPath();
18431843

1844+
if (CTP == CTP_ReturnSingleExpr || CTP == CTP_ReturnStmt) {
1845+
// Special case the "conversion to void".
1846+
if (getToType()->isVoid()) {
1847+
emitDiagnostic(anchor->getLoc(), diag::cannot_return_value_from_void_func)
1848+
.highlight(anchor->getSourceRange());
1849+
return true;
1850+
}
1851+
}
1852+
1853+
if (diagnoseConversionToNil())
1854+
return true;
1855+
18441856
assert(!path.empty());
18451857

18461858
if (diagnoseMissingFunctionCall())
@@ -1889,6 +1901,159 @@ bool ContextualFailure::diagnoseAsError() {
18891901
return true;
18901902
}
18911903

1904+
static Optional<Diag<Type>>
1905+
getContextualNilDiagnostic(ContextualTypePurpose CTP) {
1906+
switch (CTP) {
1907+
case CTP_Unused:
1908+
case CTP_CannotFail:
1909+
llvm_unreachable("These contextual type purposes cannot fail with a "
1910+
"conversion type specified!");
1911+
case CTP_CalleeResult:
1912+
llvm_unreachable("CTP_CalleeResult does not actually install a "
1913+
"contextual type");
1914+
case CTP_Initialization:
1915+
return diag::cannot_convert_initializer_value_nil;
1916+
1917+
case CTP_ReturnSingleExpr:
1918+
case CTP_ReturnStmt:
1919+
return diag::cannot_convert_to_return_type_nil;
1920+
1921+
case CTP_ThrowStmt:
1922+
case CTP_YieldByReference:
1923+
return None;
1924+
1925+
case CTP_EnumCaseRawValue:
1926+
return diag::cannot_convert_raw_initializer_value_nil;
1927+
case CTP_DefaultParameter:
1928+
return diag::cannot_convert_default_arg_value_nil;
1929+
case CTP_YieldByValue:
1930+
return diag::cannot_convert_yield_value_nil;
1931+
case CTP_CallArgument:
1932+
return diag::cannot_convert_argument_value_nil;
1933+
case CTP_ClosureResult:
1934+
return diag::cannot_convert_closure_result_nil;
1935+
case CTP_ArrayElement:
1936+
return diag::cannot_convert_array_element_nil;
1937+
case CTP_DictionaryKey:
1938+
return diag::cannot_convert_dict_key_nil;
1939+
case CTP_DictionaryValue:
1940+
return diag::cannot_convert_dict_value_nil;
1941+
case CTP_CoerceOperand:
1942+
return diag::cannot_convert_coerce_nil;
1943+
case CTP_AssignSource:
1944+
return diag::cannot_convert_assign_nil;
1945+
case CTP_SubscriptAssignSource:
1946+
return diag::cannot_convert_subscript_assign_nil;
1947+
}
1948+
}
1949+
1950+
bool ContextualFailure::diagnoseConversionToNil() const {
1951+
auto *anchor = getAnchor();
1952+
1953+
if (!isa<NilLiteralExpr>(anchor))
1954+
return false;
1955+
1956+
auto &cs = getConstraintSystem();
1957+
auto *locator = getLocator();
1958+
1959+
Optional<ContextualTypePurpose> CTP;
1960+
// Easy case were failure has been identified as contextual already.
1961+
if (locator->isLastElement(ConstraintLocator::ContextualType)) {
1962+
CTP = getContextualTypePurpose();
1963+
} else {
1964+
// Here we need to figure out where where `nil` is located.
1965+
// It could be e.g. an argument to a subscript/call, assignment
1966+
// source like `s[0] = nil` or an array element like `[nil]` or
1967+
// `[nil: 42]` as a sub-expression to a larger one.
1968+
auto *parentExpr = findParentExpr(anchor);
1969+
1970+
// Looks like it's something similar to `let _ = nil`.
1971+
if (!parentExpr) {
1972+
emitDiagnostic(anchor->getLoc(), diag::unresolved_nil_literal);
1973+
return true;
1974+
}
1975+
1976+
// Two choices here - whether it's a regular assignment
1977+
// e.g. `let _: S = nil` or a subscript one e.g. `s[0] = nil`.
1978+
if (auto *AE = dyn_cast<AssignExpr>(parentExpr)) {
1979+
CTP = isa<SubscriptExpr>(AE->getDest()) ? CTP_SubscriptAssignSource
1980+
: CTP_AssignSource;
1981+
} else if (isa<ArrayExpr>(parentExpr)) {
1982+
CTP = CTP_ArrayElement;
1983+
} else if (isa<ClosureExpr>(parentExpr)) {
1984+
CTP = CTP_ClosureResult;
1985+
} else if (isa<ParenExpr>(parentExpr) || isa<TupleExpr>(parentExpr)) {
1986+
auto *enclosingExpr = findParentExpr(parentExpr);
1987+
1988+
if (!enclosingExpr) {
1989+
// If there is no enclosing expression it's something like
1990+
// `(nil)` or `(a: nil)` which can't be inferred without a
1991+
// contextual type.
1992+
emitDiagnostic(anchor->getLoc(), diag::unresolved_nil_literal);
1993+
return true;
1994+
}
1995+
1996+
if (auto *TE = dyn_cast<TupleExpr>(parentExpr)) {
1997+
// In case of dictionary e.g. `[42: nil]` we need to figure
1998+
// out whether nil is a "key" or a "value".
1999+
if (auto *DE = dyn_cast<DictionaryExpr>(enclosingExpr)) {
2000+
assert(TE->getNumElements() == 2);
2001+
CTP = TE->getElement(0) == anchor ? CTP_DictionaryKey
2002+
: CTP_DictionaryValue;
2003+
} else {
2004+
// Can't initialize one of the tuple elements with `nil`.
2005+
CTP = CTP_Initialization;
2006+
}
2007+
}
2008+
2009+
// `nil` is passed as an argument to a parameter which doesn't
2010+
// expect it e.g. `foo(a: nil)` or `s[x: nil]`.
2011+
if (isa<ApplyExpr>(enclosingExpr) || isa<SubscriptExpr>(enclosingExpr))
2012+
CTP = CTP_CallArgument;
2013+
} else if (auto *CE = dyn_cast<CoerceExpr>(parentExpr)) {
2014+
// `nil` is passed as a left-hand side of the coercion
2015+
// operator e.g. `nil as Foo`
2016+
CTP = CTP_CoerceOperand;
2017+
} else {
2018+
// Otherwise let's produce a generic `nil` conversion diagnostic.
2019+
emitDiagnostic(anchor->getLoc(), diag::cannot_use_nil_with_this_type,
2020+
getToType());
2021+
return true;
2022+
}
2023+
}
2024+
2025+
if (!CTP)
2026+
return false;
2027+
2028+
if (CTP == CTP_ThrowStmt) {
2029+
emitDiagnostic(anchor->getLoc(), diag::cannot_throw_nil);
2030+
return true;
2031+
}
2032+
2033+
auto diagnostic = getContextualNilDiagnostic(*CTP);
2034+
if (!diagnostic)
2035+
return false;
2036+
2037+
emitDiagnostic(anchor->getLoc(), *diagnostic, getToType());
2038+
2039+
if (CTP == CTP_Initialization) {
2040+
auto *patternTR = cs.getContextualTypeLoc().getTypeRepr();
2041+
if (!patternTR)
2042+
return true;
2043+
2044+
auto diag = emitDiagnostic(patternTR->getLoc(), diag::note_make_optional,
2045+
OptionalType::get(getToType()));
2046+
if (patternTR->isSimple()) {
2047+
diag.fixItInsertAfter(patternTR->getEndLoc(), "?");
2048+
} else {
2049+
diag.fixItInsert(patternTR->getStartLoc(), "(");
2050+
diag.fixItInsertAfter(patternTR->getEndLoc(), ")?");
2051+
}
2052+
}
2053+
2054+
return true;
2055+
}
2056+
18922057
void ContextualFailure::tryFixIts(InFlightDiagnostic &diagnostic) const {
18932058
if (trySequenceSubsequenceFixIts(diagnostic))
18942059
return;

branches/master-next/lib/Sema/CSDiagnostics.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -615,6 +615,9 @@ class ContextualFailure : public FailureDiagnostic {
615615

616616
bool diagnoseAsError() override;
617617

618+
/// If we're trying to convert something to `nil`.
619+
bool diagnoseConversionToNil() const;
620+
618621
// If we're trying to convert something of type "() -> T" to T,
619622
// then we probably meant to call the value.
620623
bool diagnoseMissingFunctionCall() const;

0 commit comments

Comments
 (0)