Skip to content

Commit 08dca46

Browse files
authored
Merge pull request #29635 from DougGregor/simplify-solution-target
2 parents 3981a68 + bbc0a95 commit 08dca46

File tree

7 files changed

+75
-90
lines changed

7 files changed

+75
-90
lines changed

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7321,6 +7321,7 @@ Optional<SolutionApplicationTarget> ConstraintSystem::applySolution(
73217321
Type convertType = target.getExprConversionType();
73227322
auto shouldCoerceToContextualType = [&]() {
73237323
return convertType &&
7324+
!target.isOptionalSomePatternInit() &&
73247325
!(getType(resultExpr)->isUninhabited() &&
73257326
getContextualTypePurpose(target.getAsExpr())
73267327
== CTP_ReturnSingleExpr);

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3831,8 +3831,7 @@ bool ConstraintSystem::generateConstraints(StmtCondition condition,
38313831

38323832
case StmtConditionElement::CK_Boolean: {
38333833
Expr *condExpr = condElement.getBoolean();
3834-
setContextualType(condExpr, TypeLoc::withoutLoc(boolTy), CTP_Condition,
3835-
/*isOpaqueReturnType=*/false);
3834+
setContextualType(condExpr, TypeLoc::withoutLoc(boolTy), CTP_Condition);
38363835

38373836
condExpr = generateConstraints(condExpr, dc);
38383837
if (!condExpr) {

lib/Sema/CSSimplify.cpp

Lines changed: 39 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -9140,57 +9140,57 @@ void ConstraintSystem::addConstraint(ConstraintKind kind, Type first,
91409140
}
91419141

91429142
void ConstraintSystem::addContextualConversionConstraint(
9143-
Expr *expr, ContextualTypeInfo contextualType) {
9144-
Type convertType = contextualType.getType();
9145-
if (convertType.isNull())
9143+
Expr *expr, Type conversionType, ContextualTypePurpose purpose,
9144+
bool isOpaqueReturnType) {
9145+
if (conversionType.isNull())
91469146
return;
91479147

91489148
// Determine the type of the constraint.
91499149
auto constraintKind = ConstraintKind::Conversion;
9150-
switch (contextualType.purpose) {
9151-
case CTP_ReturnStmt:
9152-
case CTP_ReturnSingleExpr:
9153-
case CTP_Initialization:
9154-
if (contextualType.isOpaqueReturnType)
9155-
constraintKind = ConstraintKind::OpaqueUnderlyingType;
9156-
break;
9150+
switch (purpose) {
9151+
case CTP_ReturnStmt:
9152+
case CTP_ReturnSingleExpr:
9153+
case CTP_Initialization:
9154+
if (isOpaqueReturnType)
9155+
constraintKind = ConstraintKind::OpaqueUnderlyingType;
9156+
break;
91579157

9158-
case CTP_CallArgument:
9159-
constraintKind = ConstraintKind::ArgumentConversion;
9160-
break;
9158+
case CTP_CallArgument:
9159+
constraintKind = ConstraintKind::ArgumentConversion;
9160+
break;
91619161

9162-
case CTP_YieldByReference:
9163-
// In a by-reference yield, we expect the contextual type to be an
9164-
// l-value type, so the result must be bound to that.
9165-
constraintKind = ConstraintKind::Bind;
9166-
break;
9162+
case CTP_YieldByReference:
9163+
// In a by-reference yield, we expect the contextual type to be an
9164+
// l-value type, so the result must be bound to that.
9165+
constraintKind = ConstraintKind::Bind;
9166+
break;
91679167

9168-
case CTP_ArrayElement:
9169-
case CTP_AssignSource:
9170-
case CTP_CalleeResult:
9171-
case CTP_CannotFail:
9172-
case CTP_Condition:
9173-
case CTP_Unused:
9174-
case CTP_YieldByValue:
9175-
case CTP_ThrowStmt:
9176-
case CTP_EnumCaseRawValue:
9177-
case CTP_DefaultParameter:
9178-
case CTP_AutoclosureDefaultParameter:
9179-
case CTP_ClosureResult:
9180-
case CTP_DictionaryKey:
9181-
case CTP_DictionaryValue:
9182-
case CTP_CoerceOperand:
9183-
case CTP_SubscriptAssignSource:
9184-
case CTP_ForEachStmt:
9185-
break;
9168+
case CTP_ArrayElement:
9169+
case CTP_AssignSource:
9170+
case CTP_CalleeResult:
9171+
case CTP_CannotFail:
9172+
case CTP_Condition:
9173+
case CTP_Unused:
9174+
case CTP_YieldByValue:
9175+
case CTP_ThrowStmt:
9176+
case CTP_EnumCaseRawValue:
9177+
case CTP_DefaultParameter:
9178+
case CTP_AutoclosureDefaultParameter:
9179+
case CTP_ClosureResult:
9180+
case CTP_DictionaryKey:
9181+
case CTP_DictionaryValue:
9182+
case CTP_CoerceOperand:
9183+
case CTP_SubscriptAssignSource:
9184+
case CTP_ForEachStmt:
9185+
break;
91869186
}
91879187

91889188
// Add the constraint.
9189-
bool isForSingleExprFunction = (contextualType.purpose == CTP_ReturnSingleExpr);
9189+
bool isForSingleExprFunction = (purpose == CTP_ReturnSingleExpr);
91909190
auto *convertTypeLocator = getConstraintLocator(
91919191
expr, LocatorPathElt::ContextualType(isForSingleExprFunction));
9192-
addConstraint(constraintKind, getType(expr), convertType,
9193-
convertTypeLocator, /*isFavored*/ true);
9192+
addConstraint(constraintKind, getType(expr), conversionType,
9193+
convertTypeLocator, /*isFavored*/ true);
91949194
}
91959195

91969196
Type ConstraintSystem::addJoinConstraint(

lib/Sema/CSSolver.cpp

Lines changed: 5 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -240,8 +240,7 @@ void ConstraintSystem::applySolution(const Solution &solution) {
240240
for (const auto &contextualType : solution.contextualTypes) {
241241
if (!getContextualTypeInfo(contextualType.first)) {
242242
setContextualType(contextualType.first, contextualType.second.typeLoc,
243-
contextualType.second.purpose,
244-
contextualType.second.isOpaqueReturnType);
243+
contextualType.second.purpose);
245244
}
246245
}
247246

@@ -1243,8 +1242,6 @@ ConstraintSystem::solveImpl(SolutionApplicationTarget &target,
12431242
Expr *expr = target.getAsExpr();
12441243
Timer.emplace(expr, *this);
12451244

1246-
Expr *origExpr = expr;
1247-
12481245
// Try to shrink the system by reducing disjunction domains. This
12491246
// goes through every sub-expression and generate its own sub-system, to
12501247
// try to reduce the domains of those subexpressions.
@@ -1261,12 +1258,8 @@ ConstraintSystem::solveImpl(SolutionApplicationTarget &target,
12611258
// constraint.
12621259
if (Type convertType = target.getExprConversionType()) {
12631260
// Determine whether we know more about the contextual type.
1264-
ContextualTypePurpose ctp = CTP_Unused;
1265-
bool isOpaqueReturnType = false;
1266-
if (auto contextualInfo = getContextualTypeInfo(origExpr)) {
1267-
ctp = contextualInfo->purpose;
1268-
isOpaqueReturnType = contextualInfo->isOpaqueReturnType;
1269-
}
1261+
ContextualTypePurpose ctp = target.getExprContextualTypePurpose();
1262+
bool isOpaqueReturnType = target.infersOpaqueReturnType();
12701263

12711264
// Substitute type variables in for unresolved types.
12721265
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
@@ -1281,9 +1274,8 @@ ConstraintSystem::solveImpl(SolutionApplicationTarget &target,
12811274
});
12821275
}
12831276

1284-
ContextualTypeInfo info{
1285-
TypeLoc::withoutLoc(convertType), ctp, isOpaqueReturnType};
1286-
addContextualConversionConstraint(expr, info);
1277+
addContextualConversionConstraint(expr, convertType, ctp,
1278+
isOpaqueReturnType);
12871279
}
12881280

12891281
// Notify the listener that we've built the constraint system.

lib/Sema/ConstraintSystem.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4053,7 +4053,7 @@ bool SolutionApplicationTarget::contextualTypeIsOnlyAHint() const {
40534053
assert(kind == Kind::expression);
40544054
switch (expression.contextualPurpose) {
40554055
case CTP_Initialization:
4056-
return !infersOpaqueReturnType();
4056+
return !infersOpaqueReturnType() && !isOptionalSomePatternInit();
40574057
case CTP_ForEachStmt:
40584058
return true;
40594059
case CTP_Unused:

lib/Sema/ConstraintSystem.h

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -792,7 +792,6 @@ using OpenedTypeMap =
792792
struct ContextualTypeInfo {
793793
TypeLoc typeLoc;
794794
ContextualTypePurpose purpose;
795-
bool isOpaqueReturnType = false;
796795

797796
Type getType() const { return typeLoc.getType(); }
798797
};
@@ -1224,11 +1223,11 @@ class SolutionApplicationTarget {
12241223
return expression.contextualPurpose;
12251224
}
12261225

1227-
Type getExprConversionType() const {
1228-
return getExprConversionTypeLoc().getType();
1226+
Type getExprContextualType() const {
1227+
return getExprContextualTypeLoc().getType();
12291228
}
12301229

1231-
TypeLoc getExprConversionTypeLoc() const {
1230+
TypeLoc getExprContextualTypeLoc() const {
12321231
assert(kind == Kind::expression);
12331232

12341233
// For an @autoclosure parameter, the conversion type is
@@ -1241,6 +1240,14 @@ class SolutionApplicationTarget {
12411240
return expression.convertType;
12421241
}
12431242

1243+
/// Retrieve the type to which an expression should be converted, or
1244+
/// a NULL type if no conversion constraint should be generated.
1245+
Type getExprConversionType() const {
1246+
if (contextualTypeIsOnlyAHint())
1247+
return Type();
1248+
return getExprContextualType();
1249+
}
1250+
12441251
/// Returns the autoclosure parameter type, or \c nullptr if the
12451252
/// expression has a different kind of context.
12461253
FunctionType *getAsAutoclosureParamType() const {
@@ -2328,12 +2335,11 @@ class ConstraintSystem {
23282335
}
23292336

23302337
void setContextualType(
2331-
const Expr *expr, TypeLoc T, ContextualTypePurpose purpose,
2332-
bool isOpaqueReturnType) {
2338+
const Expr *expr, TypeLoc T, ContextualTypePurpose purpose) {
23332339
assert(expr != nullptr && "Expected non-null expression!");
23342340
assert(contextualTypes.count(expr) == 0 &&
23352341
"Already set this contextual type");
2336-
contextualTypes[expr] = { T, purpose, isOpaqueReturnType };
2342+
contextualTypes[expr] = { T, purpose };
23372343
}
23382344

23392345
Optional<ContextualTypeInfo> getContextualTypeInfo(const Expr *expr) const {
@@ -2565,7 +2571,8 @@ class ConstraintSystem {
25652571

25662572
/// Add the appropriate constraint for a contextual conversion.
25672573
void addContextualConversionConstraint(
2568-
Expr *expr, ContextualTypeInfo contextualType);
2574+
Expr *expr, Type conversionType, ContextualTypePurpose purpose,
2575+
bool isOpaqueReturnType);
25692576

25702577
/// Add a "join" constraint between a set of types, producing the common
25712578
/// supertype.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 13 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -2050,6 +2050,7 @@ TypeChecker::typeCheckExpression(
20502050
target.setExpr(expr);
20512051
return None;
20522052
}
2053+
target.setExpr(expr);
20532054

20542055
// Construct a constraint system from this expression.
20552056
ConstraintSystemOptions csOptions = ConstraintSystemFlags::AllowFixes;
@@ -2070,46 +2071,34 @@ TypeChecker::typeCheckExpression(
20702071
// diagnostics and is a hint for various performance optimizations.
20712072
// FIXME: Look through LoadExpr. This is an egregious hack due to the
20722073
// way typeCheckExprIndependently works.
2073-
TypeLoc convertType = target.getExprConversionTypeLoc();
20742074
Expr *contextualTypeExpr = expr;
20752075
if (auto loadExpr = dyn_cast_or_null<LoadExpr>(contextualTypeExpr))
20762076
contextualTypeExpr = loadExpr->getSubExpr();
20772077
cs.setContextualType(
2078-
contextualTypeExpr, convertType,
2079-
target.getExprContextualTypePurpose(),
2080-
target.infersOpaqueReturnType());
2081-
2082-
// If the convertType is *only* provided for that hint, then null it out so
2083-
// that we don't later treat it as an actual conversion constraint.
2084-
if (target.contextualTypeIsOnlyAHint())
2085-
convertType = TypeLoc();
2078+
contextualTypeExpr,
2079+
target.getExprContextualTypeLoc(),
2080+
target.getExprContextualTypePurpose());
20862081

20872082
// If the client can handle unresolved type variables, leave them in the
20882083
// system.
20892084
auto allowFreeTypeVariables = FreeTypeVariableBinding::Disallow;
20902085
if (options.contains(TypeCheckExprFlags::AllowUnresolvedTypeVariables))
20912086
allowFreeTypeVariables = FreeTypeVariableBinding::UnresolvedType;
20922087

2093-
Type convertTo = convertType.getType();
2094-
2088+
// If the target requires an optional of some type, form a new appropriate
2089+
// type variable and update the target's type with an optional of that
2090+
// type variable.
20952091
if (target.isOptionalSomePatternInit()) {
2096-
assert(!convertTo && "convertType and type check options conflict");
2092+
assert(!target.getExprContextualType() &&
2093+
"some pattern cannot have contextual type pre-configured");
20972094
auto *convertTypeLocator =
20982095
cs.getConstraintLocator(expr, LocatorPathElt::ContextualType());
20992096
Type var = cs.createTypeVariable(convertTypeLocator, TVO_CanBindToNoEscape);
2100-
convertTo = getOptionalType(expr->getLoc(), var);
2101-
} else if (target.getExprContextualTypePurpose()
2102-
== CTP_AutoclosureDefaultParameter) {
2103-
// FIXME: Hack around the convertTo adjustment below, which we want to
2104-
// eliminate.
2105-
convertTo = Type(target.getAsAutoclosureParamType());
2097+
target.setExprConversionType(getOptionalType(expr->getLoc(), var));
21062098
}
21072099

21082100
// Attempt to solve the constraint system.
2109-
SolutionApplicationTarget innerTarget(
2110-
expr, dc, target.getExprContextualTypePurpose(), convertTo,
2111-
target.isDiscardedExpr());
2112-
auto viable = cs.solve(innerTarget, listener, allowFreeTypeVariables);
2101+
auto viable = cs.solve(target, listener, allowFreeTypeVariables);
21132102
if (!viable) {
21142103
target.setExpr(expr);
21152104
return None;
@@ -2120,7 +2109,8 @@ TypeChecker::typeCheckExpression(
21202109
// because they will leak out into arbitrary places in the resultant AST.
21212110
if (options.contains(TypeCheckExprFlags::AllowUnresolvedTypeVariables) &&
21222111
(viable->size() != 1 ||
2123-
(convertType.getType() && convertType.getType()->hasUnresolvedType()))) {
2112+
(target.getExprConversionType() &&
2113+
target.getExprConversionType()->hasUnresolvedType()))) {
21242114
// FIXME: This hack should only be needed for CSDiag.
21252115
unresolvedTypeExprs = true;
21262116
return target;
@@ -2134,10 +2124,6 @@ TypeChecker::typeCheckExpression(
21342124
// Apply the solution to the expression.
21352125
bool performingDiagnostics =
21362126
options.contains(TypeCheckExprFlags::SubExpressionDiagnostics);
2137-
// FIXME: HACK! Copy over the inner target's expression info.
2138-
target.setExpr(innerTarget.getAsExpr());
2139-
if (convertTo.isNull())
2140-
target.setExprConversionType(convertTo);
21412127
auto resultTarget = cs.applySolution(solution, target, performingDiagnostics);
21422128
if (!resultTarget) {
21432129
// Failure already diagnosed, above, as part of applying the solution.

0 commit comments

Comments
 (0)