[CS] NFC: Store ContextualTypeInfo in SyntacticElementTarget

Move the contextual type locator onto
ContextualTypeInfo, and consolidate the separate
fields in SyntacticElementTarget into storing a
ContextualTypeInfo. This then lets us plumb down
the locator for the branch contextual type of an
if/switch expression from the initial constraint
generation, rather than introducing it later. This
should be NFC.
This commit is contained in:
Hamish Knight
2023-07-26 16:46:54 +01:00
parent 61d73d2b6f
commit a64ba23d7b
10 changed files with 151 additions and 146 deletions

View File

@@ -25,6 +25,7 @@
#include "swift/AST/TypeLoc.h" #include "swift/AST/TypeLoc.h"
#include "swift/Basic/Debug.h" #include "swift/Basic/Debug.h"
#include "swift/Sema/ConstraintLocator.h" #include "swift/Sema/ConstraintLocator.h"
#include "swift/Sema/ContextualTypeInfo.h"
#include "swift/Sema/OverloadChoice.h" #include "swift/Sema/OverloadChoice.h"
#include "llvm/ADT/ArrayRef.h" #include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/ilist.h" #include "llvm/ADT/ilist.h"
@@ -50,23 +51,6 @@ class ConstraintLocator;
class ConstraintSystem; class ConstraintSystem;
enum class TrailingClosureMatching; enum class TrailingClosureMatching;
/// Describes contextual type information about a particular element
/// (expression, statement etc.) within a constraint system.
struct ContextualTypeInfo {
TypeLoc typeLoc;
ContextualTypePurpose purpose;
ContextualTypeInfo() : typeLoc(TypeLoc()), purpose(CTP_Unused) {}
ContextualTypeInfo(Type contextualTy, ContextualTypePurpose purpose)
: typeLoc(TypeLoc::withoutLoc(contextualTy)), purpose(purpose) {}
ContextualTypeInfo(TypeLoc typeLoc, ContextualTypePurpose purpose)
: typeLoc(typeLoc), purpose(purpose) {}
Type getType() const { return typeLoc.getType(); }
};
/// Describes the kind of constraint placed on one or more types. /// Describes the kind of constraint placed on one or more types.
enum class ConstraintKind : char { enum class ConstraintKind : char {
/// The two types must be bound to the same type. This is the only /// The two types must be bound to the same type. This is the only

View File

@@ -3114,12 +3114,11 @@ public:
return E; return E;
} }
void setContextualType(ASTNode node, TypeLoc T, void setContextualInfo(ASTNode node, ContextualTypeInfo info) {
ContextualTypePurpose purpose) {
assert(bool(node) && "Expected non-null expression!"); assert(bool(node) && "Expected non-null expression!");
assert(contextualTypes.count(node) == 0 && assert(contextualTypes.count(node) == 0 &&
"Already set this contextual type"); "Already set this contextual type");
contextualTypes[node] = {{T, purpose}, Type()}; contextualTypes[node] = {info, Type()};
} }
llvm::Optional<ContextualTypeInfo> getContextualTypeInfo(ASTNode node) const { llvm::Optional<ContextualTypeInfo> getContextualTypeInfo(ASTNode node) const {

View File

@@ -0,0 +1,55 @@
//===--- ContextualTypeInfo.h - Contextual Type Info ------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2023 Apple Inc. and the Swift project authors
// Licensed under Apache License v2.0 with Runtime Library Exception
//
// See https://swift.org/LICENSE.txt for license information
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
//
//===----------------------------------------------------------------------===//
//
// This file provides the \c ContextualTypeInfo class.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_CONTEXTUAL_TYPE_INFO_H
#define SWIFT_SEMA_CONTEXTUAL_TYPE_INFO_H
#include "swift/AST/TypeLoc.h"
#include "swift/Sema/ConstraintLocator.h"
namespace swift {
namespace constraints {
/// Describes contextual type information about a particular element
/// (expression, statement etc.) within a constraint system.
struct ContextualTypeInfo {
TypeLoc typeLoc;
ContextualTypePurpose purpose;
/// The locator for the contextual type conversion constraint, or
/// \c nullptr to use the default locator which is anchored directly on
/// the expression.
ConstraintLocator *locator;
ContextualTypeInfo()
: typeLoc(TypeLoc()), purpose(CTP_Unused), locator(nullptr) {}
ContextualTypeInfo(Type contextualTy, ContextualTypePurpose purpose,
ConstraintLocator *locator = nullptr)
: typeLoc(TypeLoc::withoutLoc(contextualTy)), purpose(purpose),
locator(locator) {}
ContextualTypeInfo(TypeLoc typeLoc, ContextualTypePurpose purpose,
ConstraintLocator *locator = nullptr)
: typeLoc(typeLoc), purpose(purpose), locator(locator) {}
Type getType() const { return typeLoc.getType(); }
};
} // end namespace constraints
} // end namespace swift
#endif // SWIFT_SEMA_CONTEXTUAL_TYPE_INFO_H

View File

@@ -23,6 +23,7 @@
#include "swift/AST/Stmt.h" #include "swift/AST/Stmt.h"
#include "swift/AST/TypeLoc.h" #include "swift/AST/TypeLoc.h"
#include "swift/Sema/ConstraintLocator.h" #include "swift/Sema/ConstraintLocator.h"
#include "swift/Sema/ContextualTypeInfo.h"
namespace swift { namespace swift {
@@ -71,18 +72,8 @@ private:
/// type-checked. /// type-checked.
DeclContext *dc; DeclContext *dc;
// TODO: Fold the 3 below fields into ContextualTypeInfo /// The contextual type info for the expression.
ContextualTypeInfo contextualInfo;
/// The purpose of the contextual type.
ContextualTypePurpose contextualPurpose;
/// The type to which the expression should be converted.
TypeLoc convertType;
/// The locator for the contextual type conversion constraint, or
/// \c nullptr to use the default locator which is anchored directly on
/// the expression.
ConstraintLocator *convertTypeLocator;
/// When initializing a pattern from the expression, this is the /// When initializing a pattern from the expression, this is the
/// pattern. /// pattern.
@@ -169,26 +160,15 @@ private:
void maybeApplyPropertyWrapper(); void maybeApplyPropertyWrapper();
public: public:
SyntacticElementTarget(Expr *expr, DeclContext *dc,
ContextualTypePurpose contextualPurpose,
Type convertType,
ConstraintLocator *convertTypeLocator,
bool isDiscarded)
: SyntacticElementTarget(expr, dc, contextualPurpose,
TypeLoc::withoutLoc(convertType),
convertTypeLocator, isDiscarded) {}
SyntacticElementTarget(Expr *expr, DeclContext *dc, SyntacticElementTarget(Expr *expr, DeclContext *dc,
ContextualTypePurpose contextualPurpose, ContextualTypePurpose contextualPurpose,
Type convertType, bool isDiscarded) Type convertType, bool isDiscarded)
: SyntacticElementTarget(expr, dc, contextualPurpose, convertType, : SyntacticElementTarget(
/*convertTypeLocator*/ nullptr, isDiscarded) {} expr, dc, ContextualTypeInfo(convertType, contextualPurpose),
isDiscarded) {}
SyntacticElementTarget(Expr *expr, DeclContext *dc, SyntacticElementTarget(Expr *expr, DeclContext *dc,
ContextualTypePurpose contextualPurpose, ContextualTypeInfo contextualInfo, bool isDiscarded);
TypeLoc convertType,
ConstraintLocator *convertTypeLocator,
bool isDiscarded);
SyntacticElementTarget(ClosureExpr *closure, Type convertType) { SyntacticElementTarget(ClosureExpr *closure, Type convertType) {
kind = Kind::closure; kind = Kind::closure;
@@ -375,26 +355,31 @@ public:
llvm_unreachable("invalid decl context type"); llvm_unreachable("invalid decl context type");
} }
ContextualTypePurpose getExprContextualTypePurpose() const { /// Get the contextual type info for an expression target.
ContextualTypeInfo getExprContextualTypeInfo() const {
assert(kind == Kind::expression); assert(kind == Kind::expression);
return expression.contextualPurpose; return expression.contextualInfo;
} }
/// Get the contextual type purpose for an expression target.
ContextualTypePurpose getExprContextualTypePurpose() const {
return getExprContextualTypeInfo().purpose;
}
/// Get the contextual type for an expression target.
Type getExprContextualType() const { Type getExprContextualType() const {
return getExprContextualTypeLoc().getType(); return getExprContextualTypeLoc().getType();
} }
/// Get the contextual type for an expression target.
TypeLoc getExprContextualTypeLoc() const { TypeLoc getExprContextualTypeLoc() const {
assert(kind == Kind::expression);
// For an @autoclosure parameter, the conversion type is // For an @autoclosure parameter, the conversion type is
// the result of the function type. // the result of the function type.
if (FunctionType *autoclosureParamType = getAsAutoclosureParamType()) { auto typeLoc = getExprContextualTypeInfo().typeLoc;
return TypeLoc(expression.convertType.getTypeRepr(), if (FunctionType *autoclosureParamType = getAsAutoclosureParamType())
autoclosureParamType->getResult()); return TypeLoc(typeLoc.getTypeRepr(), autoclosureParamType->getResult());
}
return expression.convertType; return typeLoc;
} }
/// Retrieve the type to which an expression should be converted, or /// Retrieve the type to which an expression should be converted, or
@@ -408,33 +393,32 @@ public:
/// Retrieve the conversion type locator for the expression, or \c nullptr /// Retrieve the conversion type locator for the expression, or \c nullptr
/// if it has not been set. /// if it has not been set.
ConstraintLocator *getExprConvertTypeLocator() const { ConstraintLocator *getExprConvertTypeLocator() const {
assert(kind == Kind::expression); return getExprContextualTypeInfo().locator;
return expression.convertTypeLocator;
} }
/// Returns the autoclosure parameter type, or \c nullptr if the /// Returns the autoclosure parameter type, or \c nullptr if the
/// expression has a different kind of context. /// expression has a different kind of context.
FunctionType *getAsAutoclosureParamType() const { FunctionType *getAsAutoclosureParamType() const {
assert(kind == Kind::expression); if (getExprContextualTypePurpose() == CTP_AutoclosureDefaultParameter)
if (expression.contextualPurpose == CTP_AutoclosureDefaultParameter) return getExprContextualTypeInfo().getType()->castTo<FunctionType>();
return expression.convertType.getType()->castTo<FunctionType>();
return nullptr; return nullptr;
} }
void setExprConversionType(Type type) { void setExprConversionType(Type type) {
assert(kind == Kind::expression); assert(kind == Kind::expression);
expression.convertType = TypeLoc::withoutLoc(type); expression.contextualInfo.typeLoc = TypeLoc::withoutLoc(type);
} }
void setExprConversionTypeLoc(TypeLoc type) { void setExprConversionTypeLoc(TypeLoc type) {
assert(kind == Kind::expression); assert(kind == Kind::expression);
expression.convertType = type; expression.contextualInfo.typeLoc = type;
} }
/// Whether this target is for an initialization expression and pattern. /// Whether this target is for an initialization expression and pattern.
bool isForInitialization() const { bool isForInitialization() const {
return kind == Kind::expression && return kind == Kind::expression &&
expression.contextualPurpose == CTP_Initialization; getExprContextualTypePurpose() == CTP_Initialization;
} }
/// For a pattern initialization target, retrieve the pattern. /// For a pattern initialization target, retrieve the pattern.
@@ -448,7 +432,7 @@ public:
ExprPattern *getExprPattern() const { ExprPattern *getExprPattern() const {
assert(kind == Kind::expression); assert(kind == Kind::expression);
assert(expression.contextualPurpose == CTP_ExprPattern); assert(getExprContextualTypePurpose() == CTP_ExprPattern);
return cast<ExprPattern>(expression.pattern); return cast<ExprPattern>(expression.pattern);
} }
@@ -575,11 +559,16 @@ public:
return; return;
} }
assert(kind == Kind::expression); switch (getExprContextualTypePurpose()) {
assert(expression.contextualPurpose == CTP_Initialization || case CTP_Initialization:
expression.contextualPurpose == CTP_ForEachStmt || case CTP_ForEachStmt:
expression.contextualPurpose == CTP_ForEachSequence || case CTP_ForEachSequence:
expression.contextualPurpose == CTP_ExprPattern); case CTP_ExprPattern:
break;
default:
assert(false && "Unexpected contextual type purpose");
break;
}
expression.pattern = pattern; expression.pattern = pattern;
} }

View File

@@ -4334,8 +4334,9 @@ bool ConstraintSystem::generateWrappedPropertyTypeConstraints(
ConstraintKind::Equal, propertyType, wrappedValueType, ConstraintKind::Equal, propertyType, wrappedValueType,
getConstraintLocator( getConstraintLocator(
wrappedVar, LocatorPathElt::ContextualType(CTP_WrappedProperty))); wrappedVar, LocatorPathElt::ContextualType(CTP_WrappedProperty)));
setContextualType(wrappedVar, TypeLoc::withoutLoc(wrappedValueType),
CTP_WrappedProperty); ContextualTypeInfo contextInfo(wrappedValueType, CTP_WrappedProperty);
setContextualInfo(wrappedVar, contextInfo);
return false; return false;
} }
@@ -4419,10 +4420,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
makeIteratorCall, dc, /*patternType=*/Type(), PB, /*index=*/0, makeIteratorCall, dc, /*patternType=*/Type(), PB, /*index=*/0,
/*shouldBindPatternsOneWay=*/false); /*shouldBindPatternsOneWay=*/false);
cs.setContextualType( ContextualTypeInfo contextInfo(sequenceProto->getDeclaredInterfaceType(),
sequenceExpr, CTP_ForEachSequence);
TypeLoc::withoutLoc(sequenceProto->getDeclaredInterfaceType()), cs.setContextualInfo(sequenceExpr, contextInfo);
CTP_ForEachSequence);
if (cs.generateConstraints(makeIteratorTarget)) if (cs.generateConstraints(makeIteratorTarget))
return llvm::None; return llvm::None;
@@ -4480,10 +4480,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
if (!iteratorProto) if (!iteratorProto)
return llvm::None; return llvm::None;
cs.setContextualType( ContextualTypeInfo contextInfo(iteratorProto->getDeclaredInterfaceType(),
nextRef->getBase(), CTP_ForEachSequence);
TypeLoc::withoutLoc(iteratorProto->getDeclaredInterfaceType()), cs.setContextualInfo(nextRef->getBase(), contextInfo);
CTP_ForEachSequence);
} }
SyntacticElementTarget nextTarget(nextCall, dc, CTP_Unused, SyntacticElementTarget nextTarget(nextCall, dc, CTP_Unused,
@@ -4549,8 +4548,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
return llvm::None; return llvm::None;
cs.setTargetFor(whereExpr, whereTarget); cs.setTargetFor(whereExpr, whereTarget);
cs.setContextualType(whereExpr, TypeLoc::withoutLoc(boolType),
CTP_Condition); ContextualTypeInfo contextInfo(boolType, CTP_Condition);
cs.setContextualInfo(whereExpr, contextInfo);
} }
// Populate all of the information for a for-each loop. // Populate all of the information for a for-each loop.

View File

@@ -323,10 +323,8 @@ void ConstraintSystem::applySolution(const Solution &solution) {
// Add the contextual types. // Add the contextual types.
for (const auto &contextualType : solution.contextualTypes) { for (const auto &contextualType : solution.contextualTypes) {
if (!getContextualTypeInfo(contextualType.first)) { if (!getContextualTypeInfo(contextualType.first))
setContextualType(contextualType.first, contextualType.second.typeLoc, setContextualInfo(contextualType.first, contextualType.second);
contextualType.second.purpose);
}
} }
// Register the statement condition targets. // Register the statement condition targets.
@@ -1731,8 +1729,7 @@ bool ConstraintSystem::solveForCodeCompletion(
SyntacticElementTarget &target, SmallVectorImpl<Solution> &solutions) { SyntacticElementTarget &target, SmallVectorImpl<Solution> &solutions) {
if (auto *expr = target.getAsExpr()) { if (auto *expr = target.getAsExpr()) {
// Tell the constraint system what the contextual type is. // Tell the constraint system what the contextual type is.
setContextualType(expr, target.getExprContextualTypeLoc(), setContextualInfo(expr, target.getExprContextualTypeInfo());
target.getExprContextualTypePurpose());
// Set up the expression type checker timer. // Set up the expression type checker timer.
Timer.emplace(expr, *this); Timer.emplace(expr, *this);

View File

@@ -1224,8 +1224,7 @@ private:
auto contextualResultInfo = getContextualResultInfo(); auto contextualResultInfo = getContextualResultInfo();
SyntacticElementTarget target(resultExpr, context.getAsDeclContext(), SyntacticElementTarget target(resultExpr, context.getAsDeclContext(),
contextualResultInfo.purpose, contextualResultInfo,
contextualResultInfo.getType(),
/*isDiscarded=*/false); /*isDiscarded=*/false);
if (cs.generateConstraints(target)) { if (cs.generateConstraints(target)) {
@@ -1233,9 +1232,7 @@ private:
return; return;
} }
cs.setContextualType(target.getAsExpr(), cs.setContextualInfo(target.getAsExpr(), contextualResultInfo);
TypeLoc::withoutLoc(contextualResultInfo.getType()),
contextualResultInfo.purpose);
cs.setTargetFor(returnStmt, target); cs.setTargetFor(returnStmt, target);
} }
@@ -1391,9 +1388,15 @@ bool ConstraintSystem::generateConstraints(SingleValueStmtExpr *E) {
// Assign contextual types for each of the expression branches. // Assign contextual types for each of the expression branches.
SmallVector<Expr *, 4> scratch; SmallVector<Expr *, 4> scratch;
auto branches = E->getSingleExprBranches(scratch); auto branches = E->getSingleExprBranches(scratch);
for (auto *branch : branches) { for (auto idx : indices(branches)) {
setContextualType(branch, TypeLoc::withoutLoc(resultTy), auto *branch = branches[idx];
CTP_SingleValueStmtBranch);
auto ctpElt = LocatorPathElt::ContextualType(CTP_SingleValueStmtBranch);
auto *loc = getConstraintLocator(
E, {LocatorPathElt::SingleValueStmtBranch(idx), ctpElt});
ContextualTypeInfo info(resultTy, CTP_SingleValueStmtBranch, loc);
setContextualInfo(branch, info);
} }
TypeJoinExpr *join = nullptr; TypeJoinExpr *join = nullptr;
@@ -1546,26 +1549,8 @@ ConstraintSystem::simplifySyntacticElementConstraint(
getConstraintLocator(locator)); getConstraintLocator(locator));
if (auto *expr = element.dyn_cast<Expr *>()) { if (auto *expr = element.dyn_cast<Expr *>()) {
auto ctpElt = LocatorPathElt::ContextualType(contextInfo.purpose);
auto *contextualTypeLoc = getConstraintLocator(expr, {ctpElt});
// If this is a branch expression in a SingleValueStmtExpr, form a locator
// based on the branch index.
if (auto *SVE = getAsExpr<SingleValueStmtExpr>(locator.getAnchor())) {
SmallVector<Expr *, 4> scratch;
auto branches = SVE->getSingleExprBranches(scratch);
for (auto idx : indices(branches)) {
if (expr == branches[idx]) {
contextualTypeLoc = getConstraintLocator(
SVE, {LocatorPathElt::SingleValueStmtBranch(idx), ctpElt});
break;
}
}
}
SyntacticElementTarget target(expr, context->getAsDeclContext(), SyntacticElementTarget target(expr, context->getAsDeclContext(),
contextInfo.purpose, contextInfo.getType(), contextInfo, isDiscarded);
contextualTypeLoc, isDiscarded);
if (generateConstraints(target)) if (generateConstraints(target))
return SolutionKind::Error; return SolutionKind::Error;

View File

@@ -25,22 +25,23 @@ using namespace constraints;
#define DEBUG_TYPE "SyntacticElementTarget" #define DEBUG_TYPE "SyntacticElementTarget"
SyntacticElementTarget::SyntacticElementTarget( SyntacticElementTarget::SyntacticElementTarget(
Expr *expr, DeclContext *dc, ContextualTypePurpose contextualPurpose, Expr *expr, DeclContext *dc, ContextualTypeInfo contextualInfo,
TypeLoc convertType, ConstraintLocator *convertTypeLocator,
bool isDiscarded) { bool isDiscarded) {
auto contextualPurpose = contextualInfo.purpose;
// Verify that a purpose was specified if a convertType was. Note that it is // Verify that a purpose was specified if a convertType was. Note that it is
// ok to have a purpose without a convertType (which is used for call // ok to have a purpose without a convertType (which is used for call
// return types). // return types).
assert((!convertType.getType() || contextualPurpose != CTP_Unused) && assert((!contextualInfo.getType() || contextualPurpose != CTP_Unused) &&
"Purpose for conversion type was not specified"); "Purpose for conversion type was not specified");
// Take a look at the conversion type to check to make sure it is sensible. // Take a look at the conversion type to check to make sure it is sensible.
if (auto type = convertType.getType()) { if (auto type = contextualInfo.getType()) {
// If we're asked to convert to an UnresolvedType, then ignore the request. // If we're asked to convert to an UnresolvedType, then ignore the request.
// This happens when CSDiags nukes a type. // This happens when CSDiags nukes a type.
if (type->is<UnresolvedType>() || if (type->is<UnresolvedType>() ||
(type->is<MetatypeType>() && type->hasUnresolvedType())) { (type->is<MetatypeType>() && type->hasUnresolvedType())) {
convertType = TypeLoc(); contextualInfo.typeLoc = TypeLoc();
contextualPurpose = CTP_Unused; contextualPurpose = CTP_Unused;
} }
} }
@@ -48,9 +49,7 @@ SyntacticElementTarget::SyntacticElementTarget(
kind = Kind::expression; kind = Kind::expression;
expression.expression = expr; expression.expression = expr;
expression.dc = dc; expression.dc = dc;
expression.contextualPurpose = contextualPurpose; expression.contextualInfo = contextualInfo;
expression.convertType = convertType;
expression.convertTypeLocator = convertTypeLocator;
expression.pattern = nullptr; expression.pattern = nullptr;
expression.propertyWrapper.wrappedVar = nullptr; expression.propertyWrapper.wrappedVar = nullptr;
expression.propertyWrapper.innermostWrappedValueInit = nullptr; expression.propertyWrapper.innermostWrappedValueInit = nullptr;
@@ -62,8 +61,7 @@ SyntacticElementTarget::SyntacticElementTarget(
} }
void SyntacticElementTarget::maybeApplyPropertyWrapper() { void SyntacticElementTarget::maybeApplyPropertyWrapper() {
assert(kind == Kind::expression); assert(getExprContextualTypePurpose() == CTP_Initialization);
assert(expression.contextualPurpose == CTP_Initialization);
VarDecl *singleVar; VarDecl *singleVar;
if (auto *pattern = expression.pattern) { if (auto *pattern = expression.pattern) {
@@ -130,8 +128,8 @@ void SyntacticElementTarget::maybeApplyPropertyWrapper() {
// the initializer type later. // the initializer type later.
expression.propertyWrapper.wrappedVar = singleVar; expression.propertyWrapper.wrappedVar = singleVar;
expression.expression = backingInitializer; expression.expression = backingInitializer;
expression.convertType = {outermostWrapperAttr->getTypeRepr(), expression.contextualInfo.typeLoc = {outermostWrapperAttr->getTypeRepr(),
outermostWrapperAttr->getType()}; outermostWrapperAttr->getType()};
} }
SyntacticElementTarget SyntacticElementTarget
@@ -157,9 +155,9 @@ SyntacticElementTarget::forInitialization(Expr *initializer, DeclContext *dc,
} }
} }
SyntacticElementTarget target( ContextualTypeInfo contextInfo(contextualType, CTP_Initialization);
initializer, dc, CTP_Initialization, contextualType, SyntacticElementTarget target(initializer, dc, contextInfo,
/*convertTypeLocator*/ nullptr, /*isDiscarded=*/false); /*isDiscarded=*/false);
target.expression.pattern = pattern; target.expression.pattern = pattern;
target.expression.bindPatternVarsOneWay = bindPatternVarsOneWay; target.expression.bindPatternVarsOneWay = bindPatternVarsOneWay;
target.maybeApplyPropertyWrapper(); target.maybeApplyPropertyWrapper();
@@ -226,10 +224,10 @@ ContextualPattern SyntacticElementTarget::getContextualPattern() const {
forEachStmt.dc); forEachStmt.dc);
} }
assert(kind == Kind::expression); auto ctp = getExprContextualTypePurpose();
assert(expression.contextualPurpose == CTP_Initialization); assert(ctp == CTP_Initialization);
if (expression.contextualPurpose == CTP_Initialization &&
expression.initialization.patternBinding) { if (ctp == CTP_Initialization && expression.initialization.patternBinding) {
return ContextualPattern::forPatternBindingDecl( return ContextualPattern::forPatternBindingDecl(
expression.initialization.patternBinding, expression.initialization.patternBinding,
expression.initialization.patternBindingIndex); expression.initialization.patternBindingIndex);
@@ -239,12 +237,11 @@ ContextualPattern SyntacticElementTarget::getContextualPattern() const {
} }
bool SyntacticElementTarget::infersOpaqueReturnType() const { bool SyntacticElementTarget::infersOpaqueReturnType() const {
assert(kind == Kind::expression); switch (getExprContextualTypePurpose()) {
switch (expression.contextualPurpose) {
case CTP_Initialization: case CTP_Initialization:
case CTP_ReturnStmt: case CTP_ReturnStmt:
case CTP_ReturnSingleExpr: case CTP_ReturnSingleExpr:
if (Type convertType = expression.convertType.getType()) if (Type convertType = getExprContextualType())
return convertType->hasOpaqueArchetype(); return convertType->hasOpaqueArchetype();
return false; return false;
default: default:
@@ -253,8 +250,7 @@ bool SyntacticElementTarget::infersOpaqueReturnType() const {
} }
bool SyntacticElementTarget::contextualTypeIsOnlyAHint() const { bool SyntacticElementTarget::contextualTypeIsOnlyAHint() const {
assert(kind == Kind::expression); switch (getExprContextualTypePurpose()) {
switch (expression.contextualPurpose) {
case CTP_Initialization: case CTP_Initialization:
return !infersOpaqueReturnType() && !isOptionalSomePatternInit(); return !infersOpaqueReturnType() && !isOptionalSomePatternInit();
case CTP_ForEachStmt: case CTP_ForEachStmt:

View File

@@ -458,8 +458,7 @@ TypeChecker::typeCheckTarget(SyntacticElementTarget &target,
if (auto *expr = target.getAsExpr()) { if (auto *expr = target.getAsExpr()) {
// Tell the constraint system what the contextual type is. This informs // Tell the constraint system what the contextual type is. This informs
// diagnostics and is a hint for various performance optimizations. // diagnostics and is a hint for various performance optimizations.
cs.setContextualType(expr, target.getExprContextualTypeLoc(), cs.setContextualInfo(expr, target.getExprContextualTypeInfo());
target.getExprContextualTypePurpose());
// Try to shrink the system by reducing disjunction domains. This // Try to shrink the system by reducing disjunction domains. This
// goes through every sub-expression and generate its own sub-system, to // goes through every sub-expression and generate its own sub-system, to
@@ -751,9 +750,8 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
} }
defaultExprTarget.setExprConversionType(contextualTy); defaultExprTarget.setExprConversionType(contextualTy);
cs.setContextualType(defaultValue, cs.setContextualInfo(defaultValue,
defaultExprTarget.getExprContextualTypeLoc(), defaultExprTarget.getExprContextualTypeInfo());
defaultExprTarget.getExprContextualTypePurpose());
auto viable = cs.solve(defaultExprTarget, FreeTypeVariableBinding::Disallow); auto viable = cs.solve(defaultExprTarget, FreeTypeVariableBinding::Disallow);
if (!viable) if (!viable)

View File

@@ -36,7 +36,8 @@ TEST_F(SemaTest, TestPlaceholderInferenceForArrayLiteral) {
arrayExpr, DC, arrayTy, typedPattern, /*bindPatternVarsOneWay=*/false); arrayExpr, DC, arrayTy, typedPattern, /*bindPatternVarsOneWay=*/false);
ConstraintSystem cs(DC, ConstraintSystemOptions()); ConstraintSystem cs(DC, ConstraintSystemOptions());
cs.setContextualType(arrayExpr, {arrayRepr, arrayTy}, CTP_Initialization); ContextualTypeInfo contextualInfo({arrayRepr, arrayTy}, CTP_Initialization);
cs.setContextualInfo(arrayExpr, contextualInfo);
auto failed = cs.generateConstraints(target, FreeTypeVariableBinding::Disallow); auto failed = cs.generateConstraints(target, FreeTypeVariableBinding::Disallow);
ASSERT_FALSE(failed); ASSERT_FALSE(failed);
@@ -78,7 +79,8 @@ TEST_F(SemaTest, TestPlaceholderInferenceForDictionaryLiteral) {
dictExpr, DC, dictTy, typedPattern, /*bindPatternVarsOneWay=*/false); dictExpr, DC, dictTy, typedPattern, /*bindPatternVarsOneWay=*/false);
ConstraintSystem cs(DC, ConstraintSystemOptions()); ConstraintSystem cs(DC, ConstraintSystemOptions());
cs.setContextualType(dictExpr, {dictRepr, dictTy}, CTP_Initialization); ContextualTypeInfo contextualInfo({dictRepr, dictTy}, CTP_Initialization);
cs.setContextualInfo(dictExpr, contextualInfo);
auto failed = cs.generateConstraints(target, FreeTypeVariableBinding::Disallow); auto failed = cs.generateConstraints(target, FreeTypeVariableBinding::Disallow);
ASSERT_FALSE(failed); ASSERT_FALSE(failed);