Skip to content

Commit 13e3269

Browse files
committed
[CSFix] Fix a null pointer dereference in getStructuralTypeContext
First problem - the logic used constraint system, which shouldn't be required, second - it expects the type to be always present in `ContextualTypeInfo` but that's not the case for some patterns. Resolves: rdar://131819800
1 parent 7c258f2 commit 13e3269

File tree

3 files changed

+46
-14
lines changed

3 files changed

+46
-14
lines changed

include/swift/Sema/ConstraintSystem.h

Lines changed: 21 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1797,19 +1797,33 @@ class Solution {
17971797
/// "resolved" concrete type.
17981798
Type getResolvedType(ASTNode node) const;
17991799

1800-
Type getContextualType(ASTNode anchor) const {
1800+
std::optional<ContextualTypeInfo>
1801+
getContextualTypeInfo(ASTNode anchor) const {
18011802
for (const auto &entry : contextualTypes) {
1802-
if (entry.first == anchor) {
1803-
// The contextual information record could contain the purpose
1804-
// without a type i.e. when the context is an optional-some or
1805-
// an invalid pattern binding.
1806-
if (auto contextualTy = entry.second.getType())
1803+
if (entry.first == anchor)
1804+
return entry.second;
1805+
}
1806+
return std::nullopt;
1807+
}
1808+
1809+
Type getContextualType(ASTNode anchor) const {
1810+
if (auto info = getContextualTypeInfo(anchor)) {
1811+
// The contextual information record could contain the purpose
1812+
// without a type i.e. when the context is an optional-some or
1813+
// an invalid pattern binding.
1814+
if (auto contextualTy = info->getType())
18071815
return simplifyType(contextualTy);
1808-
}
18091816
}
18101817
return Type();
18111818
}
18121819

1820+
ContextualTypePurpose getContextualTypePurpose(ASTNode anchor) const {
1821+
if (auto info = getContextualTypeInfo(anchor)) {
1822+
return info->purpose;
1823+
}
1824+
return CTP_Unused;
1825+
}
1826+
18131827
/// Retrieve the generic environment for the opened element of a given pack
18141828
/// expansion, or \c nullptr if no environment was recorded.
18151829
GenericEnvironment *

lib/Sema/CSFix.cpp

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -592,12 +592,16 @@ getStructuralTypeContext(const Solution &solution, ConstraintLocator *locator) {
592592
assert(locator->isLastElement<LocatorPathElt::ContextualType>() ||
593593
locator->isLastElement<LocatorPathElt::FunctionArgument>());
594594

595-
auto &cs = solution.getConstraintSystem();
596595
auto anchor = locator->getAnchor();
597-
auto contextualType = cs.getContextualType(anchor, /*forConstraint=*/false);
598-
auto exprType = cs.getType(anchor);
599-
return std::make_tuple(contextualTypeElt->getPurpose(), exprType,
600-
contextualType);
596+
auto contextualInfo = solution.getContextualTypeInfo(anchor);
597+
// For some patterns the type could be empty and the entry is
598+
// there to indicate the purpose only.
599+
if (!contextualInfo || !contextualInfo->getType())
600+
return std::nullopt;
601+
602+
auto exprType = solution.getType(anchor);
603+
return std::make_tuple(contextualInfo->purpose, exprType,
604+
contextualInfo->getType());
601605
} else if (auto argApplyInfo = solution.getFunctionArgApplyInfo(locator)) {
602606
Type fromType = argApplyInfo->getArgType();
603607
Type toType = argApplyInfo->getParamType();
@@ -607,9 +611,8 @@ getStructuralTypeContext(const Solution &solution, ConstraintLocator *locator) {
607611
auto fromFnType = fromType->getAs<FunctionType>();
608612
auto toFnType = toType->getAs<FunctionType>();
609613
if (fromFnType && toFnType) {
610-
auto &cs = solution.getConstraintSystem();
611614
return std::make_tuple(
612-
cs.getContextualTypePurpose(locator->getAnchor()),
615+
solution.getContextualTypePurpose(locator->getAnchor()),
613616
fromFnType->getResult(), toFnType->getResult());
614617
}
615618
}

test/Constraints/patterns.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -805,3 +805,18 @@ func testMatchingNonErrorConformingTypeInClosure(_ x: any Error) {
805805
}
806806
}
807807
}
808+
809+
// rdar://131819800 - crash in `transformWithPosition` while trying to emit diagnostics for `AllowFunctionTypeMismatch` fix
810+
do {
811+
enum E {
812+
case test(kind: Int, defaultsToEmpty: Bool = false)
813+
}
814+
815+
func test(e: E) {
816+
if case .test(kind: _, // expected-error {{tuple pattern has the wrong length for tuple type '(Int, Bool)'}}
817+
name: let name?,
818+
defaultsToEmpty: _,
819+
deprecateName: let deprecatedName?) = e {
820+
}
821+
}
822+
}

0 commit comments

Comments
 (0)