Skip to content

Commit ba6a5e1

Browse files
committed
[ConstraintSystem] Replace special locator for return of single expr function with a flag on contextual type locator
It's only needed in one place in the constraint solver to allow `() -> T` to `() -> ()` and `() -> Never` to `() -> T` for expressions representing return of a single expression functions, so to simplify contextual type handling in diagnostic and other places it would be better to replace dedicated locator kind with a flag on existing `ContextualType`. Resolves: rdar://problem/51641323
1 parent f9324d8 commit ba6a5e1

File tree

7 files changed

+48
-23
lines changed

7 files changed

+48
-23
lines changed

lib/Sema/CSDiag.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2239,7 +2239,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
22392239
CS.TC.isConvertibleTo(srcFT->getResult(), contextualType, CS.DC)) {
22402240

22412241
auto locator =
2242-
CS.getConstraintLocator(expr, ConstraintLocator::ContextualType);
2242+
CS.getConstraintLocator(expr, LocatorPathElt::getContextualType());
22432243
ContextualFailure failure =
22442244
ContextualFailure(nullptr, CS, srcFT, contextualType, locator);
22452245
auto diagnosed = failure.diagnoseAsError();
@@ -2320,7 +2320,7 @@ bool FailureDiagnosis::diagnoseContextualConversionError(
23202320
if (contextualType->isExistentialType()) {
23212321
MissingContextualConformanceFailure failure(
23222322
expr, CS, CTP, exprType, contextualType,
2323-
CS.getConstraintLocator(expr, ConstraintLocator::ContextualType));
2323+
CS.getConstraintLocator(expr, LocatorPathElt::getContextualType()));
23242324
return failure.diagnoseAsError();
23252325
}
23262326

@@ -5687,7 +5687,7 @@ bool FailureDiagnosis::diagnoseClosureExpr(
56875687

56885688
MissingArgumentsFailure failure(
56895689
expr, CS, fnType, inferredArgCount - actualArgCount,
5690-
CS.getConstraintLocator(CE, ConstraintLocator::ContextualType));
5690+
CS.getConstraintLocator(CE, LocatorPathElt::getContextualType()));
56915691
return failure.diagnoseAsError();
56925692
}
56935693

lib/Sema/CSSimplify.cpp

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2935,8 +2935,7 @@ ConstraintSystem::matchTypes(Type type1, Type type2, ConstraintKind kind,
29352935
// literals and expressions representing an implicit return type of the single
29362936
// expression functions.
29372937
if (auto elt = locator.last()) {
2938-
if (elt->getKind() == ConstraintLocator::ClosureResult ||
2939-
elt->getKind() == ConstraintLocator::SingleExprFuncResultType) {
2938+
if (elt->isClosureResult() || elt->isResultOfSingleExprFunction()) {
29402939
if (kind >= ConstraintKind::Subtype &&
29412940
(type1->isUninhabited() || type2->isVoid())) {
29422941
increaseScore(SK_FunctionConversion);
@@ -5405,8 +5404,9 @@ ConstraintSystem::simplifyKeyPathConstraint(Type keyPathTy,
54055404
{rootTy, valueTy});
54065405
// Let's check whether deduced key path type would match
54075406
// expected contextual one.
5408-
return matchTypes(resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
5409-
locator.withPathElement(ConstraintLocator::ContextualType));
5407+
return matchTypes(
5408+
resolvedKPTy, keyPathTy, ConstraintKind::Bind, subflags,
5409+
locator.withPathElement(LocatorPathElt::getContextualType()));
54105410
}
54115411

54125412
ConstraintSystem::SolutionKind

lib/Sema/CSSolver.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1176,10 +1176,10 @@ ConstraintSystem::solveImpl(Expr *&expr,
11761176
if (getContextualTypePurpose() == CTP_YieldByReference)
11771177
constraintKind = ConstraintKind::Bind;
11781178

1179+
bool isForSingleExprFunction =
1180+
getContextualTypePurpose() == CTP_ReturnSingleExpr;
11791181
auto *convertTypeLocator = getConstraintLocator(
1180-
expr, getContextualTypePurpose() == CTP_ReturnSingleExpr
1181-
? ConstraintLocator::SingleExprFuncResultType
1182-
: ConstraintLocator::ContextualType);
1182+
expr, LocatorPathElt::getContextualType(isForSingleExprFunction));
11831183

11841184
if (allowFreeTypeVariables == FreeTypeVariableBinding::UnresolvedType) {
11851185
convertType = convertType.transform([&](Type type) -> Type {

lib/Sema/ConstraintLocator.cpp

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,6 @@ void ConstraintLocator::Profile(llvm::FoldingSetNodeID &id, Expr *anchor,
8282
case KeyPathRoot:
8383
case KeyPathValue:
8484
case KeyPathComponentResult:
85-
case SingleExprFuncResultType:
8685
if (unsigned numValues = numNumericValuesInPathElement(elt.getKind())) {
8786
id.AddInteger(elt.getValue());
8887
if (numValues > 1)
@@ -364,7 +363,10 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
364363
break;
365364

366365
case ContextualType:
367-
out << "contextual type";
366+
if (elt.isResultOfSingleExprFunction())
367+
out << "expected result type of the function with a single expression";
368+
else
369+
out << "contextual type";
368370
break;
369371

370372
case SynthesizedArgument:
@@ -390,9 +392,6 @@ void ConstraintLocator::dump(SourceManager *sm, raw_ostream &out) {
390392
case KeyPathComponentResult:
391393
out << "key path component result";
392394
break;
393-
case SingleExprFuncResultType:
394-
out << " expected result type of the function with a single expression";
395-
break;
396395
}
397396
}
398397
out << ']';

lib/Sema/ConstraintLocator.h

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,8 +135,6 @@ class ConstraintLocator : public llvm::FoldingSetNode {
135135
KeyPathValue,
136136
/// The result type of a key path component. Not used for subscripts.
137137
KeyPathComponentResult,
138-
/// The expected type of the function with a single expression body.
139-
SingleExprFuncResultType,
140138
};
141139

142140
/// Determine the number of numeric values used for the given path
@@ -165,14 +163,13 @@ class ConstraintLocator : public llvm::FoldingSetNode {
165163
case Witness:
166164
case ImplicitlyUnwrappedDisjunctionChoice:
167165
case DynamicLookupResult:
168-
case ContextualType:
169166
case KeyPathType:
170167
case KeyPathRoot:
171168
case KeyPathValue:
172169
case KeyPathComponentResult:
173-
case SingleExprFuncResultType:
174170
return 0;
175171

172+
case ContextualType:
176173
case OpenedGeneric:
177174
case GenericArgument:
178175
case NamedTupleElement:
@@ -240,7 +237,6 @@ class ConstraintLocator : public llvm::FoldingSetNode {
240237
case KeyPathRoot:
241238
case KeyPathValue:
242239
case KeyPathComponentResult:
243-
case SingleExprFuncResultType:
244240
return 0;
245241

246242
case FunctionArgument:
@@ -398,6 +394,10 @@ class ConstraintLocator : public llvm::FoldingSetNode {
398394
return PathElement(base);
399395
}
400396

397+
static PathElement getContextualType(bool isForSingleExprFunction = false) {
398+
return PathElement(ContextualType, isForSingleExprFunction);
399+
}
400+
401401
/// Retrieve the kind of path element.
402402
PathElementKind getKind() const {
403403
switch (static_cast<StoredKind>(storedKind)) {
@@ -506,6 +506,17 @@ class ConstraintLocator : public llvm::FoldingSetNode {
506506
bool isKeyPathComponent() const {
507507
return getKind() == PathElementKind::KeyPathComponent;
508508
}
509+
510+
bool isClosureResult() const {
511+
return getKind() == PathElementKind::ClosureResult;
512+
}
513+
514+
/// Determine whether this element points to the contextual type
515+
/// associated with result of a single expression function.
516+
bool isResultOfSingleExprFunction() const {
517+
return getKind() == PathElementKind::ContextualType ? bool(getValue())
518+
: false;
519+
}
509520
};
510521

511522
/// Return the summary flags for an entire path.

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2219,8 +2219,8 @@ Type TypeChecker::typeCheckExpressionImpl(Expr *&expr, DeclContext *dc,
22192219
Type convertTo = convertType.getType();
22202220
if (options.contains(TypeCheckExprFlags::ExpressionTypeMustBeOptional)) {
22212221
assert(!convertTo && "convertType and type check options conflict");
2222-
auto *convertTypeLocator = cs.getConstraintLocator(
2223-
cs.getConstraintLocator(expr), ConstraintLocator::ContextualType);
2222+
auto *convertTypeLocator =
2223+
cs.getConstraintLocator(expr, LocatorPathElt::getContextualType());
22242224
Type var = cs.createTypeVariable(convertTypeLocator, TVO_CanBindToNoEscape);
22252225
convertTo = getOptionalType(expr->getLoc(), var);
22262226
}
@@ -2604,7 +2604,7 @@ bool TypeChecker::typeCheckBinding(Pattern *&pattern, Expr *&initializer,
26042604

26052605
// Save the locator we're using for the expression.
26062606
Locator =
2607-
cs.getConstraintLocator(expr, ConstraintLocator::ContextualType);
2607+
cs.getConstraintLocator(expr, LocatorPathElt::getContextualType());
26082608

26092609
// Collect constraints from the pattern.
26102610
Type patternType = cs.generateConstraints(pattern, Locator);

test/type/opaque.swift

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -365,3 +365,18 @@ struct OtherGeneric<X, Y, Z> {
365365
var y: GenericWithOpaqueAssoc<Y>.Assoc
366366
var z: GenericWithOpaqueAssoc<Z>.Assoc
367367
}
368+
369+
370+
protocol P_51641323 {
371+
associatedtype T
372+
373+
var foo: Self.T { get }
374+
}
375+
376+
func rdar_51641323() {
377+
struct Foo: P_51641323 {
378+
var foo: some P_51641323 { {} }
379+
// expected-error@-1 {{return type of property 'foo' requires that '() -> ()' conform to 'P_51641323'}}
380+
// expected-note@-2 {{opaque return type declared here}}
381+
}
382+
}

0 commit comments

Comments
 (0)