mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
[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:
@@ -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
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
55
include/swift/Sema/ContextualTypeInfo.h
Normal file
55
include/swift/Sema/ContextualTypeInfo.h
Normal 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
|
||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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.
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -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:
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user