Merge pull request #79592 from xedin/rdar-131819800

[CSFix] Fix a null pointer dereference in `getStructuralTypeContext`
This commit is contained in:
Pavel Yaskevich
2025-02-25 09:56:37 -08:00
committed by GitHub
3 changed files with 46 additions and 14 deletions

View File

@@ -1797,19 +1797,33 @@ public:
/// "resolved" concrete type.
Type getResolvedType(ASTNode node) const;
Type getContextualType(ASTNode anchor) const {
std::optional<ContextualTypeInfo>
getContextualTypeInfo(ASTNode anchor) const {
for (const auto &entry : contextualTypes) {
if (entry.first == anchor) {
// The contextual information record could contain the purpose
// without a type i.e. when the context is an optional-some or
// an invalid pattern binding.
if (auto contextualTy = entry.second.getType())
if (entry.first == anchor)
return entry.second;
}
return std::nullopt;
}
Type getContextualType(ASTNode anchor) const {
if (auto info = getContextualTypeInfo(anchor)) {
// The contextual information record could contain the purpose
// without a type i.e. when the context is an optional-some or
// an invalid pattern binding.
if (auto contextualTy = info->getType())
return simplifyType(contextualTy);
}
}
return Type();
}
ContextualTypePurpose getContextualTypePurpose(ASTNode anchor) const {
if (auto info = getContextualTypeInfo(anchor)) {
return info->purpose;
}
return CTP_Unused;
}
/// Retrieve the generic environment for the opened element of a given pack
/// expansion, or \c nullptr if no environment was recorded.
GenericEnvironment *

View File

@@ -592,12 +592,16 @@ getStructuralTypeContext(const Solution &solution, ConstraintLocator *locator) {
assert(locator->isLastElement<LocatorPathElt::ContextualType>() ||
locator->isLastElement<LocatorPathElt::FunctionArgument>());
auto &cs = solution.getConstraintSystem();
auto anchor = locator->getAnchor();
auto contextualType = cs.getContextualType(anchor, /*forConstraint=*/false);
auto exprType = cs.getType(anchor);
return std::make_tuple(contextualTypeElt->getPurpose(), exprType,
contextualType);
auto contextualInfo = solution.getContextualTypeInfo(anchor);
// For some patterns the type could be empty and the entry is
// there to indicate the purpose only.
if (!contextualInfo || !contextualInfo->getType())
return std::nullopt;
auto exprType = solution.getType(anchor);
return std::make_tuple(contextualInfo->purpose, exprType,
contextualInfo->getType());
} else if (auto argApplyInfo = solution.getFunctionArgApplyInfo(locator)) {
Type fromType = argApplyInfo->getArgType();
Type toType = argApplyInfo->getParamType();
@@ -607,9 +611,8 @@ getStructuralTypeContext(const Solution &solution, ConstraintLocator *locator) {
auto fromFnType = fromType->getAs<FunctionType>();
auto toFnType = toType->getAs<FunctionType>();
if (fromFnType && toFnType) {
auto &cs = solution.getConstraintSystem();
return std::make_tuple(
cs.getContextualTypePurpose(locator->getAnchor()),
solution.getContextualTypePurpose(locator->getAnchor()),
fromFnType->getResult(), toFnType->getResult());
}
}

View File

@@ -805,3 +805,18 @@ func testMatchingNonErrorConformingTypeInClosure(_ x: any Error) {
}
}
}
// rdar://131819800 - crash in `transformWithPosition` while trying to emit diagnostics for `AllowFunctionTypeMismatch` fix
do {
enum E {
case test(kind: Int, defaultsToEmpty: Bool = false)
}
func test(e: E) {
if case .test(kind: _, // expected-error {{tuple pattern has the wrong length for tuple type '(Int, Bool)'}}
name: let name?,
defaultsToEmpty: _,
deprecateName: let deprecatedName?) = e {
}
}
}