Skip to content

Commit 4175a01

Browse files
authored
Merge pull request #34206 from xedin/decouple-cs-tc-headers
[Sema] Decouple ConstraintSystem and TypeChecker headers
2 parents d70f35d + 0b648fb commit 4175a01

17 files changed

+161
-131
lines changed

lib/Sema/CSApply.cpp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4301,7 +4301,7 @@ namespace {
43014301
{ Identifier() });
43024302

43034303
auto resultTy = TypeChecker::typeCheckExpression(
4304-
callExpr, cs.DC, valueType, CTP_CannotFail);
4304+
callExpr, cs.DC, /*contextualInfo=*/{valueType, CTP_CannotFail});
43054305
assert(resultTy && "Conversion cannot fail!");
43064306
(void)resultTy;
43074307

@@ -8031,8 +8031,8 @@ static Optional<SolutionApplicationTarget> applySolutionToForEachStmt(
80318031
Expr *convertElementExpr = elementExpr;
80328032
if (TypeChecker::typeCheckExpression(
80338033
convertElementExpr, dc,
8034-
optPatternType,
8035-
CTP_CoerceOperand).isNull()) {
8034+
/*contextualInfo=*/{optPatternType, CTP_CoerceOperand})
8035+
.isNull()) {
80368036
return None;
80378037
}
80388038
elementExpr->setIsPlaceholder(false);

lib/Sema/CSBindings.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//===----------------------------------------------------------------------===//
1616
#include "ConstraintGraph.h"
1717
#include "ConstraintSystem.h"
18+
#include "TypeChecker.h"
1819
#include "llvm/ADT/SetVector.h"
1920
#include <tuple>
2021

lib/Sema/CSClosure.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
//===----------------------------------------------------------------------===//
1818

1919
#include "ConstraintSystem.h"
20+
#include "TypeChecker.h"
21+
2022
using namespace swift;
2123
using namespace swift::constraints;
2224

lib/Sema/CSDiagnostics.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "Constraint.h"
2020
#include "ConstraintSystem.h"
2121
#include "OverloadChoice.h"
22+
#include "TypeChecker.h"
2223
#include "swift/AST/ASTContext.h"
2324
#include "swift/AST/ASTNode.h"
2425
#include "swift/AST/Decl.h"

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include "ConstraintGraph.h"
1717
#include "ConstraintSystem.h"
1818
#include "TypeCheckType.h"
19+
#include "TypeChecker.h"
1920
#include "swift/AST/ASTVisitor.h"
2021
#include "swift/AST/ASTWalker.h"
2122
#include "swift/AST/Expr.h"

lib/Sema/CSRanking.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
//
1616
//===----------------------------------------------------------------------===//
1717
#include "ConstraintSystem.h"
18+
#include "TypeChecker.h"
1819
#include "swift/AST/GenericSignature.h"
1920
#include "swift/AST/ParameterList.h"
2021
#include "swift/AST/ProtocolConformance.h"

lib/Sema/CSSolver.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
#include "ConstraintSystem.h"
1919
#include "SolutionResult.h"
2020
#include "TypeCheckType.h"
21+
#include "TypeChecker.h"
2122
#include "swift/AST/ParameterList.h"
2223
#include "swift/AST/TypeWalker.h"
2324
#include "llvm/ADT/STLExtras.h"

lib/Sema/ConstraintSystem.cpp

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
#include "CSDiagnostics.h"
2121
#include "CSFix.h"
2222
#include "SolutionResult.h"
23+
#include "TypeChecker.h"
2324
#include "TypeCheckType.h"
2425
#include "swift/AST/Initializer.h"
2526
#include "swift/AST/GenericEnvironment.h"
@@ -5215,3 +5216,39 @@ Type ConstraintSystem::getVarType(const VarDecl *var) {
52155216
return HoleType::get(Context, const_cast<VarDecl *>(var));
52165217
});
52175218
}
5219+
5220+
bool ConstraintSystem::isReadOnlyKeyPathComponent(
5221+
const AbstractStorageDecl *storage, SourceLoc referenceLoc) {
5222+
// See whether key paths can store to this component. (Key paths don't
5223+
// get any special power from being formed in certain contexts, such
5224+
// as the ability to assign to `let`s in initialization contexts, so
5225+
// we pass null for the DC to `isSettable` here.)
5226+
if (!getASTContext().isSwiftVersionAtLeast(5)) {
5227+
// As a source-compatibility measure, continue to allow
5228+
// WritableKeyPaths to be formed in the same conditions we did
5229+
// in previous releases even if we should not be able to set
5230+
// the value in this context.
5231+
if (!storage->isSettable(DC)) {
5232+
// A non-settable component makes the key path read-only, unless
5233+
// a reference-writable component shows up later.
5234+
return true;
5235+
}
5236+
} else if (!storage->isSettable(nullptr) ||
5237+
!storage->isSetterAccessibleFrom(DC)) {
5238+
// A non-settable component makes the key path read-only, unless
5239+
// a reference-writable component shows up later.
5240+
return true;
5241+
}
5242+
5243+
// If the setter is unavailable, then the keypath ought to be read-only
5244+
// in this context.
5245+
if (auto setter = storage->getOpaqueAccessor(AccessorKind::Set)) {
5246+
auto maybeUnavail =
5247+
TypeChecker::checkDeclarationAvailability(setter, referenceLoc, DC);
5248+
if (maybeUnavail.hasValue()) {
5249+
return true;
5250+
}
5251+
}
5252+
5253+
return false;
5254+
}

lib/Sema/ConstraintSystem.h

Lines changed: 85 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,20 @@
2424
#include "ConstraintGraphScope.h"
2525
#include "ConstraintLocator.h"
2626
#include "OverloadChoice.h"
27-
#include "TypeChecker.h"
27+
#include "SolutionResult.h"
28+
#include "swift/AST/ASTContext.h"
2829
#include "swift/AST/ASTNode.h"
2930
#include "swift/AST/ASTVisitor.h"
3031
#include "swift/AST/ASTWalker.h"
32+
#include "swift/AST/AnyFunctionRef.h"
33+
#include "swift/AST/DiagnosticsSema.h"
3134
#include "swift/AST/NameLookup.h"
3235
#include "swift/AST/PropertyWrappers.h"
3336
#include "swift/AST/Types.h"
3437
#include "swift/Basic/Debug.h"
3538
#include "swift/Basic/LLVM.h"
3639
#include "swift/Basic/OptionSet.h"
40+
#include "llvm/ADT/MapVector.h"
3741
#include "llvm/ADT/PointerUnion.h"
3842
#include "llvm/ADT/STLExtras.h"
3943
#include "llvm/ADT/SetOperations.h"
@@ -49,15 +53,32 @@
4953
namespace swift {
5054

5155
class Expr;
56+
class FuncDecl;
57+
class BraseStmt;
58+
enum class TypeCheckExprFlags;
5259

5360
namespace constraints {
5461

5562
class ConstraintGraph;
5663
class ConstraintGraphNode;
5764
class ConstraintSystem;
65+
class SolutionApplicationTarget;
5866

5967
} // end namespace constraints
6068

69+
// Forward declare some TypeChecker related functions
70+
// so they could be made friends of ConstraintSystem.
71+
namespace TypeChecker {
72+
73+
Optional<BraceStmt *> applyFunctionBuilderBodyTransform(FuncDecl *func,
74+
Type builderType);
75+
76+
Optional<constraints::SolutionApplicationTarget>
77+
typeCheckExpression(constraints::SolutionApplicationTarget &target,
78+
OptionSet<TypeCheckExprFlags> options);
79+
80+
} // end namespace TypeChecker
81+
6182
} // end namespace swift
6283

6384
/// Allocate memory within the given constraint system.
@@ -66,6 +87,57 @@ void *operator new(size_t bytes, swift::constraints::ConstraintSystem& cs,
6687

6788
namespace swift {
6889

90+
/// This specifies the purpose of the contextual type, when specified to
91+
/// typeCheckExpression. This is used for diagnostic generation to produce more
92+
/// specified error messages when the conversion fails.
93+
///
94+
enum ContextualTypePurpose {
95+
CTP_Unused, ///< No contextual type is specified.
96+
CTP_Initialization, ///< Pattern binding initialization.
97+
CTP_ReturnStmt, ///< Value specified to a 'return' statement.
98+
CTP_ReturnSingleExpr, ///< Value implicitly returned from a function.
99+
CTP_YieldByValue, ///< By-value yield operand.
100+
CTP_YieldByReference, ///< By-reference yield operand.
101+
CTP_ThrowStmt, ///< Value specified to a 'throw' statement.
102+
CTP_EnumCaseRawValue, ///< Raw value specified for "case X = 42" in enum.
103+
CTP_DefaultParameter, ///< Default value in parameter 'foo(a : Int = 42)'.
104+
105+
/// Default value in @autoclosure parameter
106+
/// 'foo(a : @autoclosure () -> Int = 42)'.
107+
CTP_AutoclosureDefaultParameter,
108+
109+
CTP_CalleeResult, ///< Constraint is placed on the result of a callee.
110+
CTP_CallArgument, ///< Call to function or operator requires type.
111+
CTP_ClosureResult, ///< Closure result expects a specific type.
112+
CTP_ArrayElement, ///< ArrayExpr wants elements to have a specific type.
113+
CTP_DictionaryKey, ///< DictionaryExpr keys should have a specific type.
114+
CTP_DictionaryValue, ///< DictionaryExpr values should have a specific type.
115+
CTP_CoerceOperand, ///< CoerceExpr operand coerced to specific type.
116+
CTP_AssignSource, ///< AssignExpr source operand coerced to result type.
117+
CTP_SubscriptAssignSource, ///< AssignExpr source operand coerced to subscript
118+
///< result type.
119+
CTP_Condition, ///< Condition expression of various statements e.g.
120+
///< `if`, `for`, `while` etc.
121+
CTP_ForEachStmt, ///< "expression/sequence" associated with 'for-in' loop
122+
///< is expected to conform to 'Sequence' protocol.
123+
CTP_WrappedProperty, ///< Property type expected to match 'wrappedValue' type
124+
CTP_ComposedPropertyWrapper, ///< Composed wrapper type expected to match
125+
///< former 'wrappedValue' type
126+
127+
CTP_CannotFail, ///< Conversion can never fail. abort() if it does.
128+
};
129+
130+
/// Specify how we handle the binding of underconstrained (free) type variables
131+
/// within a solution to a constraint system.
132+
enum class FreeTypeVariableBinding {
133+
/// Disallow any binding of such free type variables.
134+
Disallow,
135+
/// Allow the free type variables to persist in the solution.
136+
Allow,
137+
/// Bind the type variables to UnresolvedType to represent the ambiguity.
138+
UnresolvedType
139+
};
140+
69141
namespace constraints {
70142

71143
/// Describes the algorithm to use for trailing closure matching.
@@ -857,6 +929,14 @@ struct ContextualTypeInfo {
857929
TypeLoc typeLoc;
858930
ContextualTypePurpose purpose;
859931

932+
ContextualTypeInfo() : typeLoc(TypeLoc()), purpose(CTP_Unused) {}
933+
934+
ContextualTypeInfo(Type contextualTy, ContextualTypePurpose purpose)
935+
: typeLoc(TypeLoc::withoutLoc(contextualTy)), purpose(purpose) {}
936+
937+
ContextualTypeInfo(TypeLoc typeLoc, ContextualTypePurpose purpose)
938+
: typeLoc(typeLoc), purpose(purpose) {}
939+
860940
Type getType() const { return typeLoc.getType(); }
861941
};
862942

@@ -2671,9 +2751,10 @@ class ConstraintSystem {
26712751
friend Optional<BraceStmt *>
26722752
swift::TypeChecker::applyFunctionBuilderBodyTransform(FuncDecl *func,
26732753
Type builderType);
2754+
26742755
friend Optional<SolutionApplicationTarget>
2675-
swift::TypeChecker::typeCheckExpression(SolutionApplicationTarget &target,
2676-
TypeCheckExprOptions options);
2756+
swift::TypeChecker::typeCheckExpression(
2757+
SolutionApplicationTarget &target, OptionSet<TypeCheckExprFlags> options);
26772758

26782759
/// Emit the fixes computed as part of the solution, returning true if we were
26792760
/// able to emit an error message, or false if none of the fixits worked out.
@@ -4912,41 +4993,7 @@ class ConstraintSystem {
49124993
llvm::function_ref<bool(Constraint *)> pred);
49134994

49144995
bool isReadOnlyKeyPathComponent(const AbstractStorageDecl *storage,
4915-
SourceLoc referenceLoc) {
4916-
// See whether key paths can store to this component. (Key paths don't
4917-
// get any special power from being formed in certain contexts, such
4918-
// as the ability to assign to `let`s in initialization contexts, so
4919-
// we pass null for the DC to `isSettable` here.)
4920-
if (!getASTContext().isSwiftVersionAtLeast(5)) {
4921-
// As a source-compatibility measure, continue to allow
4922-
// WritableKeyPaths to be formed in the same conditions we did
4923-
// in previous releases even if we should not be able to set
4924-
// the value in this context.
4925-
if (!storage->isSettable(DC)) {
4926-
// A non-settable component makes the key path read-only, unless
4927-
// a reference-writable component shows up later.
4928-
return true;
4929-
}
4930-
} else if (!storage->isSettable(nullptr) ||
4931-
!storage->isSetterAccessibleFrom(DC)) {
4932-
// A non-settable component makes the key path read-only, unless
4933-
// a reference-writable component shows up later.
4934-
return true;
4935-
}
4936-
4937-
// If the setter is unavailable, then the keypath ought to be read-only
4938-
// in this context.
4939-
if (auto setter = storage->getOpaqueAccessor(AccessorKind::Set)) {
4940-
auto maybeUnavail = TypeChecker::checkDeclarationAvailability(setter,
4941-
referenceLoc,
4942-
DC);
4943-
if (maybeUnavail.hasValue()) {
4944-
return true;
4945-
}
4946-
}
4947-
4948-
return false;
4949-
}
4996+
SourceLoc referenceLoc);
49504997

49514998
public:
49524999
// Given a type variable, attempt to find the disjunction of

lib/Sema/DebuggerTestingTransform.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -244,7 +244,8 @@ class DebuggerTestingTransform : public ASTWalker {
244244
// TODO: typeCheckExpression() seems to assign types to everything here,
245245
// but may not be sufficient in some cases.
246246
Expr *FinalExpr = ClosureCall;
247-
if (!TypeChecker::typeCheckExpression(FinalExpr, getCurrentDeclContext()))
247+
if (!TypeChecker::typeCheckExpression(FinalExpr, getCurrentDeclContext(),
248+
/*contextualInfo=*/{}))
248249
llvm::report_fatal_error("Could not type-check instrumentation");
249250

250251
// Captures have to be computed after the closure is type-checked. This

lib/Sema/InstrumenterSupport.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,7 +119,7 @@ bool InstrumenterBase::doTypeCheckImpl(ASTContext &Ctx, DeclContext *DC,
119119
DiagnosticSuppression suppression(Ctx.Diags);
120120
ErrorGatherer errorGatherer(Ctx.Diags);
121121

122-
TypeChecker::typeCheckExpression(parsedExpr, DC);
122+
TypeChecker::typeCheckExpression(parsedExpr, DC, /*contextualInfo=*/{});
123123

124124
if (parsedExpr) {
125125
ErrorFinder errorFinder;

lib/Sema/InstrumenterSupport.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//===----------------------------------------------------------------------===//
1717

1818
#include "TypeChecker.h"
19-
2019
#include "swift/AST/ASTWalker.h"
2120

2221
namespace swift {

lib/Sema/TypeCheckCodeCompletion.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -962,8 +962,7 @@ bool swift::typeCheckExpression(DeclContext *DC, Expr *&parsedExpr) {
962962
parsedExpr = parsedExpr->walk(SanitizeExpr(ctx, /*shouldReusePrecheckedType=*/false));
963963

964964
DiagnosticSuppression suppression(ctx.Diags);
965-
auto resultTy = TypeChecker::typeCheckExpression(parsedExpr, DC, Type(),
966-
CTP_Unused);
965+
auto resultTy = TypeChecker::typeCheckExpression(parsedExpr, DC);
967966
return !resultTy;
968967
}
969968

lib/Sema/TypeCheckConstraints.cpp

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -300,11 +300,10 @@ void constraints::performSyntacticDiagnosticsForTarget(
300300

301301
#pragma mark High-level entry points
302302
Type TypeChecker::typeCheckExpression(Expr *&expr, DeclContext *dc,
303-
Type convertType,
304-
ContextualTypePurpose convertTypePurpose,
303+
ContextualTypeInfo contextualInfo,
305304
TypeCheckExprOptions options) {
306305
SolutionApplicationTarget target(
307-
expr, dc, convertTypePurpose, convertType,
306+
expr, dc, contextualInfo.purpose, contextualInfo.getType(),
308307
options.contains(TypeCheckExprFlags::IsDiscarded));
309308
auto resultTarget = typeCheckExpression(target, options);
310309
if (!resultTarget) {
@@ -422,9 +421,10 @@ Type TypeChecker::typeCheckParameterDefault(Expr *&defaultValue,
422421
DeclContext *DC, Type paramType,
423422
bool isAutoClosure) {
424423
assert(paramType && !paramType->hasError());
425-
return typeCheckExpression(
426-
defaultValue, DC, paramType,
427-
isAutoClosure ? CTP_AutoclosureDefaultParameter : CTP_DefaultParameter);
424+
return typeCheckExpression(defaultValue, DC, /*contextualInfo=*/
425+
{paramType, isAutoClosure
426+
? CTP_AutoclosureDefaultParameter
427+
: CTP_DefaultParameter});
428428
}
429429

430430
bool TypeChecker::typeCheckBinding(
@@ -593,7 +593,8 @@ bool TypeChecker::typeCheckCondition(Expr *&expr, DeclContext *dc) {
593593
// If this expression is already typechecked and has type Bool, then just
594594
// re-typecheck it.
595595
if (expr->getType() && expr->getType()->isBool()) {
596-
auto resultTy = TypeChecker::typeCheckExpression(expr, dc);
596+
auto resultTy =
597+
TypeChecker::typeCheckExpression(expr, dc);
597598
return !resultTy;
598599
}
599600

@@ -602,8 +603,8 @@ bool TypeChecker::typeCheckCondition(Expr *&expr, DeclContext *dc) {
602603
return true;
603604

604605
auto resultTy = TypeChecker::typeCheckExpression(
605-
expr, dc, boolDecl->getDeclaredInterfaceType(),
606-
CTP_Condition);
606+
expr, dc,
607+
/*contextualInfo=*/{boolDecl->getDeclaredInterfaceType(), CTP_Condition});
607608
return !resultTy;
608609
}
609610

0 commit comments

Comments
 (0)