| //===--- TypeChecker.h - Type Checking Class --------------------*- C++ -*-===// |
| // |
| // This source file is part of the Swift.org open source project |
| // |
| // Copyright (c) 2014 - 2016 Apple Inc. and the Swift project authors |
| // Licensed under Apache License v2.0 with Runtime Library Exception |
| // |
| // See http://swift.org/LICENSE.txt for license information |
| // See http://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/Sema/TypeCheckRequest.h" |
| #include "swift/AST/AST.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/TypeRefinementContext.h" |
| #include "swift/Parse/Lexer.h" |
| #include "swift/Basic/Fallthrough.h" |
| #include "swift/Basic/OptionSet.h" |
| #include "swift/Config.h" |
| #include "llvm/ADT/SetVector.h" |
| #include <functional> |
| |
| namespace swift { |
| |
| class ArchetypeBuilder; |
| class GenericTypeResolver; |
| class NominalTypeDecl; |
| class TopLevelContext; |
| class TypeChecker; |
| |
| namespace constraints { |
| enum class ConstraintKind : char; |
| class ConstraintSystem; |
| class Solution; |
| } |
| |
| /// \brief A mapping from substitutable types to the protocol-conformance |
| /// mappings for those types. |
| typedef llvm::DenseMap<SubstitutableType *, |
| SmallVector<ProtocolConformance *, 2>> ConformanceMap; |
| |
| /// The result of name lookup. |
| class LookupResult { |
| public: |
| struct Result { |
| /// The declaration we found. |
| ValueDecl *Decl; |
| |
| /// The base declaration through which we found the declaration. |
| ValueDecl *Base; |
| |
| operator ValueDecl*() const { return Decl; } |
| ValueDecl *operator->() const { return Decl; } |
| }; |
| |
| private: |
| /// The set of results found. |
| SmallVector<Result, 4> Results; |
| |
| public: |
| typedef SmallVectorImpl<Result>::iterator iterator; |
| iterator begin() { return Results.begin(); } |
| iterator end() { return Results.end(); } |
| unsigned size() const { return Results.size(); } |
| bool empty() const { return Results.empty(); } |
| |
| const Result& operator[](unsigned index) const { return Results[index]; } |
| |
| Result front() const { return Results.front(); } |
| Result back() const { return Results.back(); } |
| |
| /// Add a result to the set of results. |
| void add(Result result) { Results.push_back(result); } |
| |
| void clear() { Results.clear(); } |
| |
| /// Determine whether the result set is nonempty. |
| explicit operator bool() const { |
| return !Results.empty(); |
| } |
| |
| TypeDecl *getSingleTypeResult() const { |
| if (size() != 1) |
| return nullptr; |
| |
| return dyn_cast<TypeDecl>(front().Decl); |
| } |
| |
| /// Filter out any results that aren't accepted by the given predicate. |
| void filter(const std::function<bool(Result)> &pred); |
| }; |
| |
| /// The result of name lookup for types. |
| class LookupTypeResult { |
| /// The set of results found. |
| SmallVector<std::pair<TypeDecl *, Type>, 4> Results; |
| |
| friend class TypeChecker; |
| |
| public: |
| typedef SmallVectorImpl<std::pair<TypeDecl *, Type>>::iterator iterator; |
| iterator begin() { return Results.begin(); } |
| iterator end() { return Results.end(); } |
| unsigned size() const { return Results.size(); } |
| |
| std::pair<TypeDecl *, Type> operator[](unsigned index) const { |
| return Results[index]; |
| } |
| |
| std::pair<TypeDecl *, Type> front() const { return Results.front(); } |
| std::pair<TypeDecl *, Type> back() const { return Results.back(); } |
| |
| /// Add a result to the set of results. |
| void addResult(std::pair<TypeDecl *, Type> result) { |
| Results.push_back(result); |
| } |
| |
| /// \brief 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_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_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, |
| |
| /// Set if the client wants diagnostics suppressed. |
| SuppressDiagnostics = 0x04, |
| |
| /// 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, |
| }; |
| |
| typedef OptionSet<TypeCheckExprFlags> TypeCheckExprOptions; |
| |
| 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 to perform 'dynamic' name lookup that finds @objc |
| /// members of any class or protocol. |
| DynamicLookup = 0x04, |
| /// Whether we're only looking for types. |
| OnlyTypes = 0x08, |
| }; |
| |
| /// A set of options that control name lookup. |
| typedef OptionSet<NameLookupFlags> NameLookupOptions; |
| |
| inline NameLookupOptions operator|(NameLookupFlags flag1, |
| NameLookupFlags flag2) { |
| return NameLookupOptions(flag1) | flag2; |
| } |
| |
| /// Default options for member name lookup. |
| const NameLookupOptions defaultMemberLookupOptions |
| = NameLookupFlags::DynamicLookup | NameLookupFlags::ProtocolMembers; |
| |
| /// Default options for constructor lookup. |
| const NameLookupOptions defaultConstructorLookupOptions |
| = NameLookupFlags::ProtocolMembers; |
| |
| /// Default options for member type lookup. |
| const NameLookupOptions defaultMemberTypeLookupOptions |
| = NameLookupFlags::ProtocolMembers; |
| |
| /// Default options for unqualified name lookup. |
| const NameLookupOptions defaultUnqualifiedLookupOptions |
| = NameLookupFlags::ProtocolMembers; |
| |
| /// 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 fresh generic parameters. |
| GenericParameters, |
| /// 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 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); |
| }; |
| |
| /// Flags that describe the context of type checking a pattern or |
| /// type. |
| enum TypeResolutionFlags : unsigned { |
| /// Whether to allow unspecified types within a pattern. |
| TR_AllowUnspecifiedTypes = 0x01, |
| |
| /// Whether the given type can override the type of a typed pattern. |
| TR_OverrideType = 0x04, |
| |
| /// Whether to allow unbound generic types. |
| TR_AllowUnboundGenerics = 0x08, |
| |
| /// Whether we are validating the type for SIL. |
| TR_SILType = 0x10, |
| |
| /// Whether we are in the input type of a function, or under one level of |
| /// tuple type. This is not set for multi-level tuple arguments. |
| TR_FunctionInput = 0x20, |
| |
| /// Whether this is the immediate input type to a function type, |
| TR_ImmediateFunctionInput = 0x40, |
| |
| /// Whether we are in the result type of a function body that is |
| /// known to produce dynamic Self. |
| TR_DynamicSelfResult = 0x100, |
| |
| /// Whether this is a resolution based on a non-inferred type pattern. |
| TR_FromNonInferredPattern = 0x200, |
| |
| /// Whether we are the variable type in a for/in statement. |
| TR_EnumerationVariable = 0x400, |
| |
| /// Whether we are looking only in the generic signature of the context |
| /// we're searching, rather than the entire context. |
| TR_GenericSignature = 0x800, |
| |
| /// Whether this type is the referent of a global type alias. |
| TR_GlobalTypeAlias = 0x1000, |
| |
| /// Whether this type is the value carried in an enum case. |
| TR_EnumCase = 0x2000, |
| |
| /// Whether this type is being used in an expression or local declaration. |
| /// |
| /// This affects what sort of dependencies are recorded when resolving the |
| /// type. |
| TR_InExpression = 0x4000, |
| |
| /// Whether this type resolution is guaranteed not to affect downstream files. |
| TR_KnownNonCascadingDependency = 0x8000, |
| |
| /// Whether we should allow references to unavailable types. |
| TR_AllowUnavailable = 0x10000, |
| |
| /// Whether this is the payload subpattern of an enum pattern. |
| TR_EnumPatternPayload = 0x20000, |
| |
| /// Whether we are binding an extension declaration, which limits |
| /// the lookup. |
| TR_ExtensionBinding = 0x40000, |
| |
| /// Whether we are in the inheritance clause of a nominal type declaration |
| /// or extension. |
| TR_InheritanceClause = 0x80000, |
| |
| /// Whether we should resolve only the structure of the resulting |
| /// type rather than its complete semantic properties. |
| TR_ResolveStructure = 0x100000, |
| |
| /// Whether this is the type of an editor placeholder. |
| TR_EditorPlaceholder = 0x200000, |
| }; |
| |
| /// Option set describing how type resolution should work. |
| typedef OptionSet<TypeResolutionFlags> TypeResolutionOptions; |
| |
| inline TypeResolutionOptions operator|(TypeResolutionFlags lhs, |
| TypeResolutionFlags rhs) { |
| return TypeResolutionOptions(lhs) | rhs; |
| } |
| |
| /// Strip the contextual options from the given type resolution options. |
| static inline TypeResolutionOptions |
| withoutContext(TypeResolutionOptions options) { |
| options -= TR_ImmediateFunctionInput; |
| options -= TR_FunctionInput; |
| options -= TR_EnumCase; |
| return options; |
| } |
| |
| /// Describes the reason why are we trying to apply @objc to a declaration. |
| /// |
| /// Should only affect diagnostics. If you change this enum, also change |
| /// the OBJC_ATTR_SELECT macro in DiagnosticsSema.def. |
| enum class ObjCReason { |
| DoNotDiagnose, |
| ExplicitlyDynamic, |
| ExplicitlyObjC, |
| ExplicitlyIBOutlet, |
| ExplicitlyNSManaged, |
| MemberOfObjCProtocol, |
| ImplicitlyObjC, |
| OverridesObjC |
| }; |
| |
| /// Return the %select discriminator for the OBJC_ATTR_SELECT macro used to |
| /// complain about the correct attribute during @objc inference. |
| static inline unsigned getObjCDiagnosticAttrKind(ObjCReason Reason) { |
| assert(Reason != ObjCReason::DoNotDiagnose); |
| return static_cast<unsigned>(Reason) - 1; |
| } |
| |
| /// Flags that control protocol conformance checking. |
| enum class ConformanceCheckFlags { |
| /// Whether we're performing the check from within an expression. |
| InExpression = 0x01, |
| /// Whether we will be using the conformance in the AST. |
| /// |
| /// This implies that the conformance will have to be complete. |
| Used = 0x02 |
| }; |
| |
| /// Options that control protocol conformance checking. |
| typedef OptionSet<ConformanceCheckFlags> ConformanceCheckOptions; |
| |
| inline ConformanceCheckOptions operator|(ConformanceCheckFlags lhs, |
| ConformanceCheckFlags rhs) { |
| return ConformanceCheckOptions(lhs) | rhs; |
| } |
| |
| /// 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 LazyResolver { |
| public: |
| ASTContext &Context; |
| DiagnosticEngine &Diags; |
| |
| /// \brief The list of implicitly-defined functions created by the |
| /// type checker. |
| std::vector<AbstractFunctionDecl *> implicitlyDefinedFunctions; |
| |
| /// \brief The list of function definitions we've encountered. |
| std::vector<AbstractFunctionDecl *> definedFunctions; |
| |
| /// The list of protocol conformances that were "used" and will need to be |
| /// completed before type checking is considered complete. |
| llvm::SetVector<NormalProtocolConformance *> UsedConformances; |
| |
| /// The list of nominal type declarations that have been validated |
| /// during type checking. |
| llvm::SetVector<NominalTypeDecl *> ValidatedTypes; |
| |
| /// Caches whether a particular type is accessible from a particular file |
| /// unit. |
| /// |
| /// This can't use CanTypes because typealiases may have more limited types |
| /// than their underlying types. |
| llvm::DenseMap<Type, Accessibility> TypeAccessibilityCache; |
| |
| // We delay validation of C and Objective-C type-bridging functions in the |
| // standard library until we encounter a declaration that requires one. This |
| // flag is set to 'true' once the bridge functions have been checked. |
| bool HasCheckedBridgeFunctions = false; |
| |
| /// A list of closures for the most recently type-checked function, which we |
| /// will need to compute captures for. |
| std::vector<AnyFunctionRef> ClosuresWithUncomputedCaptures; |
| |
| /// Describes an attempt to capture a local function. |
| struct LocalFunctionCapture { |
| FuncDecl *LocalFunction; |
| SourceLoc CaptureLoc; |
| }; |
| |
| /// Local functions that have been captured before their definitions. |
| /// |
| /// We need this to guard against functions that would transitively capture |
| /// variables before their definition, e.g.: |
| /// |
| /// func outer() { |
| /// func first() { |
| /// second() |
| /// } |
| /// second() |
| /// var x |
| /// func second() { |
| /// use(x) |
| /// } |
| /// } |
| |
| llvm::SmallDenseMap<AnyFunctionRef, SmallVector<AnyFunctionRef, 4>, 4> |
| ForwardCapturedFuncs; |
| |
| /// A set of local functions from which C function pointers are derived. |
| /// |
| /// This is used to diagnose the use of local functions with captured context |
| /// as C function pointers when the function's captures have not yet been |
| /// computed. |
| llvm::DenseMap<AnyFunctionRef, std::vector<Expr*>> LocalCFunctionPointers; |
| |
| private: |
| Type IntLiteralType; |
| Type FloatLiteralType; |
| Type BooleanLiteralType; |
| Type UnicodeScalarType; |
| Type ExtendedGraphemeClusterType; |
| Type StringLiteralType; |
| Type ArrayLiteralType; |
| Type DictionaryLiteralType; |
| Type ColorLiteralType; |
| Type ImageLiteralType; |
| Type FileReferenceLiteralType; |
| Type StringType; |
| Type Int8Type; |
| Type UInt8Type; |
| Type NSObjectType; |
| Type NSErrorType; |
| Type ExceptionType; |
| |
| /// The \c Swift.UnsafeMutablePointer<T> declaration. |
| Optional<NominalTypeDecl *> ArrayDecl; |
| |
| /// A set of types that can be trivially mapped to Objective-C types. |
| llvm::DenseSet<CanType> ObjCMappedTypes; |
| |
| /// A set of types that can be mapped to C integer types. |
| llvm::DenseSet<CanType> CIntegerTypes; |
| |
| /// The set of expressions currently being analyzed for failures. |
| llvm::DenseMap<Expr*, Expr*> DiagnosedExprs; |
| |
| /// A set of types that are representable in Objective-C, but require |
| /// non-trivial bridging. |
| /// |
| /// The value of the map is a flag indicating whether the bridged |
| /// type can be optional. |
| llvm::DenseMap<CanType, bool> ObjCRepresentableTypes; |
| |
| Module *StdlibModule = nullptr; |
| |
| /// The index of the next response metavariable to bind to a REPL result. |
| unsigned NextResponseVariableIndex = 0; |
| |
| /// If true, the time it takes to type-check each function will be dumped |
| /// to llvm::errs(). |
| bool DebugTimeFunctionBodies = false; |
| |
| /// Indicate that the type checker is checking code that will be |
| /// immediately executed. This will suppress certain warnings |
| /// when executing scripts. |
| bool InImmediateMode = false; |
| |
| /// A helper to construct and typecheck call to super.init(). |
| /// |
| /// \returns NULL if the constructed expression does not typecheck. |
| Expr* constructCallToSuperInit(ConstructorDecl *ctor, ClassDecl *ClDecl); |
| |
| public: |
| TypeChecker(ASTContext &Ctx) : TypeChecker(Ctx, Ctx.Diags) { } |
| TypeChecker(ASTContext &Ctx, DiagnosticEngine &Diags); |
| ~TypeChecker(); |
| |
| LangOptions &getLangOpts() const { return Context.LangOpts; } |
| |
| /// Dump the time it takes to type-check each function to llvm::errs(). |
| void enableDebugTimeFunctionBodies() { |
| DebugTimeFunctionBodies = true; |
| } |
| |
| bool getInImmediateMode() { |
| return InImmediateMode; |
| } |
| |
| void setInImmediateMode(bool InImmediateMode) { |
| this->InImmediateMode = InImmediateMode; |
| } |
| |
| template<typename ...ArgTypes> |
| InFlightDiagnostic diagnose(ArgTypes &&...Args) { |
| return Diags.diagnose(std::forward<ArgTypes>(Args)...); |
| } |
| |
| Type getArraySliceType(SourceLoc loc, Type elementType); |
| Type getDictionaryType(SourceLoc loc, Type keyType, Type valueType); |
| Type getOptionalType(SourceLoc loc, Type elementType); |
| Type getImplicitlyUnwrappedOptionalType(SourceLoc loc, Type elementType); |
| Type getStringType(DeclContext *dc); |
| Type getInt8Type(DeclContext *dc); |
| Type getUInt8Type(DeclContext *dc); |
| Type getNSObjectType(DeclContext *dc); |
| Type getNSErrorType(DeclContext *dc); |
| Type getExceptionType(DeclContext *dc, SourceLoc loc); |
| |
| /// \brief Try to resolve an IdentTypeRepr, returning either the referenced |
| /// Type or an ErrorType in case of error. |
| Type resolveIdentifierType(DeclContext *DC, |
| IdentTypeRepr *IdType, |
| TypeResolutionOptions options, |
| bool diagnoseErrors, |
| GenericTypeResolver *resolver, |
| UnsatisfiedDependency *unsatisfiedDependency); |
| |
| /// Bind an UnresolvedDeclRefExpr by performing name lookup and |
| /// returning the resultant expression. Context is the DeclContext used |
| /// for the lookup. |
| Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context); |
| |
| /// \brief 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 DC The context that the type appears in. |
| /// |
| /// \param options Options that alter type resolution. |
| /// |
| /// \param resolver A resolver for generic types. If none is supplied, this |
| /// routine will create a \c PartialGenericTypeToArchetypeResolver to use. |
| /// |
| /// \returns true if type validation failed, or false otherwise. |
| bool validateType(TypeLoc &Loc, DeclContext *DC, |
| TypeResolutionOptions options = None, |
| GenericTypeResolver *resolver = nullptr, |
| UnsatisfiedDependency *unsatisfiedDependency = nullptr); |
| |
| /// Check for unsupported protocol types in the given declaration. |
| void checkUnsupportedProtocolType(Decl *decl); |
| |
| /// Check for unsupported protocol types in the given statement. |
| void checkUnsupportedProtocolType(Stmt *stmt); |
| |
| /// Expose TypeChecker's handling of GenericParamList to SIL parsing. |
| /// We pass in a vector of nested GenericParamLists and a vector of |
| /// ArchetypeBuilders with the innermost GenericParamList in the beginning |
| /// of the vector. |
| bool handleSILGenericParams(SmallVectorImpl<ArchetypeBuilder *> &builders, |
| SmallVectorImpl<GenericParamList *> &gps, |
| DeclContext *DC); |
| |
| /// \brief Resolves a TypeRepr to a type. |
| /// |
| /// Performs name binding, checking of generic arguments, and so on in order |
| /// to create a well-formed type. |
| /// |
| /// \param TyR The type representation to check. |
| /// |
| /// \param DC The context that the type appears in. |
| /// |
| /// \param options Options that alter type resolution. |
| /// |
| /// \param resolver A resolver for generic types. If none is supplied, this |
| /// routine will create a \c PartialGenericTypeToArchetypeResolver to use. |
| /// |
| /// \param unsatisfiedDependency When non-null, used to check whether |
| /// dependencies have been satisfied appropriately. |
| /// |
| /// \returns a well-formed type or an ErrorType in case of an error. |
| Type resolveType(TypeRepr *TyR, DeclContext *DC, |
| TypeResolutionOptions options, |
| GenericTypeResolver *resolver = nullptr, |
| UnsatisfiedDependency *unsatisfiedDependency = nullptr); |
| |
| void validateDecl(ValueDecl *D, bool resolveTypeParams = false); |
| |
| /// Resolves the accessibility of the given declaration. |
| void validateAccessibility(ValueDecl *D); |
| |
| /// Validate the given extension declaration, ensuring that it |
| /// properly extends the nominal type it names. |
| void validateExtension(ExtensionDecl *ext); |
| |
| /// \brief Force all members of an external decl, and also add its |
| /// conformances. |
| void forceExternalDeclMembers(NominalTypeDecl *NTD); |
| |
| /// 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 fromDC The declaration context in which the name lookup occurred. |
| /// \param isSpecialized Whether this type is immediately specialized. |
| /// \param resolver The resolver for generic types. |
| /// |
| /// \returns the resolved type, or emits a diagnostic and returns null if the |
| /// type cannot be resolved. |
| Type resolveTypeInContext(TypeDecl *typeDecl, DeclContext *fromDC, |
| TypeResolutionOptions options, |
| bool isSpecialized, |
| GenericTypeResolver *resolver = nullptr, |
| UnsatisfiedDependency *unsatisfiedDependency |
| = nullptr); |
| |
| /// \brief Apply generic arguments to the given type. |
| /// |
| /// \param type The unbound generic type to which to apply arguments. |
| /// \param loc The source location for diagnostic reporting. |
| /// \param dc The context where the arguments are applied. |
| /// \param genericArgs The list of generic arguments to apply to the type. |
| /// \param isGenericSignature True if we are looking only in the generic |
| /// signature of the context. |
| /// \param resolver The generic type resolver. |
| /// |
| /// \returns A BoundGenericType bound to the given arguments, or null on |
| /// error. |
| Type applyGenericArguments(Type type, |
| SourceLoc loc, |
| DeclContext *dc, |
| MutableArrayRef<TypeLoc> genericArgs, |
| bool isGenericSignature, |
| GenericTypeResolver *resolver); |
| |
| /// \brief Substitute the given base type into the type of the given member, |
| /// producing the effective type that the member 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 isTypeReference Whether this is a reference to a type declaration |
| /// within a type context. |
| Type substMemberTypeWithBase(Module *module, const ValueDecl *member, |
| Type baseTy, bool isTypeReference); |
| |
| /// \brief Retrieve the superclass type of the given type, or a null type if |
| /// the type has no supertype. |
| Type getSuperClassOf(Type type); |
| |
| /// \brief 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. |
| bool isSubtypeOf(Type t1, Type t2, DeclContext *dc); |
| |
| /// \brief 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. |
| /// |
| /// \returns true if \c t1 can be implicitly converted to \c t2. |
| bool isConvertibleTo(Type t1, Type t2, DeclContext *dc); |
| |
| /// \brief 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. |
| bool isExplicitlyConvertibleTo(Type t1, Type t2, DeclContext *dc); |
| |
| /// \brief 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. |
| bool checkedCastMaySucceed(Type t1, Type t2, DeclContext *dc); |
| |
| /// \brief 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 dc The context of the conversion. |
| /// |
| /// \returns true if \c t1 and \c t2 satisfy the constraint. |
| bool typesSatisfyConstraint(Type t1, Type t2, |
| constraints::ConstraintKind kind, |
| DeclContext *dc); |
| |
| /// \brief Determine whether one type would be a valid substitution for an |
| /// archetype. |
| /// |
| /// \param type The potential type. |
| /// |
| /// \param archetype The archetype for which type may (or may not) be |
| /// substituted. |
| /// |
| /// \param dc The context of the check. |
| /// |
| /// \returns true if \c t1 is a valid substitution for \c t2. |
| bool isSubstitutableFor(Type type, ArchetypeType *archetype, DeclContext *dc); |
| |
| /// 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. |
| Expr *substituteInputSugarTypeForResult(ApplyExpr *E); |
| |
| bool typeCheckAbstractFunctionBodyUntil(AbstractFunctionDecl *AFD, |
| SourceLoc EndTypeCheckLoc); |
| bool typeCheckAbstractFunctionBody(AbstractFunctionDecl *AFD); |
| bool typeCheckFunctionBodyUntil(FuncDecl *FD, SourceLoc EndTypeCheckLoc); |
| bool typeCheckConstructorBodyUntil(ConstructorDecl *CD, |
| SourceLoc EndTypeCheckLoc); |
| bool typeCheckDestructorBodyUntil(DestructorDecl *DD, |
| SourceLoc EndTypeCheckLoc); |
| |
| void typeCheckClosureBody(ClosureExpr *closure); |
| |
| void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD); |
| |
| void processREPLTopLevel(SourceFile &SF, TopLevelContext &TLC, |
| unsigned StartElem); |
| Identifier getNextResponseVariableName(DeclContext *DC); |
| |
| void typeCheckDecl(Decl *D, bool isFirstPass); |
| |
| void checkDeclAttributesEarly(Decl *D); |
| void checkDeclAttributes(Decl *D); |
| void checkTypeModifyingDeclAttributes(VarDecl *var); |
| |
| void checkAutoClosureAttr(ParamDecl *D, AutoClosureAttr *attr); |
| void checkNoEscapeAttr(ParamDecl *D, NoEscapeAttr *attr); |
| void checkOwnershipAttr(VarDecl *D, OwnershipAttr *attr); |
| |
| void computeAccessibility(ValueDecl *D); |
| void computeDefaultAccessibility(ExtensionDecl *D); |
| |
| virtual void resolveAccessibility(ValueDecl *VD) override { |
| validateAccessibility(VD); |
| } |
| |
| virtual void resolveDeclSignature(ValueDecl *VD) override { |
| validateDecl(VD, true); |
| } |
| |
| virtual void resolveExtension(ExtensionDecl *ext) override { |
| validateExtension(ext); |
| checkInheritanceClause(ext); |
| } |
| |
| virtual void resolveImplicitConstructors(NominalTypeDecl *nominal) override { |
| addImplicitConstructors(nominal); |
| } |
| |
| virtual void |
| resolveExternalDeclImplicitMembers(NominalTypeDecl *nominal) override { |
| handleExternalDecl(nominal); |
| } |
| |
| /// Determine attributes for the given function and curry level, with a level |
| /// of 0 indicating the innermost function. |
| AnyFunctionType::ExtInfo |
| applyFunctionTypeAttributes(AbstractFunctionDecl *func, unsigned i); |
| |
| /// Determine whether the given (potentially constrained) protocol extension |
| /// is usable for the given type. |
| bool isProtocolExtensionUsable(DeclContext *dc, Type type, |
| ExtensionDecl *protocolExtension) override; |
| |
| /// Validate the signature of a generic function. |
| /// |
| /// \param func The generic function. |
| /// |
| /// \returns true if an error occurred, or false otherwise. |
| bool validateGenericFuncSignature(AbstractFunctionDecl *func); |
| |
| /// Revert the signature of a generic function to its pre-type-checked state, |
| /// so that it can be type checked again when we have resolved its generic |
| /// parameters. |
| void revertGenericFuncSignature(AbstractFunctionDecl *func); |
| |
| /// Revert the dependent types within the given generic parameter list. |
| void revertGenericParamList(GenericParamList *genericParams); |
| |
| /// Validate the given generic parameters to produce a generic |
| /// signature. |
| /// |
| /// \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 inferRequirements When non-empty, callback that will be invoked |
| /// to perform any additional requirement inference that contributes to the |
| /// generic signature. Returns true if an error occurred. |
| /// |
| /// \param invalid Will be set true if an error occurs during validation. |
| /// |
| /// \returns the generic signature that captures the generic |
| /// parameters and inferred requirements. |
| GenericSignature *validateGenericSignature( |
| GenericParamList *genericParams, |
| DeclContext *dc, |
| GenericSignature *outerSignature, |
| std::function<bool(ArchetypeBuilder &)> inferRequirements, |
| bool &invalid); |
| |
| /// Validate the signature of a generic type. |
| /// |
| /// \param nominal The generic type. |
| /// |
| /// \returns true if an error occurred, or false otherwise. |
| bool validateGenericTypeSignature(NominalTypeDecl *nominal); |
| |
| /// Check the generic parameters in the given generic parameter list (and its |
| /// parent generic parameter lists) according to the given resolver. |
| bool checkGenericParamList(ArchetypeBuilder *builder, |
| GenericParamList *genericParams, |
| DeclContext *parentDC, |
| bool adoptArchetypes = true, |
| GenericTypeResolver *resolver = nullptr); |
| |
| /// 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 genericSig The actual generic signature. |
| /// \param genericArgs The generic arguments. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool checkGenericArguments(DeclContext *dc, SourceLoc loc, |
| SourceLoc noteLoc, |
| Type owner, |
| GenericSignature *genericSig, |
| ArrayRef<Type> genericArgs); |
| |
| /// Given a type that was produced within the given generic declaration |
| /// context, produce the corresponding interface type. |
| /// |
| /// \param dc The declaration context in which the type was produced. |
| /// |
| /// \param type The type, which involves archetypes but not dependent types. |
| /// |
| /// \returns the type after mapping all archetypes to their corresponding |
| /// dependent types. |
| Type getInterfaceTypeFromInternalType(DeclContext *dc, Type type); |
| |
| /// Resolve the superclass of the given class. |
| void resolveSuperclass(ClassDecl *classDecl) override; |
| |
| /// Resolve the raw type of the given enum. |
| void resolveRawType(EnumDecl *enumDecl) override; |
| |
| /// Resolve the inherited protocols of a given protocol. |
| void resolveInheritedProtocols(ProtocolDecl *protocol) override; |
| |
| /// Resolve the types in the inheritance clause of the given |
| /// declaration context, which will be a nominal type declaration or |
| /// extension declaration. |
| void resolveInheritanceClause( |
| llvm::PointerUnion<TypeDecl *, ExtensionDecl *> decl) override; |
| |
| /// Check the inheritance clause of the given declaration. |
| void checkInheritanceClause(Decl *decl, |
| GenericTypeResolver *resolver = nullptr); |
| |
| /// Retrieve the set of inherited protocols for this protocol type. |
| ArrayRef<ProtocolDecl *> getDirectConformsTo(ProtocolDecl *proto); |
| |
| /// \brief Add any implicitly-defined constructors required for the given |
| /// struct or class. |
| void addImplicitConstructors(NominalTypeDecl *typeDecl); |
| |
| /// \brief Add an implicitly-defined destructor, if there is no |
| /// user-provided destructor. |
| void addImplicitDestructor(ClassDecl *CD); |
| |
| /// \brief Add the RawOptionSet (todo:, Equatable, and Hashable) methods to an |
| /// imported NS_OPTIONS struct. |
| void addImplicitStructConformances(StructDecl *ED); |
| |
| /// \brief Add the RawRepresentable, Equatable, and Hashable methods to an |
| /// enum with a raw type. |
| void addImplicitEnumConformances(EnumDecl *ED); |
| |
| /// The specified AbstractStorageDecl \c storage was just found to satisfy |
| /// the protocol property \c requirement. Ensure that it has the full |
| /// complement of accessors. |
| void synthesizeWitnessAccessorsForStorage(AbstractStorageDecl *requirement, |
| AbstractStorageDecl *storage); |
| |
| /// Provide storage and accessor implementations for the given property, |
| /// which must be lazy. |
| void completeLazyVarImplementation(VarDecl *lazyVar); |
| |
| /// Sets up and solves the constraint system \p cs to type check the given |
| /// expression. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| /// |
| /// \see typeCheckExpression |
| bool solveForExpression(Expr *&expr, DeclContext *dc, Type convertType, |
| FreeTypeVariableBinding allowFreeTypeVariables, |
| ExprTypeCheckListener *listener, |
| constraints::ConstraintSystem &cs, |
| SmallVectorImpl<constraints::Solution> &viable, |
| TypeCheckExprOptions options); |
| |
| /// \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: |
| /// \brief Define the default constructor for the given struct or class. |
| void defineDefaultConstructor(NominalTypeDecl *decl); |
| |
| /// \brief Fold the given sequence expression into an (unchecked) expression |
| /// tree. |
| Expr *foldSequence(SequenceExpr *expr, DeclContext *dc); |
| |
| /// \brief 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. |
| /// |
| /// \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. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool typeCheckExpression(Expr *&expr, DeclContext *dc, |
| Type convertType = Type(), |
| ContextualTypePurpose convertTypePurpose =CTP_Unused, |
| TypeCheckExprOptions options =TypeCheckExprOptions(), |
| ExprTypeCheckListener *listener = nullptr); |
| |
| bool typeCheckExpression(Expr *&expr, DeclContext *dc, |
| ExprTypeCheckListener *listener) { |
| return typeCheckExpression(expr, dc, Type(), CTP_Unused, |
| TypeCheckExprOptions(), listener); |
| } |
| |
| |
| /// \brief Type check the given expression and return its type without |
| /// applying the solution. |
| /// |
| /// \param expr The expression to type-check. |
| /// |
| /// \param allowFreeTypeVariables Whether free type variables are allowed in |
| /// the solution, and what to do with them. |
| /// |
| /// \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. |
| /// |
| /// \returns the type of \p expr on success, None otherwise. |
| /// FIXME: expr may still be modified... |
| Optional<Type> getTypeOfExpressionWithoutApplying( |
| Expr *&expr, DeclContext *dc, |
| FreeTypeVariableBinding allowFreeTypeVariables = |
| FreeTypeVariableBinding::Disallow, |
| ExprTypeCheckListener *listener = nullptr); |
| |
| bool typeCheckCompletionSequence(Expr *&expr, DeclContext *DC); |
| |
| /// \brief Type check the given expression assuming that its children |
| /// have already been fully type-checked. |
| /// |
| /// \param expr The expression to type-check, which will be modified in |
| /// place. |
| /// |
| /// \param convertType The type that the expression is being converted to, |
| /// or null if the expression is standalone. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool typeCheckExpressionShallow(Expr *&expr, DeclContext *dc, |
| Type convertType = Type()); |
| |
| |
| /// \brief Type check the given expression as a condition, which converts |
| /// it to a logic value. |
| /// |
| /// \param expr The expression to type-check, which will be modified in place |
| /// to return a logic value (builtin i1). |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool typeCheckCondition(Expr *&expr, DeclContext *dc); |
| |
| /// \brief Type check the given 'if' or 'while' statement condition, which |
| /// either converts an expression to a logic value or bind variables to the |
| /// contents of an Optional. |
| /// |
| /// \param cond The condition to type-check, which will be modified in place. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool typeCheckStmtCondition(StmtCondition &cond, DeclContext *dc, |
| Diag<> diagnosticForAlwaysTrue); |
| |
| /// \brief Determine the semantics of a checked cast operation. |
| /// |
| /// \param fromType The source type of the cast. |
| /// \param toType The destination type of the cast. |
| /// \param dc The context of the cast. |
| /// \param diagLoc The location at which to report diagnostics. |
| /// \param diagFromRange The source range of the input operand of the cast. |
| /// \param diagToRange The source range of the destination type. |
| /// \param convertToType A callback called when an implicit conversion |
| /// to an intermediate type is needed. |
| /// \param suppressDiagnostics |
| /// True if the type check should simply fail instead |
| /// of printing diagnostics. |
| /// |
| /// \returns a CheckedCastKind indicating the semantics of the cast. If the |
| /// cast is invalid, Unresolved is returned. If the cast represents an implicit |
| /// conversion, Coercion is returned. |
| CheckedCastKind typeCheckCheckedCast(Type fromType, |
| Type toType, |
| DeclContext *dc, |
| SourceLoc diagLoc, |
| SourceRange diagFromRange, |
| SourceRange diagToRange, |
| std::function<bool(Type)> convertToType, |
| bool suppressDiagnostics); |
| |
| /// Retrieves the Objective-C type to which the given value type is |
| /// bridged. |
| /// |
| /// \param dc The declaration context from which we will look for |
| /// bridging. |
| /// |
| /// \param type The value type being queried, e.g., String. |
| /// |
| /// \returns the class type to which the given type is bridged, or null if it |
| /// is not bridged. |
| Type getBridgedToObjC(const DeclContext *dc, Type type); |
| |
| /// Find the Objective-C class that bridges between a value of the given |
| /// dynamic type and the given value type. |
| /// |
| /// \param dc The declaration context from which we will look for |
| /// bridging. |
| /// |
| /// \param dynamicType A dynamic type from which we are bridging. Class and |
| /// Objective-C protocol types can be used for bridging. |
| /// |
| /// \param valueType The value type being queried, e.g., String. |
| /// |
| /// \returns the Objective-C class type that represents the value |
| /// type as an Objective-C class, e.g., \c NSString represents \c |
| /// String, or a null type if there is no such type or if the |
| /// dynamic type isn't something we can start from. |
| Type getDynamicBridgedThroughObjCClass(DeclContext *dc, |
| Type dynamicType, |
| Type valueType); |
| |
| /// \brief Resolve ambiguous pattern/expr productions inside a pattern using |
| /// name lookup information. Must be done before type-checking the pattern. |
| Pattern *resolvePattern(Pattern *P, DeclContext *dc, |
| bool isStmtCondition); |
| |
| /// Type check the given pattern. |
| /// |
| /// \param P The pattern to type check. |
| /// \param dc The context in which type checking occurs. |
| /// \param options Options that control type resolution. |
| /// \param resolver A generic type resolver. |
| /// |
| /// \returns true if any errors occurred during type checking. |
| bool typeCheckPattern(Pattern *P, DeclContext *dc, |
| TypeResolutionOptions options, |
| GenericTypeResolver *resolver = nullptr); |
| |
| bool typeCheckCatchPattern(CatchStmt *S, DeclContext *dc); |
| |
| /// Type check a parameter list. |
| bool typeCheckParameterList(ParameterList *PL, DeclContext *dc, |
| TypeResolutionOptions options, |
| GenericTypeResolver *resolver = nullptr); |
| |
| /// Coerce a pattern to the given type. |
| /// |
| /// \param P The pattern, which may be modified by this coercion. |
| /// \param dc The context in which this pattern occurs. |
| /// \param type the type to coerce the pattern to. |
| /// \param options Options describing how to perform this coercion. |
| /// \param resolver The generic resolver to use. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool coercePatternToType(Pattern *&P, DeclContext *dc, Type type, |
| TypeResolutionOptions options, |
| GenericTypeResolver *resolver = nullptr); |
| bool typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, |
| Type type); |
| |
| /// Coerce the specified parameter list of a ClosureExpr to the specified |
| /// contextual type. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool coerceParameterListToType(ClosureExpr *CE, AnyFunctionType *closureType); |
| |
| |
| /// Type-check an initialized variable pattern declaration. |
| bool typeCheckBinding(Pattern *&P, Expr *&Init, DeclContext *DC); |
| bool typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned patternNumber); |
| |
| /// Type-check a for-each loop's pattern binding and sequence together. |
| bool typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt); |
| |
| /// \brief Lazily diagnose conversions to C function pointers of closures |
| /// with captures. |
| void maybeDiagnoseCaptures(Expr *E, AnyFunctionRef AFR); |
| |
| /// \brief Compute the set of captures for the given function or closure. |
| void computeCaptures(AnyFunctionRef AFR); |
| |
| /// \brief Change the context of closures in the given initializer |
| /// expression to the given context. |
| /// |
| /// \returns true if any closures were found |
| static bool contextualizeInitializer(Initializer *DC, Expr *init); |
| static void contextualizeTopLevelCode(TopLevelContext &TLC, |
| ArrayRef<Decl*> topLevelDecls); |
| |
| /// Return the type-of-reference of the given value. This does not |
| /// open values of polymorphic function type. |
| /// |
| /// \param baseType if non-null, return the type of a member reference to |
| /// this value when the base has the given type |
| /// |
| /// \param UseDC The context of the access. Some variables have different |
| /// types depending on where they are used. |
| /// |
| /// \param base The optional base expression of this value reference |
| /// |
| /// \param wantInterfaceType Whether we want the interface type, if available. |
| Type getUnopenedTypeOfReference(ValueDecl *value, Type baseType, |
| DeclContext *UseDC, |
| const DeclRefExpr *base = nullptr, |
| bool wantInterfaceType = false); |
| |
| /// Return the non-lvalue type-of-reference of the given value. |
| Type getTypeOfRValue(ValueDecl *value, bool wantInterfaceType = false); |
| |
| /// \brief Retrieve the default type for the given protocol. |
| /// |
| /// Some protocols, particularly those that correspond to literals, have |
| /// default types associated with them. This routine retrieves that default |
| /// type. |
| /// |
| /// \returns the default type, or null if there is no default type for |
| /// this protocol. |
| Type getDefaultType(ProtocolDecl *protocol, DeclContext *dc); |
| |
| /// \brief Convert the given expression to the given type. |
| /// |
| /// \param expr The expression, which will be updated in place. |
| /// \param type The type to convert to. |
| /// |
| /// \returns true if an error occurred, false otherwise. |
| bool convertToType(Expr *&expr, Type type, DeclContext *dc); |
| |
| /// \brief Coerce the given expression to an rvalue, if it isn't already. |
| Expr *coerceToRValue(Expr *expr); |
| |
| /// \brief Coerce the given expression to materializable type, if it |
| /// isn't already. |
| Expr *coerceToMaterializable(Expr *expr); |
| |
| /// Require that the library intrinsics for working with Optional<T> |
| /// exist. |
| bool requireOptionalIntrinsics(SourceLoc loc); |
| |
| /// Require that the library intrinsics for working with |
| /// UnsafeMutablePointer<T> exist. |
| bool requirePointerArgumentIntrinsics(SourceLoc loc); |
| |
| /// Require that the library intrinsics for creating |
| /// array literals exist. |
| bool requireArrayLiteralIntrinsics(SourceLoc loc); |
| |
| /// \brief Retrieve the witness type with the given name. |
| /// |
| /// \param type The type that conforms to the given protocol. |
| /// |
| /// \param protocol The protocol through which we're looking. |
| /// |
| /// \param conformance The protocol conformance. |
| /// |
| /// \param name The name of the associated type. |
| /// |
| /// \param brokenProtocolDiag Diagnostic to emit if the type cannot be |
| /// accessed. |
| /// |
| /// \return the witness type, or null if an error occurs. |
| Type getWitnessType(Type type, ProtocolDecl *protocol, |
| ProtocolConformance *conformance, |
| Identifier name, |
| Diag<> brokenProtocolDiag); |
| |
| /// \brief Build a call to the witness with the given name and arguments. |
| /// |
| /// \param base The base expression, whose witness will be invoked. |
| /// |
| /// \param protocol The protocol to call through. |
| /// |
| /// \param conformance The conformance of the base type to the given |
| /// protocol. |
| /// |
| /// \param name The name of the method to call. |
| /// |
| /// \param arguments The arguments to |
| /// |
| /// \param brokenProtocolDiag Diagnostic to emit if the protocol is broken. |
| /// |
| /// \returns a fully type-checked call, or null if the protocol was broken. |
| Expr *callWitness(Expr *base, DeclContext *dc, |
| ProtocolDecl *protocol, |
| ProtocolConformance *conformance, |
| DeclName name, |
| MutableArrayRef<Expr *> arguments, |
| Diag<> brokenProtocolDiag); |
| |
| /// \brief Determine whether the given type contains the given protocol. |
| /// |
| /// \param DC The context in which to check conformance. This affects, for |
| /// example, extension visibility. |
| /// |
| /// \param options Options that control the conformance check. |
| /// |
| /// \param Conformance If non-NULL, and the type does conform to the given |
| /// protocol, this will be set to the protocol conformance mapping that |
| /// maps the given type \c T to the protocol \c Proto. The mapping may be |
| /// NULL, if the mapping is trivial due to T being either an archetype or |
| /// an existential type that directly implies conformance to \c Proto. |
| /// |
| /// \param ComplainLoc If valid, then this function will emit diagnostics if |
| /// T does not conform to the given protocol. The primary diagnostic will |
| /// be placed at this location, with notes for each of the protocol |
| /// requirements not satisfied. |
| /// |
| /// \returns true if T conforms to the protocol Proto, false otherwise. |
| /// |
| /// \note If this method returns 'true', it only means that there exists a |
| /// declared conformance of \c T to \c Proto. It does not mean that this |
| /// conformance is valid. Check \c (*Conformance)->getState() for that. |
| bool containsProtocol(Type T, ProtocolDecl *Proto, |
| DeclContext *DC, |
| ConformanceCheckOptions options, |
| ProtocolConformance **Conformance = nullptr, |
| SourceLoc ComplainLoc = SourceLoc()); |
| |
| /// \brief Determine whether the given type conforms to the given protocol. |
| /// |
| /// Unlike subTypeOfProtocol(), this will return false for existentials of |
| /// non-self conforming protocols. |
| /// |
| /// \param DC The context in which to check conformance. This affects, for |
| /// example, extension visibility. |
| /// |
| /// \param options Options that control the conformance check. |
| /// |
| /// \param Conformance If non-NULL, and the type does conform to the given |
| /// protocol, this will be set to the protocol conformance mapping that |
| /// maps the given type \c T to the protocol \c Proto. The mapping may be |
| /// NULL, if the mapping is trivial due to T being either an archetype or |
| /// an existential type that directly implies conformance to \c Proto. |
| /// |
| /// \param ComplainLoc If valid, then this function will emit diagnostics if |
| /// T does not conform to the given protocol. The primary diagnostic will |
| /// be placed at this location, with notes for each of the protocol |
| /// requirements not satisfied. |
| /// |
| /// \returns true if T conforms to the protocol Proto, false otherwise. |
| /// |
| /// \note If this method returns 'true', it only means that there exists a |
| /// declared conformance of \c T to \c Proto. It does not mean that this |
| /// conformance is valid. Check \c (*Conformance)->getState() for that. |
| bool conformsToProtocol(Type T, ProtocolDecl *Proto, DeclContext *DC, |
| ConformanceCheckOptions options, |
| ProtocolConformance **Conformance = nullptr, |
| SourceLoc ComplainLoc = SourceLoc()); |
| |
| /// Derive an implicit declaration to satisfy a requirement of a derived |
| /// protocol conformance. |
| /// |
| /// \param DC The declaration context where the conformance was |
| /// defined, either the type itself or an extension |
| /// \param TypeDecl The type for which the requirement is being derived. |
| /// \param Requirement The protocol requirement. |
| /// |
| /// \returns nullptr if the derivation failed, or the derived declaration |
| /// if it succeeded. If successful, the derived declaration is added |
| /// to TypeDecl's body. |
| ValueDecl *deriveProtocolRequirement(DeclContext *DC, |
| NominalTypeDecl *TypeDecl, |
| ValueDecl *Requirement); |
| |
| /// Derive an implicit type witness for the given associated type in |
| /// the conformance of the given nominal type to some known |
| /// protocol. |
| Type deriveTypeWitness(DeclContext *DC, |
| NominalTypeDecl *nominal, |
| AssociatedTypeDecl *assocType); |
| |
| /// Perform unqualified name lookup at the given source location |
| /// within a particular declaration context. |
| /// |
| /// \param dc The declaration context in which to perform name lookup. |
| /// \param name The name of the entity to look for. |
| /// \param loc The source location at which name lookup occurs. |
| /// \param options Options that control name lookup. |
| LookupResult lookupUnqualified(DeclContext *dc, DeclName name, SourceLoc loc, |
| NameLookupOptions options |
| = defaultUnqualifiedLookupOptions); |
| |
| /// \brief Lookup a member in the given type. |
| /// |
| /// \param dc The context that needs the member. |
| /// \param type The type in which we will look for a member. |
| /// \param name The name of the member to look for. |
| /// \param options Options that control name lookup. |
| /// |
| /// \returns The result of name lookup. |
| LookupResult lookupMember(DeclContext *dc, Type type, DeclName name, |
| NameLookupOptions options |
| = defaultMemberLookupOptions); |
| |
| /// \brief Look up a member type within the given type. |
| /// |
| /// This routine looks for member types with the given name within the |
| /// given type. |
| /// |
| /// \param dc The context that needs the member. |
| /// \param type The type in which we will look for a member type. |
| /// \param name The name of the member to look for. |
| /// \param options Options that control name lookup. |
| /// |
| /// \returns The result of name lookup. |
| LookupTypeResult lookupMemberType(DeclContext *dc, Type type, |
| Identifier name, |
| NameLookupOptions options |
| = defaultMemberTypeLookupOptions); |
| |
| /// \brief Look up the constructors of the given type. |
| /// |
| /// \param dc The context that needs the constructor. |
| /// \param type The type for which we will look for constructors. |
| /// \param options Options that control name lookup. |
| /// |
| /// \returns the constructors found for this type. |
| LookupResult lookupConstructors(DeclContext *dc, Type type, |
| NameLookupOptions options |
| = defaultConstructorLookupOptions); |
| |
| /// \brief Look up the Bool type in the standard library. |
| Type lookupBoolType(const DeclContext *dc); |
| |
| /// Diagnose an ambiguous member type lookup result. |
| void diagnoseAmbiguousMemberType(Type baseTy, SourceRange baseRange, |
| Identifier name, SourceLoc nameLoc, |
| LookupTypeResult &lookup); |
| |
| /// Emit a diagnostic for references to declarations that have been |
| /// marked as unavailable, either through "unavailable" or "obsoleted=". |
| bool diagnoseExplicitUnavailability(const ValueDecl *D, |
| SourceRange R, |
| const DeclContext *DC); |
| |
| /// @} |
| |
| /// Fix the name of the given function to the target name, attaching |
| /// Fix-Its to the provided in-flight diagnostic. |
| void fixAbstractFunctionNames(InFlightDiagnostic &diag, |
| AbstractFunctionDecl *func, |
| DeclName targetName); |
| |
| /// \name Overload resolution |
| /// |
| /// Routines that perform overload resolution or provide diagnostics related |
| /// to overload resolution. |
| /// @{ |
| |
| /// Compare two declarations to determine whether one is more specialized |
| /// than the other. |
| /// |
| /// A declaration is more specialized than another declaration if its type |
| /// is a subtype of the other declaration's type (ignoring the 'self' |
| /// parameter of function declarations) and if |
| Comparison compareDeclarations(DeclContext *dc, |
| ValueDecl *decl1, |
| ValueDecl *decl2); |
| |
| /// \brief Build a type-checked reference to the given value. |
| Expr *buildCheckedRefExpr(ValueDecl *D, DeclContext *UseDC, |
| SourceLoc nameLoc, bool Implicit); |
| |
| /// \brief Build a reference to a declaration, where name lookup returned |
| /// the given set of declarations. |
| Expr *buildRefExpr(ArrayRef<ValueDecl *> Decls, DeclContext *UseDC, |
| SourceLoc NameLoc, bool Implicit, |
| bool isSpecialized = false); |
| /// @} |
| |
| /// \brief Retrieve a specific, known protocol. |
| /// |
| /// \param loc The location at which we need to look for the protocol. |
| /// \param kind The known protocol we're looking for. |
| /// |
| /// \returns null if the protocol is not available. This represents a |
| /// problem with the Standard Library. |
| ProtocolDecl *getProtocol(SourceLoc loc, KnownProtocolKind kind); |
| |
| /// \brief Retrieve the literal protocol for the given expression. |
| /// |
| /// \returns the literal protocol, if known and available, or null if the |
| /// expression does not have an associated literal protocol. |
| ProtocolDecl *getLiteralProtocol(Expr *expr); |
| |
| DeclName getObjectLiteralConstructorName(ObjectLiteralExpr *expr); |
| |
| /// Get the module appropriate for looking up standard library types. |
| /// |
| /// This is "Swift", if that module is imported, or the current module if |
| /// we're parsing the standard library. |
| Module *getStdlibModule(const DeclContext *dc); |
| |
| /// \name AST Mutation Listener Implementation |
| /// @{ |
| void handleExternalDecl(Decl *decl); |
| |
| /// @} |
| |
| /// \name Lazy resolution. |
| /// |
| /// Routines that perform lazy resolution as required for AST operations. |
| /// @{ |
| void checkConformance(NormalProtocolConformance *conformance) override; |
| void resolveTypeWitness(const NormalProtocolConformance *conformance, |
| AssociatedTypeDecl *assocType) override; |
| void resolveWitness(const NormalProtocolConformance *conformance, |
| ValueDecl *requirement) override; |
| Type resolveMemberType(DeclContext *dc, Type type, |
| Identifier name) override; |
| |
| bool isCIntegerType(const DeclContext *DC, Type T); |
| bool isRepresentableInObjC(const AbstractFunctionDecl *AFD, |
| ObjCReason Reason, |
| Optional<ForeignErrorConvention> &errorConvention); |
| bool isRepresentableInObjC(const VarDecl *VD, ObjCReason Reason); |
| bool isRepresentableInObjC(const SubscriptDecl *SD, ObjCReason Reason); |
| bool isTriviallyRepresentableInObjC(const DeclContext *DC, Type T); |
| bool isRepresentableInObjC(const DeclContext *DC, Type T); |
| |
| void diagnoseTypeNotRepresentableInObjC(const DeclContext *DC, |
| Type T, SourceRange TypeRange); |
| |
| void fillObjCRepresentableTypeCache(const DeclContext *DC); |
| |
| ArchetypeBuilder createArchetypeBuilder(Module *mod); |
| |
| /// \name Availability checking |
| /// |
| /// Routines that perform API availability checking and type checking of |
| /// potentially unavailable API elements |
| /// @{ |
| |
| /// \brief Returns true if the availability of the overriding declaration |
| /// makes it a safe override, given the availability of the base declaration. |
| bool isAvailabilitySafeForOverride(ValueDecl *override, ValueDecl *base); |
| |
| /// \brief Returns true if the availability of the witness |
| /// is sufficient to safely conform to the requirement in the context |
| /// the provided conformance. On return, requiredRange holds the range |
| /// required for conformance. |
| bool isAvailabilitySafeForConformance(ValueDecl *witness, |
| ValueDecl *requirement, |
| NormalProtocolConformance *conformance, |
| VersionRange &requiredRange); |
| |
| /// Returns an over-approximation of the range of operating system versions |
| /// that could the passed-in location could be executing upon for |
| /// the target platform. |
| VersionRange overApproximateOSVersionsAtLocation(SourceLoc loc, |
| const DeclContext *DC); |
| |
| /// Walk the AST to build the hierarchy of TypeRefinementContexts |
| /// |
| /// \param StartElem Where to start for incremental building of refinement |
| /// contexts |
| void buildTypeRefinementContextHierarchy(SourceFile &SF, |
| unsigned StartElem); |
| |
| /// Build the hierarchy of TypeRefinementContexts for the entire |
| /// source file, if it has not already been built. Returns the root |
| /// TypeRefinementContext for the source file. |
| TypeRefinementContext *getOrBuildTypeRefinementContext(SourceFile *SF); |
| |
| /// Returns a diagnostic indicating why the declaration cannot be annotated |
| /// with an @available() attribute indicating it is potentially unavailable |
| /// or None if this is allowed. |
| Optional<Diag<>> |
| diagnosticIfDeclCannotBePotentiallyUnavailable(const Decl *D); |
| |
| /// Checks whether a declaration is available when referred to at the given |
| /// location (this reference location must be in the passed-in |
| /// reference DeclContext). |
| /// If the declaration is available, return true. |
| /// If the declaration is not available, return false and write the |
| /// declaration's available version range to the out parameter |
| /// OutAvailableRange. |
| bool isDeclAvailable(const Decl *D, SourceLoc referenceLoc, |
| const DeclContext *referenceDC, |
| VersionRange &OutAvailableRange); |
| |
| /// Checks whether a declaration should be considered unavailable when |
| /// referred to at the given location and, if so, returns the reason why the |
| /// declaration is unavailable. Returns None is the declaration is |
| /// definitely available. |
| Optional<UnavailabilityReason> |
| checkDeclarationAvailability(const Decl *D, SourceLoc referenceLoc, |
| const DeclContext *referenceDC); |
| |
| /// Checks an "ignored" expression to see if it's okay for it to be ignored. |
| /// |
| /// An ignored expression is one that is not nested within a larger |
| /// expression or statement. The warning from the \@warn_unused_result |
| /// attribute is produced here. |
| void checkIgnoredExpr(Expr *E); |
| |
| // Emits a diagnostic, if necessary, for a reference to a declaration |
| // that is potentially unavailable at the given source location. |
| void diagnosePotentialUnavailability(const ValueDecl *D, |
| SourceRange ReferenceRange, |
| const DeclContext *ReferenceDC, |
| const UnavailabilityReason &Reason); |
| |
| // Emits a diagnostic, if necessary, for a reference to a declaration |
| // that is potentially unavailable at the given source location, using |
| // Name as the diagnostic name. |
| void diagnosePotentialUnavailability(const Decl *D, DeclName Name, |
| SourceRange ReferenceRange, |
| const DeclContext *ReferenceDC, |
| const UnavailabilityReason &Reason); |
| |
| /// Emits a diagnostic for a reference to a storage accessor that is |
| /// potentially unavailable. |
| void diagnosePotentialAccessorUnavailability( |
| FuncDecl *Accessor, SourceRange ReferenceRange, |
| const DeclContext *ReferenceDC, const UnavailabilityReason &Reason, |
| bool ForInout); |
| |
| /// Returns true if the reference or any of its parents is an |
| /// implicit function. |
| bool isInsideImplicitFunction(SourceRange ReferenceRange, |
| const DeclContext *DC); |
| |
| /// Returns true if the reference or any of its parents is an |
| /// unavailable (or obsoleted) declaration. |
| bool isInsideUnavailableDeclaration(SourceRange ReferenceRange, |
| const DeclContext *DC); |
| |
| /// Returns the availability attribute indicating deprecation if the |
| /// declaration is deprecated or null otherwise. |
| static const AvailableAttr *getDeprecated(const Decl *D); |
| |
| /// Emits a diagnostic for a reference to a declaration that is deprecated. |
| /// Callers can provide a lambda that adds additional information (such as a |
| /// fixit hint) to the deprecation diagnostic, if it is emitted. |
| void diagnoseDeprecated(SourceRange SourceRange, |
| const DeclContext *ReferenceDC, |
| const AvailableAttr *Attr, |
| DeclName Name, |
| std::function<void(InFlightDiagnostic&)> extraInfoHandler = |
| [](InFlightDiagnostic&){}); |
| /// @} |
| |
| /// If LangOptions::DebugForbidTypecheckPrefix is set and the given decl |
| /// has a name with that prefix, an llvm fatal_error is triggered. |
| /// This is for testing purposes. |
| void checkForForbiddenPrefix(const Decl *D); |
| void checkForForbiddenPrefix(const UnresolvedDeclRefExpr *E); |
| void checkForForbiddenPrefix(Identifier Ident); |
| void checkForForbiddenPrefix(StringRef Name); |
| |
| bool hasEnabledForbiddenTypecheckPrefix() const { |
| return !Context.LangOpts.DebugForbidTypecheckPrefix.empty(); |
| } |
| |
| /// Check error handling in the given type-checked top-level code. |
| void checkTopLevelErrorHandling(TopLevelCodeDecl *D); |
| void checkFunctionErrorHandling(AbstractFunctionDecl *D); |
| void checkInitializerErrorHandling(Initializer *I, Expr *E); |
| void checkEnumElementErrorHandling(EnumElementDecl *D); |
| |
| void addExprForDiagnosis(Expr *E1, Expr *Result) { |
| DiagnosedExprs[E1] = Result; |
| } |
| Expr *isExprBeingDiagnosed(Expr *E) { |
| return DiagnosedExprs[E]; |
| } |
| |
| /// If an expression references 'self.init' or 'super.init' in an |
| /// initializer context, returns the implicit 'self' decl of the constructor. |
| /// Otherwise, return nil. |
| VarDecl *getSelfForInitDelegationInConstructor(DeclContext *DC, |
| UnresolvedConstructorExpr *ctorRef); |
| |
| /// When referencing a class initializer, check that the base expression is |
| /// either a static metatype or that the initializer is 'required'. |
| bool |
| diagnoseInvalidDynamicConstructorReferences(Expr *base, |
| SourceLoc memberRefLoc, |
| AnyMetatypeType *metaTy, |
| ConstructorDecl *ctorDecl, |
| bool SuppressDiagnostics); |
| |
| /// Check for needless words in the name of the given function/constructor. |
| void checkOmitNeedlessWords(AbstractFunctionDecl *afd); |
| |
| /// Check for needless words in the name of the given variable. |
| void checkOmitNeedlessWords(VarDecl *var); |
| |
| /// Check for needless words in the name of the function/constructor being |
| /// called. |
| void checkOmitNeedlessWords(ApplyExpr *apply); |
| |
| /// Check for needless words in the member reference. |
| void checkOmitNeedlessWords(MemberRefExpr *memberRef); |
| }; |
| |
| /// \brief RAII object that cleans up the given expression if not explicitly |
| /// disabled. |
| class CleanupIllFormedExpressionRAII { |
| ASTContext &Context; |
| Expr **expr; |
| |
| public: |
| CleanupIllFormedExpressionRAII(ASTContext &Context, Expr *&expr) |
| : Context(Context), expr(&expr) { } |
| |
| ~CleanupIllFormedExpressionRAII(); |
| |
| static void doIt(Expr *expr, ASTContext &Context); |
| |
| /// \brief Disable the cleanup of this expression; it doesn't need it. |
| void disable() { |
| expr = nullptr; |
| } |
| }; |
| |
| /// Temporary on-stack storage and unescaping for encoded diagnostic |
| /// messages. |
| /// |
| /// |
| class EncodedDiagnosticMessage { |
| llvm::SmallString<128> Buf; |
| |
| public: |
| /// \param S A string with an encoded message |
| EncodedDiagnosticMessage(StringRef S) |
| : Message(Lexer::getEncodedStringSegment(S, Buf)) {} |
| |
| /// The unescaped message to display to the user. |
| const StringRef Message; |
| }; |
| |
| } // end namespace swift |
| |
| #endif |