-
Notifications
You must be signed in to change notification settings - Fork 10.5k
/
Copy pathTypeChecker.h
1851 lines (1608 loc) · 78 KB
/
TypeChecker.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
//===--- TypeChecker.h - Type Checking Class --------------------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2017 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 defines the TypeChecking class.
//
//===----------------------------------------------------------------------===//
#ifndef TYPECHECKING_H
#define TYPECHECKING_H
#include "swift/AST/ASTContext.h"
#include "swift/AST/AccessScope.h"
#include "swift/AST/AnyFunctionRef.h"
#include "swift/AST/Availability.h"
#include "swift/AST/DiagnosticsSema.h"
#include "swift/AST/KnownProtocols.h"
#include "swift/AST/LazyResolver.h"
#include "swift/AST/NameLookup.h"
#include "swift/AST/TypeRefinementContext.h"
#include "swift/Parse/Lexer.h"
#include "swift/Basic/OptionSet.h"
#include "swift/Config.h"
#include "llvm/ADT/SetVector.h"
#include "llvm/ADT/TinyPtrVector.h"
#include <functional>
namespace swift {
class GenericSignatureBuilder;
class NominalTypeDecl;
class NormalProtocolConformance;
class TopLevelContext;
class TypeChecker;
class TypeResolution;
class TypeResolutionOptions;
class TypoCorrectionResults;
class ExprPattern;
enum class TypeResolutionStage : uint8_t;
namespace constraints {
enum class ConstraintKind : char;
enum class SolutionKind : char;
class ConstraintSystem;
class Solution;
}
/// A mapping from substitutable types to the protocol-conformance
/// mappings for those types.
using ConformanceMap =
llvm::DenseMap<SubstitutableType *, SmallVector<ProtocolConformance *, 2>>;
/// Special-case type checking semantics for certain declarations.
enum class DeclTypeCheckingSemantics {
/// A normal declaration.
Normal,
/// The type(of:) declaration, which performs a "dynamic type" operation,
/// with different behavior for existential and non-existential arguments.
TypeOf,
/// The withoutActuallyEscaping(_:do:) declaration, which makes a nonescaping
/// closure temporarily escapable.
WithoutActuallyEscaping,
/// The _openExistential(_:do:) declaration, which extracts the value inside
/// an existential and passes it as a value of its own dynamic type.
OpenExistential,
};
/// The result of name lookup.
class LookupResult {
private:
/// The set of results found.
SmallVector<LookupResultEntry, 4> Results;
size_t IndexOfFirstOuterResult = 0;
public:
LookupResult() {}
explicit LookupResult(const SmallVectorImpl<LookupResultEntry> &Results,
size_t indexOfFirstOuterResult)
: Results(Results.begin(), Results.end()),
IndexOfFirstOuterResult(indexOfFirstOuterResult) {}
using iterator = SmallVectorImpl<LookupResultEntry>::iterator;
iterator begin() { return Results.begin(); }
iterator end() {
return Results.begin() + IndexOfFirstOuterResult;
}
unsigned size() const { return innerResults().size(); }
bool empty() const { return innerResults().empty(); }
ArrayRef<LookupResultEntry> innerResults() const {
return llvm::makeArrayRef(Results).take_front(IndexOfFirstOuterResult);
}
ArrayRef<LookupResultEntry> outerResults() const {
return llvm::makeArrayRef(Results).drop_front(IndexOfFirstOuterResult);
}
const LookupResultEntry& operator[](unsigned index) const {
return Results[index];
}
LookupResultEntry front() const { return innerResults().front(); }
LookupResultEntry back() const { return innerResults().back(); }
/// Add a result to the set of results.
void add(LookupResultEntry result, bool isOuter) {
Results.push_back(result);
if (!isOuter) {
IndexOfFirstOuterResult++;
assert(IndexOfFirstOuterResult == Results.size() &&
"found an outer result before an inner one");
} else {
assert(IndexOfFirstOuterResult > 0 &&
"found outer results without an inner one");
}
}
void clear() { Results.clear(); }
/// Determine whether the result set is nonempty.
explicit operator bool() const {
return !empty();
}
TypeDecl *getSingleTypeResult() const {
if (size() != 1)
return nullptr;
return dyn_cast<TypeDecl>(front().getValueDecl());
}
/// Filter out any results that aren't accepted by the given predicate.
void
filter(llvm::function_ref<bool(LookupResultEntry, /*isOuter*/ bool)> pred);
/// Shift down results by dropping inner results while keeping outer
/// results (if any), the innermost of which are recogized as inner
/// results afterwards.
void shiftDownResults();
};
/// An individual result of a name lookup for a type.
struct LookupTypeResultEntry {
TypeDecl *Member;
Type MemberType;
/// The associated type that the Member/MemberType were inferred for, but only
/// if inference happened when creating this entry.
AssociatedTypeDecl *InferredAssociatedType;
};
/// The result of name lookup for types.
class LookupTypeResult {
/// The set of results found.
SmallVector<LookupTypeResultEntry, 4> Results;
friend class TypeChecker;
public:
using iterator = SmallVectorImpl<LookupTypeResultEntry>::iterator;
iterator begin() { return Results.begin(); }
iterator end() { return Results.end(); }
unsigned size() const { return Results.size(); }
LookupTypeResultEntry operator[](unsigned index) const {
return Results[index];
}
LookupTypeResultEntry front() const { return Results.front(); }
LookupTypeResultEntry back() const { return Results.back(); }
/// Add a result to the set of results.
void addResult(LookupTypeResultEntry result) { Results.push_back(result); }
/// Determine whether this result set is ambiguous.
bool isAmbiguous() const {
return Results.size() > 1;
}
/// Determine whether the result set is nonempty.
explicit operator bool() const {
return !Results.empty();
}
};
/// This specifies the purpose of the contextual type, when specified to
/// typeCheckExpression. This is used for diagnostic generation to produce more
/// specified error messages when the conversion fails.
///
enum ContextualTypePurpose {
CTP_Unused, ///< No contextual type is specified.
CTP_Initialization, ///< Pattern binding initialization.
CTP_ReturnStmt, ///< Value specified to a 'return' statement.
CTP_ReturnSingleExpr, ///< Value implicitly returned from a function.
CTP_YieldByValue, ///< By-value yield operand.
CTP_YieldByReference, ///< By-reference yield operand.
CTP_ThrowStmt, ///< Value specified to a 'throw' statement.
CTP_EnumCaseRawValue, ///< Raw value specified for "case X = 42" in enum.
CTP_DefaultParameter, ///< Default value in parameter 'foo(a : Int = 42)'.
CTP_CalleeResult, ///< Constraint is placed on the result of a callee.
CTP_CallArgument, ///< Call to function or operator requires type.
CTP_ClosureResult, ///< Closure result expects a specific type.
CTP_ArrayElement, ///< ArrayExpr wants elements to have a specific type.
CTP_DictionaryKey, ///< DictionaryExpr keys should have a specific type.
CTP_DictionaryValue, ///< DictionaryExpr values should have a specific type.
CTP_CoerceOperand, ///< CoerceExpr operand coerced to specific type.
CTP_AssignSource, ///< AssignExpr source operand coerced to result type.
CTP_SubscriptAssignSource, ///< AssignExpr source operand coerced to subscript
///< result type.
CTP_Condition, ///< Condition expression of various statements e.g.
///< `if`, `for`, `while` etc.
CTP_ForEachStmt, ///< "expression/sequence" associated with 'for-in' loop
///< is expected to conform to 'Sequence' protocol.
CTP_CannotFail, ///< Conversion can never fail. abort() if it does.
};
/// Flags that can be used to control name lookup.
enum class TypeCheckExprFlags {
/// Whether we know that the result of the expression is discarded. This
/// disables constraints forcing an lvalue result to be loadable.
IsDiscarded = 0x01,
/// Whether the client wants to disable the structural syntactic restrictions
/// that we force for style or other reasons.
DisableStructuralChecks = 0x02,
/// If set, the client wants a best-effort solution to the constraint system,
/// but can tolerate a solution where all of the constraints are solved, but
/// not all type variables have been determined. In this case, the constraint
/// system is not applied to the expression AST, but the ConstraintSystem is
/// left in-tact.
AllowUnresolvedTypeVariables = 0x08,
/// If set, the 'convertType' specified to typeCheckExpression should not
/// produce a conversion constraint, but it should be used to guide the
/// solution in terms of performance optimizations of the solver, and in terms
/// of guiding diagnostics.
ConvertTypeIsOnlyAHint = 0x10,
/// If set, this expression isn't embedded in a larger expression or
/// statement. This should only be used for syntactic restrictions, and should
/// not affect type checking itself.
IsExprStmt = 0x20,
/// If set, this expression is being re-type checked as part of diagnostics,
/// and so we should not visit bodies of non-single expression closures.
SkipMultiStmtClosures = 0x40,
/// This is an inout yield.
IsInOutYield = 0x100,
/// If set, a conversion constraint should be specified so that the result of
/// the expression is an optional type.
ExpressionTypeMustBeOptional = 0x200,
/// FIXME(diagnostics): Once diagnostics are completely switched to new
/// framework, this flag could be removed as obsolete.
///
/// If set, this is a sub-expression, and it is being re-typechecked
/// as part of the expression diagnostics, which is attempting to narrow
/// down failure location.
SubExpressionDiagnostics = 0x400,
/// If set, the 'convertType' specified to typeCheckExpression is the opaque
/// return type of the declaration being checked. The archetype should be
/// opened into a type variable to provide context to the expression, and
/// the resulting type will be a candidate for binding the underlying
/// type.
ConvertTypeIsOpaqueReturnType = 0x800,
};
using TypeCheckExprOptions = OptionSet<TypeCheckExprFlags>;
inline TypeCheckExprOptions operator|(TypeCheckExprFlags flag1,
TypeCheckExprFlags flag2) {
return TypeCheckExprOptions(flag1) | flag2;
}
/// Flags that can be used to control name lookup.
enum class NameLookupFlags {
/// Whether we know that this lookup is always a private dependency.
KnownPrivate = 0x01,
/// Whether name lookup should be able to find protocol members.
ProtocolMembers = 0x02,
/// Whether we should map the requirement to the witness if we
/// find a protocol member and the base type is a concrete type.
///
/// If this is not set but ProtocolMembers is set, we will
/// find protocol extension members, but not protocol requirements
/// that do not yet have a witness (such as inferred associated
/// types, or witnesses for derived conformances).
PerformConformanceCheck = 0x04,
/// Whether to perform 'dynamic' name lookup that finds @objc
/// members of any class or protocol.
DynamicLookup = 0x08,
/// Whether to ignore access control for this lookup, allowing inaccessible
/// results to be returned.
IgnoreAccessControl = 0x10,
/// Whether to include results from outside the innermost scope that has a
/// result.
IncludeOuterResults = 0x20,
/// Whether to consider synonyms declared through @_implements().
IncludeAttributeImplements = 0x40,
};
/// A set of options that control name lookup.
using NameLookupOptions = OptionSet<NameLookupFlags>;
inline NameLookupOptions operator|(NameLookupFlags flag1,
NameLookupFlags flag2) {
return NameLookupOptions(flag1) | flag2;
}
/// Default options for member name lookup.
const NameLookupOptions defaultMemberLookupOptions
= NameLookupFlags::ProtocolMembers |
NameLookupFlags::PerformConformanceCheck;
/// Default options for constructor lookup.
const NameLookupOptions defaultConstructorLookupOptions
= NameLookupFlags::ProtocolMembers |
NameLookupFlags::PerformConformanceCheck;
/// Default options for member type lookup.
const NameLookupOptions defaultMemberTypeLookupOptions
= NameLookupFlags::ProtocolMembers |
NameLookupFlags::PerformConformanceCheck;
/// Default options for unqualified name lookup.
const NameLookupOptions defaultUnqualifiedLookupOptions
= NameLookupFlags::ProtocolMembers |
NameLookupFlags::PerformConformanceCheck;
/// Describes the result of comparing two entities, of which one may be better
/// or worse than the other, or they are unordered.
enum class Comparison {
/// Neither entity is better than the other.
Unordered,
/// The first entity is better than the second.
Better,
/// The first entity is worse than the second.
Worse
};
/// Specify how we handle the binding of underconstrained (free) type variables
/// within a solution to a constraint system.
enum class FreeTypeVariableBinding {
/// Disallow any binding of such free type variables.
Disallow,
/// Allow the free type variables to persist in the solution.
Allow,
/// Bind the type variables to UnresolvedType to represent the ambiguity.
UnresolvedType
};
/// An abstract interface that can interact with the type checker during
/// the type checking of a particular expression.
class ExprTypeCheckListener {
public:
virtual ~ExprTypeCheckListener();
/// Callback invoked once the constraint system has been constructed.
///
/// \param cs The constraint system that has been constructed.
///
/// \param expr The pre-checked expression from which the constraint system
/// was generated.
///
/// \returns true if an error occurred that is not itself part of the
/// constraint system, or false otherwise.
virtual bool builtConstraints(constraints::ConstraintSystem &cs, Expr *expr);
/// Callback invoked once a solution has been found.
///
/// The callback may further alter the expression, returning either a
/// new expression (to replace the result) or a null pointer to indicate
/// failure.
virtual Expr *foundSolution(constraints::Solution &solution, Expr *expr);
/// Callback invokes once the chosen solution has been applied to the
/// expression.
///
/// The callback may further alter the expression, returning either a
/// new expression (to replace the result) or a null pointer to indicate
/// failure.
virtual Expr *appliedSolution(constraints::Solution &solution,
Expr *expr);
/// Callback invoked if expression is structurally unsound and can't
/// be correctly processed by the constraint solver.
virtual void preCheckFailed(Expr *expr);
/// Callback invoked if constraint system failed to generate
/// constraints for a given expression.
virtual void constraintGenerationFailed(Expr *expr);
/// Callback invoked if application of chosen solution to
/// expression has failed.
virtual void applySolutionFailed(constraints::Solution &solution, Expr *expr);
};
/// A conditional conformance that implied some other requirements. That is, \c
/// ConformingType conforming to \c Protocol may have required additional
/// requirements to be satisfied.
///
/// This is designed to be used in a stack of such requirements, which can be
/// formatted with \c diagnoseConformanceStack.
struct ParentConditionalConformance {
Type ConformingType;
ProtocolType *Protocol;
/// Format the stack \c conformances as a series of notes that trace a path of
/// conditional conformances that lead to some other failing requirement (that
/// is not in \c conformances).
///
/// The end of \c conformances is the active end of the stack, i.e. \c
/// conformances[0] is a conditional conformance that requires \c
/// conformances[1], etc.
static void
diagnoseConformanceStack(DiagnosticEngine &diags, SourceLoc location,
ArrayRef<ParentConditionalConformance> conformances);
};
/// An abstract interface that is used by `checkGenericArguments`.
class GenericRequirementsCheckListener {
public:
virtual ~GenericRequirementsCheckListener();
/// Callback invoked before trying to check generic requirement placed
/// between given types. Note: if either of the types assigned to the
/// requirement is generic parameter or dependent member, this callback
/// method is going to get their substitutions.
///
/// \param kind The kind of generic requirement to check.
///
/// \param first The left-hand side type assigned to the requirement,
/// possibly represented by its generic substitute.
///
/// \param second The right-hand side type assigned to the requirement,
/// possibly represented by its generic substitute.
///
///
/// \returns true if it's ok to validate requirement, false otherwise.
virtual bool shouldCheck(RequirementKind kind, Type first, Type second);
/// Callback to report the result of a satisfied conformance requirement.
///
/// \param depTy The dependent type, from the signature.
/// \param replacementTy The type \c depTy was replaced with.
/// \param conformance The conformance itself.
virtual void satisfiedConformance(Type depTy, Type replacementTy,
ProtocolConformanceRef conformance);
/// Callback to diagnose problem with unsatisfied generic requirement.
///
/// \param req The unsatisfied generic requirement.
///
/// \param first The left-hand side type assigned to the requirement,
/// possibly represented by its generic substitute.
///
/// \param second The right-hand side type assigned to the requirement,
/// possibly represented by its generic substitute.
///
/// \returns true if problem has been diagnosed, false otherwise.
virtual bool diagnoseUnsatisfiedRequirement(
const Requirement &req, Type first, Type second,
ArrayRef<ParentConditionalConformance> parents);
};
/// The result of `checkGenericRequirement`.
enum class RequirementCheckResult {
Success, Failure, SubstitutionFailure
};
/// Flags that control protocol conformance checking.
enum class ConformanceCheckFlags {
/// Whether we're performing the check from within an expression.
InExpression = 0x01,
/// Whether to suppress dependency tracking entirely.
///
/// FIXME: This deals with some oddities with the
/// _ObjectiveCBridgeable conformances.
SuppressDependencyTracking = 0x02,
/// Whether to skip the check for any conditional conformances.
///
/// When set, the caller takes responsibility for any
/// conditional requirements required for the conformance to be
/// correctly used. Otherwise (the default), all of the conditional
/// requirements will be checked.
SkipConditionalRequirements = 0x04,
};
/// Options that control protocol conformance checking.
using ConformanceCheckOptions = OptionSet<ConformanceCheckFlags>;
inline ConformanceCheckOptions operator|(ConformanceCheckFlags lhs,
ConformanceCheckFlags rhs) {
return ConformanceCheckOptions(lhs) | rhs;
}
/// Describes the kind of checked cast operation being performed.
enum class CheckedCastContextKind {
/// None: we're just establishing how to perform the checked cast. This
/// is useful when we don't care to produce any diagnostics.
None,
/// A forced cast, with "as!".
ForcedCast,
/// A conditional cast, with "as?".
ConditionalCast,
/// An "is" expression.
IsExpr,
/// An "is" pattern.
IsPattern,
/// An enum-element pattern.
EnumElementPattern,
};
/// The Swift type checker, which takes a parsed AST and performs name binding,
/// type checking, and semantic analysis to produce a type-annotated AST.
class TypeChecker final {
public:
/// The list of function definitions we've encountered.
std::vector<AbstractFunctionDecl *> definedFunctions;
/// A list of closures for the most recently type-checked function, which we
/// will need to compute captures for.
std::vector<AbstractClosureExpr *> ClosuresWithUncomputedCaptures;
private:
ASTContext &Context;
TypeChecker(ASTContext &Ctx);
friend class ASTContext;
friend class constraints::ConstraintSystem;
friend class TypeCheckFunctionBodyUntilRequest;
public:
/// Create a new type checker instance for the given ASTContext, if it
/// doesn't already have one.
///
/// \returns a reference to the type checker.
static TypeChecker &createForContext(ASTContext &ctx);
public:
TypeChecker(const TypeChecker&) = delete;
TypeChecker& operator=(const TypeChecker&) = delete;
~TypeChecker();
static Type getArraySliceType(SourceLoc loc, Type elementType);
static Type getDictionaryType(SourceLoc loc, Type keyType, Type valueType);
static Type getOptionalType(SourceLoc loc, Type elementType);
static Type getStringType(ASTContext &ctx);
static Type getSubstringType(ASTContext &ctx);
static Type getIntType(ASTContext &ctx);
static Type getInt8Type(ASTContext &ctx);
static Type getUInt8Type(ASTContext &ctx);
/// Try to resolve an IdentTypeRepr, returning either the referenced
/// Type or an ErrorType in case of error.
static Type resolveIdentifierType(TypeResolution resolution,
IdentTypeRepr *IdType,
TypeResolutionOptions options);
/// Bind an UnresolvedDeclRefExpr by performing name lookup and
/// returning the resultant expression. Context is the DeclContext used
/// for the lookup.
static Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE,
DeclContext *Context);
/// Validate the given type.
///
/// Type validation performs name binding, checking of generic arguments,
/// and so on to determine whether the given type is well-formed and can
/// be used as a type.
///
/// \param Loc The type (with source location information) to validate.
/// If the type has already been validated, returns immediately.
///
/// \param resolution The type resolution being performed.
///
/// \param options Options that alter type resolution.
///
/// \returns true if type validation failed, or false otherwise.
static bool validateType(ASTContext &Ctx, TypeLoc &Loc,
TypeResolution resolution,
TypeResolutionOptions options);
/// Check for unsupported protocol types in the given declaration.
static void checkUnsupportedProtocolType(Decl *decl);
/// Check for unsupported protocol types in the given statement.
static void checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt);
/// Check for unsupported protocol types in the given generic requirement
/// list.
static void checkUnsupportedProtocolType(ASTContext &ctx,
TrailingWhereClause *whereClause);
/// Check for unsupported protocol types in the given generic requirement
/// list.
static void checkUnsupportedProtocolType(ASTContext &ctx,
GenericParamList *genericParams);
/// Expose TypeChecker's handling of GenericParamList to SIL parsing.
static GenericEnvironment *
handleSILGenericParams(GenericParamList *genericParams, DeclContext *DC);
/// Resolve a reference to the given type declaration within a particular
/// context.
///
/// This routine aids unqualified name lookup for types by performing the
/// resolution necessary to rectify the declaration found by name lookup with
/// the declaration context from which name lookup started.
///
/// \param typeDecl The type declaration found by name lookup.
/// \param isSpecialized Whether the type will have generic arguments applied.
/// \param resolution The resolution to perform.
///
/// \returns the resolved type.
static Type resolveTypeInContext(TypeDecl *typeDecl,
DeclContext *foundDC,
TypeResolution resolution,
TypeResolutionOptions options,
bool isSpecialized);
/// Apply generic arguments to the given type.
///
/// This function emits diagnostics about an invalid type or the wrong number
/// of generic arguments, whereas applyUnboundGenericArguments requires this
/// to be in a correct and valid form.
///
/// \param type The generic type to which to apply arguments.
/// \param loc The source location for diagnostic reporting.
/// \param resolution The type resolution to perform.
/// \param generic The arguments to apply with the angle bracket range for
/// diagnostics.
/// \param options The type resolution context.
///
/// \returns A BoundGenericType bound to the given arguments, or null on
/// error.
///
/// \see applyUnboundGenericArguments
static Type applyGenericArguments(Type type, SourceLoc loc,
TypeResolution resolution,
GenericIdentTypeRepr *generic,
TypeResolutionOptions options);
/// Apply generic arguments to the given type.
///
/// This function requires a valid unbound generic type with the correct
/// number of generic arguments given, whereas applyGenericArguments emits
/// diagnostics in those cases.
///
/// \param unboundType The unbound generic type to which to apply arguments.
/// \param decl The declaration of the type.
/// \param loc The source location for diagnostic reporting.
/// \param resolution The type resolution.
/// \param genericArgs The list of generic arguments to apply to the type.
///
/// \returns A BoundGenericType bound to the given arguments, or null on
/// error.
///
/// \see applyGenericArguments
static Type applyUnboundGenericArguments(UnboundGenericType *unboundType,
GenericTypeDecl *decl,
SourceLoc loc,
TypeResolution resolution,
ArrayRef<Type> genericArgs);
/// Substitute the given base type into the type of the given nested type,
/// producing the effective type that the nested type will have.
///
/// \param module The module in which the substitution will be performed.
/// \param member The member whose type projection is being computed.
/// \param baseTy The base type that will be substituted for the 'Self' of the
/// member.
/// \param useArchetypes Whether to use context archetypes for outer generic
/// parameters if the class is nested inside a generic function.
static Type substMemberTypeWithBase(ModuleDecl *module, TypeDecl *member,
Type baseTy, bool useArchetypes = true);
/// Determine whether this is a "pass-through" typealias, which has the
/// same type parameters as the nominal type it references and specializes
/// the underlying nominal type with exactly those type parameters.
/// For example, the following typealias \c GX is a pass-through typealias:
///
/// \code
/// struct X<T, U> { }
/// typealias GX<A, B> = X<A, B>
/// \endcode
///
/// whereas \c GX2 and \c GX3 are not pass-through because \c GX2 has
/// different type parameters and \c GX3 doesn't pass its type parameters
/// directly through.
///
/// \code
/// typealias GX2<A> = X<A, A>
/// typealias GX3<A, B> = X<B, A>
/// \endcode
static bool isPassThroughTypealias(TypeAliasDecl *typealias,
Type underlyingType,
NominalTypeDecl *nominal);
/// Determine whether one type is a subtype of another.
///
/// \param t1 The potential subtype.
/// \param t2 The potential supertype.
/// \param dc The context of the check.
///
/// \returns true if \c t1 is a subtype of \c t2.
static bool isSubtypeOf(Type t1, Type t2, DeclContext *dc);
/// Determine whether one type is implicitly convertible to another.
///
/// \param t1 The potential source type of the conversion.
///
/// \param t2 The potential destination type of the conversion.
///
/// \param dc The context of the conversion.
///
/// \param unwrappedIUO If non-null, will be set to indicate whether the
/// conversion force-unwrapped an implicitly-unwrapped optional.
///
/// \returns true if \c t1 can be implicitly converted to \c t2.
static bool isConvertibleTo(Type t1, Type t2, DeclContext *dc,
bool *unwrappedIUO = nullptr);
/// Determine whether one type is explicitly convertible to another,
/// i.e. using an 'as' expression.
///
/// \param t1 The potential source type of the conversion.
///
/// \param t2 The potential destination type of the conversion.
///
/// \param dc The context of the conversion.
///
/// \returns true if \c t1 can be explicitly converted to \c t2.
static bool isExplicitlyConvertibleTo(Type t1, Type t2, DeclContext *dc);
/// Determine whether one type is bridged to another type.
///
/// \param t1 The potential source type of the conversion.
///
/// \param t2 The potential destination type of the conversion.
///
/// \param dc The context of the conversion.
///
/// \param unwrappedIUO If non-null, will be set to indicate whether the
/// conversion force-unwrapped an implicitly-unwrapped optional.
///
/// \returns true if \c t1 can be explicitly converted to \c t2.
static bool isObjCBridgedTo(Type t1, Type t2, DeclContext *dc,
bool *unwrappedIUO = nullptr);
/// Return true if performing a checked cast from one type to another
/// with the "as!" operator could possibly succeed.
///
/// \param t1 The potential source type of the cast.
///
/// \param t2 The potential destination type of the cast.
///
/// \param dc The context of the cast.
///
/// \returns true if a checked cast from \c t1 to \c t2 may succeed, and
/// false if it will certainly fail, e.g. because the types are unrelated.
static bool checkedCastMaySucceed(Type t1, Type t2, DeclContext *dc);
/// Determine whether a constraint of the given kind can be satisfied
/// by the two types.
///
/// \param t1 The first type of the constraint.
///
/// \param t2 The second type of the constraint.
///
/// \param openArchetypes If true, archetypes are replaced with type
/// variables, and the result can be interpreted as whether or not the
/// two types can possibly equal at runtime.
///
/// \param dc The context of the conversion.
///
/// \param unwrappedIUO If non-null, will be set to \c true if the coercion
/// or bridge operation force-unwraps an implicitly-unwrapped optional.
///
/// \returns true if \c t1 and \c t2 satisfy the constraint.
static bool typesSatisfyConstraint(Type t1, Type t2,
bool openArchetypes,
constraints::ConstraintKind kind,
DeclContext *dc,
bool *unwrappedIUO = nullptr);
/// If the inputs to an apply expression use a consistent "sugar" type
/// (that is, a typealias or shorthand syntax) equivalent to the result type
/// of the function, set the result type of the expression to that sugar type.
static Expr *substituteInputSugarTypeForResult(ApplyExpr *E);
static bool typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD,
SourceLoc EndTypeCheckLoc);
static bool typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD);
static BraceStmt *applyFunctionBuilderBodyTransform(FuncDecl *FD,
BraceStmt *body,
Type builderType);
static bool typeCheckClosureBody(ClosureExpr *closure);
static bool typeCheckTapBody(TapExpr *expr, DeclContext *DC);
static Type typeCheckParameterDefault(Expr *&defaultValue, DeclContext *DC,
Type paramType,
bool isAutoClosure = false,
bool canFail = true);
static void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD);
static void processREPLTopLevel(SourceFile &SF, TopLevelContext &TLC,
unsigned StartElem);
static void typeCheckDecl(Decl *D);
static void addImplicitDynamicAttribute(Decl *D);
static void checkDeclAttributes(Decl *D);
static void checkParameterAttributes(ParameterList *params);
static ValueDecl *findReplacedDynamicFunction(const ValueDecl *d);
static Type checkReferenceOwnershipAttr(VarDecl *D, Type interfaceType,
ReferenceOwnershipAttr *attr);
/// Infer default value witnesses for all requirements in the given protocol.
static void inferDefaultWitnesses(ProtocolDecl *proto);
/// For a generic requirement in a protocol, make sure that the requirement
/// set didn't add any requirements to Self or its associated types.
static void checkProtocolSelfRequirements(ValueDecl *decl);
/// All generic parameters of a generic function must be referenced in the
/// declaration's type, otherwise we have no way to infer them.
static void checkReferencedGenericParams(GenericContext *dc);
/// Construct a new generic environment for the given declaration context.
///
/// \param genericParams The generic parameters to validate.
///
/// \param dc The declaration context in which to perform the validation.
///
/// \param outerSignature The generic signature of the outer
/// context, if not available as part of the \c dc argument (used
/// for SIL parsing).
///
/// \param allowConcreteGenericParams Whether or not to allow
/// same-type constraints between generic parameters and concrete types.
///
/// \param additionalRequirements Additional requirements to add
/// directly to the GSB.
///
/// \param inferenceSources Additional types to infer requirements from.
///
/// \returns the resulting generic signature.
static GenericSignature checkGenericSignature(
GenericParamList *genericParams,
DeclContext *dc,
GenericSignature outerSignature,
bool allowConcreteGenericParams,
SmallVector<Requirement, 2> additionalRequirements = {},
SmallVector<TypeLoc, 2> inferenceSources = {});
/// Create a text string that describes the bindings of generic parameters
/// that are relevant to the given set of types, e.g.,
/// "[with T = Bar, U = Wibble]".
///
/// \param types The types that will be scanned for generic type parameters,
/// which will be used in the resulting type.
///
/// \param genericParams The generic parameters to use to resugar any
/// generic parameters that occur within the types.
///
/// \param substitutions The generic parameter -> generic argument
/// substitutions that will have been applied to these types.
/// These are used to produce the "parameter = argument" bindings in the test.
static std::string
gatherGenericParamBindingsText(ArrayRef<Type> types,
TypeArrayView<GenericTypeParamType> genericParams,
TypeSubstitutionFn substitutions);
/// Check the given set of generic arguments against the requirements in a
/// generic signature.
///
/// \param dc The context in which the generic arguments should be checked.
/// \param loc The location at which any diagnostics should be emitted.
/// \param noteLoc The location at which any notes will be printed.
/// \param owner The type that owns the generic signature.
/// \param genericParams The generic parameters being substituted.
/// \param requirements The requirements against which the generic arguments
/// should be checked.
/// \param substitutions Substitutions from interface types of the signature.
/// \param conformanceOptions The flags to use when checking conformance
/// requirement.
/// \param listener The generic check listener used to pick requirements and
/// notify callers about diagnosed errors.
static RequirementCheckResult checkGenericArguments(
DeclContext *dc, SourceLoc loc, SourceLoc noteLoc, Type owner,
TypeArrayView<GenericTypeParamType> genericParams,
ArrayRef<Requirement> requirements,
TypeSubstitutionFn substitutions,
LookupConformanceFn conformances,
ConformanceCheckOptions conformanceOptions,
GenericRequirementsCheckListener *listener = nullptr,
SubstOptions options = None);
/// Diagnose if the class has no designated initializers.
static void maybeDiagnoseClassWithoutInitializers(ClassDecl *classDecl);
///
/// Add any implicitly-defined constructors required for the given
/// struct or class.
static void addImplicitConstructors(NominalTypeDecl *typeDecl);
/// \name Name lookup
///
/// Routines that perform name lookup.
///
/// During type checking, these routines should be used instead of
/// \c MemberLookup and \c UnqualifiedLookup, because these routines will
/// lazily introduce declarations and (FIXME: eventually) perform recursive
/// type-checking that the AST-level lookup routines don't.
///
/// @{
private:
Optional<Type> boolType;
public:
/// Fold the given sequence expression into an (unchecked) expression
/// tree.
static Expr *foldSequence(SequenceExpr *expr, DeclContext *dc);
/// Type check the given expression.
///
/// \param expr The expression to type-check, which will be modified in
/// place.
///
/// \param convertTypePurpose When convertType is specified, this indicates
/// what the conversion is doing. This allows diagnostics generation to
/// produce more specific and helpful error messages when the conversion fails
/// to be possible.
///
/// \param convertType The type that the expression is being converted to,
/// or null if the expression is standalone. If the 'ConvertTypeIsOnlyAHint'
/// option is specified, then this is only a hint, it doesn't produce a full
/// conversion constraint. The location information is only used for
/// diagnostics should the conversion fail; it is safe to pass a TypeLoc
/// without location information.
///
/// \param options Options that control how type checking is performed.
///
/// \param listener If non-null, a listener that will be notified of important
/// events in the type checking of this expression, and which can introduce
/// additional constraints.
///
/// \param baseCS If this type checking process is the simplification of
/// another constraint system, set the original constraint system. \c null
/// otherwise
///
/// \returns The type of the top-level expression, or Type() if an
/// error occurred.
static Type
typeCheckExpression(Expr *&expr, DeclContext *dc,
TypeLoc convertType = TypeLoc(),
ContextualTypePurpose convertTypePurpose = CTP_Unused,
TypeCheckExprOptions options = TypeCheckExprOptions(),
ExprTypeCheckListener *listener = nullptr,
constraints::ConstraintSystem *baseCS = nullptr);
static Type typeCheckExpression(Expr *&expr, DeclContext *dc,
ExprTypeCheckListener *listener) {
return TypeChecker::typeCheckExpression(expr, dc, TypeLoc(), CTP_Unused,
TypeCheckExprOptions(), listener);
}
private:
Type typeCheckExpressionImpl(Expr *&expr, DeclContext *dc,
TypeLoc convertType,
ContextualTypePurpose convertTypePurpose,
TypeCheckExprOptions options,
ExprTypeCheckListener &listener,
constraints::ConstraintSystem *baseCS);
public: