Skip to content

Commit a64ba23

Browse files
committed
[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.
1 parent 61d73d2 commit a64ba23

File tree

10 files changed

+151
-146
lines changed

10 files changed

+151
-146
lines changed

include/swift/Sema/Constraint.h

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "swift/AST/TypeLoc.h"
2626
#include "swift/Basic/Debug.h"
2727
#include "swift/Sema/ConstraintLocator.h"
28+
#include "swift/Sema/ContextualTypeInfo.h"
2829
#include "swift/Sema/OverloadChoice.h"
2930
#include "llvm/ADT/ArrayRef.h"
3031
#include "llvm/ADT/ilist.h"
@@ -50,23 +51,6 @@ class ConstraintLocator;
5051
class ConstraintSystem;
5152
enum class TrailingClosureMatching;
5253

53-
/// Describes contextual type information about a particular element
54-
/// (expression, statement etc.) within a constraint system.
55-
struct ContextualTypeInfo {
56-
TypeLoc typeLoc;
57-
ContextualTypePurpose purpose;
58-
59-
ContextualTypeInfo() : typeLoc(TypeLoc()), purpose(CTP_Unused) {}
60-
61-
ContextualTypeInfo(Type contextualTy, ContextualTypePurpose purpose)
62-
: typeLoc(TypeLoc::withoutLoc(contextualTy)), purpose(purpose) {}
63-
64-
ContextualTypeInfo(TypeLoc typeLoc, ContextualTypePurpose purpose)
65-
: typeLoc(typeLoc), purpose(purpose) {}
66-
67-
Type getType() const { return typeLoc.getType(); }
68-
};
69-
7054
/// Describes the kind of constraint placed on one or more types.
7155
enum class ConstraintKind : char {
7256
/// The two types must be bound to the same type. This is the only

include/swift/Sema/ConstraintSystem.h

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3114,12 +3114,11 @@ class ConstraintSystem {
31143114
return E;
31153115
}
31163116

3117-
void setContextualType(ASTNode node, TypeLoc T,
3118-
ContextualTypePurpose purpose) {
3117+
void setContextualInfo(ASTNode node, ContextualTypeInfo info) {
31193118
assert(bool(node) && "Expected non-null expression!");
31203119
assert(contextualTypes.count(node) == 0 &&
31213120
"Already set this contextual type");
3122-
contextualTypes[node] = {{T, purpose}, Type()};
3121+
contextualTypes[node] = {info, Type()};
31233122
}
31243123

31253124
llvm::Optional<ContextualTypeInfo> getContextualTypeInfo(ASTNode node) const {
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
//===--- ContextualTypeInfo.h - Contextual Type Info ------------*- C++ -*-===//
2+
//
3+
// This source file is part of the Swift.org open source project
4+
//
5+
// Copyright (c) 2023 Apple Inc. and the Swift project authors
6+
// Licensed under Apache License v2.0 with Runtime Library Exception
7+
//
8+
// See https://swift.org/LICENSE.txt for license information
9+
// See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors
10+
//
11+
//===----------------------------------------------------------------------===//
12+
//
13+
// This file provides the \c ContextualTypeInfo class.
14+
//
15+
//===----------------------------------------------------------------------===//
16+
17+
#ifndef SWIFT_SEMA_CONTEXTUAL_TYPE_INFO_H
18+
#define SWIFT_SEMA_CONTEXTUAL_TYPE_INFO_H
19+
20+
#include "swift/AST/TypeLoc.h"
21+
#include "swift/Sema/ConstraintLocator.h"
22+
23+
namespace swift {
24+
namespace constraints {
25+
26+
/// Describes contextual type information about a particular element
27+
/// (expression, statement etc.) within a constraint system.
28+
struct ContextualTypeInfo {
29+
TypeLoc typeLoc;
30+
ContextualTypePurpose purpose;
31+
32+
/// The locator for the contextual type conversion constraint, or
33+
/// \c nullptr to use the default locator which is anchored directly on
34+
/// the expression.
35+
ConstraintLocator *locator;
36+
37+
ContextualTypeInfo()
38+
: typeLoc(TypeLoc()), purpose(CTP_Unused), locator(nullptr) {}
39+
40+
ContextualTypeInfo(Type contextualTy, ContextualTypePurpose purpose,
41+
ConstraintLocator *locator = nullptr)
42+
: typeLoc(TypeLoc::withoutLoc(contextualTy)), purpose(purpose),
43+
locator(locator) {}
44+
45+
ContextualTypeInfo(TypeLoc typeLoc, ContextualTypePurpose purpose,
46+
ConstraintLocator *locator = nullptr)
47+
: typeLoc(typeLoc), purpose(purpose), locator(locator) {}
48+
49+
Type getType() const { return typeLoc.getType(); }
50+
};
51+
52+
} // end namespace constraints
53+
} // end namespace swift
54+
55+
#endif // SWIFT_SEMA_CONTEXTUAL_TYPE_INFO_H

include/swift/Sema/SyntacticElementTarget.h

Lines changed: 39 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "swift/AST/Stmt.h"
2424
#include "swift/AST/TypeLoc.h"
2525
#include "swift/Sema/ConstraintLocator.h"
26+
#include "swift/Sema/ContextualTypeInfo.h"
2627

2728
namespace swift {
2829

@@ -71,18 +72,8 @@ class SyntacticElementTarget {
7172
/// type-checked.
7273
DeclContext *dc;
7374

74-
// TODO: Fold the 3 below fields into ContextualTypeInfo
75-
76-
/// The purpose of the contextual type.
77-
ContextualTypePurpose contextualPurpose;
78-
79-
/// The type to which the expression should be converted.
80-
TypeLoc convertType;
81-
82-
/// The locator for the contextual type conversion constraint, or
83-
/// \c nullptr to use the default locator which is anchored directly on
84-
/// the expression.
85-
ConstraintLocator *convertTypeLocator;
75+
/// The contextual type info for the expression.
76+
ContextualTypeInfo contextualInfo;
8677

8778
/// When initializing a pattern from the expression, this is the
8879
/// pattern.
@@ -169,26 +160,15 @@ class SyntacticElementTarget {
169160
void maybeApplyPropertyWrapper();
170161

171162
public:
172-
SyntacticElementTarget(Expr *expr, DeclContext *dc,
173-
ContextualTypePurpose contextualPurpose,
174-
Type convertType,
175-
ConstraintLocator *convertTypeLocator,
176-
bool isDiscarded)
177-
: SyntacticElementTarget(expr, dc, contextualPurpose,
178-
TypeLoc::withoutLoc(convertType),
179-
convertTypeLocator, isDiscarded) {}
180-
181163
SyntacticElementTarget(Expr *expr, DeclContext *dc,
182164
ContextualTypePurpose contextualPurpose,
183165
Type convertType, bool isDiscarded)
184-
: SyntacticElementTarget(expr, dc, contextualPurpose, convertType,
185-
/*convertTypeLocator*/ nullptr, isDiscarded) {}
166+
: SyntacticElementTarget(
167+
expr, dc, ContextualTypeInfo(convertType, contextualPurpose),
168+
isDiscarded) {}
186169

187170
SyntacticElementTarget(Expr *expr, DeclContext *dc,
188-
ContextualTypePurpose contextualPurpose,
189-
TypeLoc convertType,
190-
ConstraintLocator *convertTypeLocator,
191-
bool isDiscarded);
171+
ContextualTypeInfo contextualInfo, bool isDiscarded);
192172

193173
SyntacticElementTarget(ClosureExpr *closure, Type convertType) {
194174
kind = Kind::closure;
@@ -375,26 +355,31 @@ class SyntacticElementTarget {
375355
llvm_unreachable("invalid decl context type");
376356
}
377357

378-
ContextualTypePurpose getExprContextualTypePurpose() const {
358+
/// Get the contextual type info for an expression target.
359+
ContextualTypeInfo getExprContextualTypeInfo() const {
379360
assert(kind == Kind::expression);
380-
return expression.contextualPurpose;
361+
return expression.contextualInfo;
362+
}
363+
364+
/// Get the contextual type purpose for an expression target.
365+
ContextualTypePurpose getExprContextualTypePurpose() const {
366+
return getExprContextualTypeInfo().purpose;
381367
}
382368

369+
/// Get the contextual type for an expression target.
383370
Type getExprContextualType() const {
384371
return getExprContextualTypeLoc().getType();
385372
}
386373

374+
/// Get the contextual type for an expression target.
387375
TypeLoc getExprContextualTypeLoc() const {
388-
assert(kind == Kind::expression);
389-
390376
// For an @autoclosure parameter, the conversion type is
391377
// the result of the function type.
392-
if (FunctionType *autoclosureParamType = getAsAutoclosureParamType()) {
393-
return TypeLoc(expression.convertType.getTypeRepr(),
394-
autoclosureParamType->getResult());
395-
}
378+
auto typeLoc = getExprContextualTypeInfo().typeLoc;
379+
if (FunctionType *autoclosureParamType = getAsAutoclosureParamType())
380+
return TypeLoc(typeLoc.getTypeRepr(), autoclosureParamType->getResult());
396381

397-
return expression.convertType;
382+
return typeLoc;
398383
}
399384

400385
/// Retrieve the type to which an expression should be converted, or
@@ -408,33 +393,32 @@ class SyntacticElementTarget {
408393
/// Retrieve the conversion type locator for the expression, or \c nullptr
409394
/// if it has not been set.
410395
ConstraintLocator *getExprConvertTypeLocator() const {
411-
assert(kind == Kind::expression);
412-
return expression.convertTypeLocator;
396+
return getExprContextualTypeInfo().locator;
413397
}
414398

415399
/// Returns the autoclosure parameter type, or \c nullptr if the
416400
/// expression has a different kind of context.
417401
FunctionType *getAsAutoclosureParamType() const {
418-
assert(kind == Kind::expression);
419-
if (expression.contextualPurpose == CTP_AutoclosureDefaultParameter)
420-
return expression.convertType.getType()->castTo<FunctionType>();
402+
if (getExprContextualTypePurpose() == CTP_AutoclosureDefaultParameter)
403+
return getExprContextualTypeInfo().getType()->castTo<FunctionType>();
404+
421405
return nullptr;
422406
}
423407

424408
void setExprConversionType(Type type) {
425409
assert(kind == Kind::expression);
426-
expression.convertType = TypeLoc::withoutLoc(type);
410+
expression.contextualInfo.typeLoc = TypeLoc::withoutLoc(type);
427411
}
428412

429413
void setExprConversionTypeLoc(TypeLoc type) {
430414
assert(kind == Kind::expression);
431-
expression.convertType = type;
415+
expression.contextualInfo.typeLoc = type;
432416
}
433417

434418
/// Whether this target is for an initialization expression and pattern.
435419
bool isForInitialization() const {
436420
return kind == Kind::expression &&
437-
expression.contextualPurpose == CTP_Initialization;
421+
getExprContextualTypePurpose() == CTP_Initialization;
438422
}
439423

440424
/// For a pattern initialization target, retrieve the pattern.
@@ -448,7 +432,7 @@ class SyntacticElementTarget {
448432

449433
ExprPattern *getExprPattern() const {
450434
assert(kind == Kind::expression);
451-
assert(expression.contextualPurpose == CTP_ExprPattern);
435+
assert(getExprContextualTypePurpose() == CTP_ExprPattern);
452436
return cast<ExprPattern>(expression.pattern);
453437
}
454438

@@ -575,11 +559,16 @@ class SyntacticElementTarget {
575559
return;
576560
}
577561

578-
assert(kind == Kind::expression);
579-
assert(expression.contextualPurpose == CTP_Initialization ||
580-
expression.contextualPurpose == CTP_ForEachStmt ||
581-
expression.contextualPurpose == CTP_ForEachSequence ||
582-
expression.contextualPurpose == CTP_ExprPattern);
562+
switch (getExprContextualTypePurpose()) {
563+
case CTP_Initialization:
564+
case CTP_ForEachStmt:
565+
case CTP_ForEachSequence:
566+
case CTP_ExprPattern:
567+
break;
568+
default:
569+
assert(false && "Unexpected contextual type purpose");
570+
break;
571+
}
583572
expression.pattern = pattern;
584573
}
585574

lib/Sema/CSGen.cpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -4334,8 +4334,9 @@ bool ConstraintSystem::generateWrappedPropertyTypeConstraints(
43344334
ConstraintKind::Equal, propertyType, wrappedValueType,
43354335
getConstraintLocator(
43364336
wrappedVar, LocatorPathElt::ContextualType(CTP_WrappedProperty)));
4337-
setContextualType(wrappedVar, TypeLoc::withoutLoc(wrappedValueType),
4338-
CTP_WrappedProperty);
4337+
4338+
ContextualTypeInfo contextInfo(wrappedValueType, CTP_WrappedProperty);
4339+
setContextualInfo(wrappedVar, contextInfo);
43394340
return false;
43404341
}
43414342

@@ -4419,10 +4420,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
44194420
makeIteratorCall, dc, /*patternType=*/Type(), PB, /*index=*/0,
44204421
/*shouldBindPatternsOneWay=*/false);
44214422

4422-
cs.setContextualType(
4423-
sequenceExpr,
4424-
TypeLoc::withoutLoc(sequenceProto->getDeclaredInterfaceType()),
4425-
CTP_ForEachSequence);
4423+
ContextualTypeInfo contextInfo(sequenceProto->getDeclaredInterfaceType(),
4424+
CTP_ForEachSequence);
4425+
cs.setContextualInfo(sequenceExpr, contextInfo);
44264426

44274427
if (cs.generateConstraints(makeIteratorTarget))
44284428
return llvm::None;
@@ -4480,10 +4480,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
44804480
if (!iteratorProto)
44814481
return llvm::None;
44824482

4483-
cs.setContextualType(
4484-
nextRef->getBase(),
4485-
TypeLoc::withoutLoc(iteratorProto->getDeclaredInterfaceType()),
4486-
CTP_ForEachSequence);
4483+
ContextualTypeInfo contextInfo(iteratorProto->getDeclaredInterfaceType(),
4484+
CTP_ForEachSequence);
4485+
cs.setContextualInfo(nextRef->getBase(), contextInfo);
44874486
}
44884487

44894488
SyntacticElementTarget nextTarget(nextCall, dc, CTP_Unused,
@@ -4549,8 +4548,9 @@ generateForEachStmtConstraints(ConstraintSystem &cs,
45494548
return llvm::None;
45504549

45514550
cs.setTargetFor(whereExpr, whereTarget);
4552-
cs.setContextualType(whereExpr, TypeLoc::withoutLoc(boolType),
4553-
CTP_Condition);
4551+
4552+
ContextualTypeInfo contextInfo(boolType, CTP_Condition);
4553+
cs.setContextualInfo(whereExpr, contextInfo);
45544554
}
45554555

45564556
// Populate all of the information for a for-each loop.

lib/Sema/CSSolver.cpp

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,8 @@ void ConstraintSystem::applySolution(const Solution &solution) {
323323

324324
// Add the contextual types.
325325
for (const auto &contextualType : solution.contextualTypes) {
326-
if (!getContextualTypeInfo(contextualType.first)) {
327-
setContextualType(contextualType.first, contextualType.second.typeLoc,
328-
contextualType.second.purpose);
329-
}
326+
if (!getContextualTypeInfo(contextualType.first))
327+
setContextualInfo(contextualType.first, contextualType.second);
330328
}
331329

332330
// Register the statement condition targets.
@@ -1731,8 +1729,7 @@ bool ConstraintSystem::solveForCodeCompletion(
17311729
SyntacticElementTarget &target, SmallVectorImpl<Solution> &solutions) {
17321730
if (auto *expr = target.getAsExpr()) {
17331731
// Tell the constraint system what the contextual type is.
1734-
setContextualType(expr, target.getExprContextualTypeLoc(),
1735-
target.getExprContextualTypePurpose());
1732+
setContextualInfo(expr, target.getExprContextualTypeInfo());
17361733

17371734
// Set up the expression type checker timer.
17381735
Timer.emplace(expr, *this);

0 commit comments

Comments
 (0)