| //===--- 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/GenericParamList.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/Sema/ConstraintSystem.h" |
| #include "swift/Config.h" |
| #include "llvm/ADT/SetVector.h" |
| #include "llvm/ADT/TinyPtrVector.h" |
| #include <functional> |
| |
| namespace swift { |
| |
| class ExportContext; |
| class GenericSignatureBuilder; |
| class NominalTypeDecl; |
| class NormalProtocolConformance; |
| class RootProtocolConformance; |
| class TypeResolution; |
| class TypeResolutionOptions; |
| class TypoCorrectionResults; |
| class ExprPattern; |
| enum class TypeResolutionStage : uint8_t; |
| enum class ExportabilityReason : unsigned; |
| |
| namespace constraints { |
| enum class ConstraintKind : char; |
| class ConstraintSystem; |
| class Solution; |
| class SolutionApplicationTarget; |
| class SolutionResult; |
| } |
| |
| /// 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, |
| }; |
| |
| /// 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; |
| |
| 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(); |
| } |
| }; |
| |
| /// Flags that can be used to control type checking. |
| 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, |
| |
| /// 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 = 0x02, |
| |
| /// 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 = 0x04, |
| |
| /// Don't try to type check closure expression bodies, and leave them |
| /// unchecked. This is used by source tooling functionalities such as code |
| /// completion. |
| LeaveClosureBodyUnchecked = 0x08, |
| }; |
| |
| 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 to ignore access control for this lookup, allowing inaccessible |
| /// results to be returned. |
| IgnoreAccessControl = 1 << 0, |
| /// Whether to include results from outside the innermost scope that has a |
| /// result. |
| IncludeOuterResults = 1 << 1, |
| // Whether to include results that are marked @inlinable or @usableFromInline. |
| IncludeUsableFromInline = 1 << 2, |
| }; |
| |
| /// 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; |
| |
| /// Default options for member type lookup. |
| const NameLookupOptions defaultMemberTypeLookupOptions; |
| |
| /// Default options for unqualified name lookup. |
| const NameLookupOptions defaultUnqualifiedLookupOptions; |
| |
| /// 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 |
| }; |
| |
| /// 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); |
| }; |
| |
| /// The result of `checkGenericRequirement`. |
| enum class RequirementCheckResult { |
| Success, Failure, SubstitutionFailure |
| }; |
| |
| /// 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, |
| /// Coerce to checked cast. Used when we verify if it is possible to |
| /// suggest to convert a coercion to a checked cast. |
| Coercion, |
| }; |
| |
| namespace TypeChecker { |
| Type getArraySliceType(SourceLoc loc, Type elementType); |
| Type getOptionalType(SourceLoc loc, Type elementType); |
| |
| /// Bind an UnresolvedDeclRefExpr by performing name lookup and |
| /// returning the resultant expression. Context is the DeclContext used |
| /// for the lookup. |
| /// |
| /// \param replaceInvalidRefsWithErrors Indicates whether it's allowed |
| /// to replace any discovered invalid member references with `ErrorExpr`. |
| Expr *resolveDeclRefExpr(UnresolvedDeclRefExpr *UDRE, DeclContext *Context, |
| bool replaceInvalidRefsWithErrors); |
| |
| /// Check for unsupported protocol types in the given declaration. |
| void checkUnsupportedProtocolType(Decl *decl); |
| |
| /// Check for unsupported protocol types in the given statement. |
| void checkUnsupportedProtocolType(ASTContext &ctx, Stmt *stmt); |
| |
| /// Check for unsupported protocol types in the given generic requirement |
| /// list. |
| void checkUnsupportedProtocolType(ASTContext &ctx, |
| TrailingWhereClause *whereClause); |
| |
| /// Check for unsupported protocol types in the given generic requirement |
| /// list. |
| void checkUnsupportedProtocolType(ASTContext &ctx, |
| GenericParamList *genericParams); |
| |
| /// 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. |
| Type resolveTypeInContext(TypeDecl *typeDecl, DeclContext *foundDC, |
| TypeResolution resolution, bool isSpecialized); |
| |
| /// Apply generic arguments to the unbound generic type represented by the |
| /// given declaration and parent type. |
| /// |
| /// This function requires the correct number of generic arguments, |
| /// whereas applyGenericArguments emits diagnostics in those cases. |
| /// |
| /// \param decl The declaration that the resulting bound generic type |
| /// shall reference. |
| /// \param parentTy The parent type. |
| /// \param loc The source location for diagnostic reporting. |
| /// \param resolution The type resolution. |
| /// \param genericArgs The list of generic arguments to apply. |
| /// |
| /// \returns A BoundGenericType bound to the given arguments, or null on |
| /// error. |
| /// |
| /// \see applyGenericArguments |
| Type applyUnboundGenericArguments(GenericTypeDecl *decl, Type parentTy, |
| 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. |
| 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 |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| 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. |
| Expr *substituteInputSugarTypeForResult(ApplyExpr *E); |
| |
| void typeCheckASTNode(ASTNode &node, DeclContext *DC, |
| bool LeaveBodyUnchecked = false); |
| |
| /// Try to apply the result builder transform of the given builder type |
| /// to the body of the function. |
| /// |
| /// \returns \c None if the builder transformation cannot be applied at all, |
| /// e.g., because of a \c return statement. Otherwise, returns either the |
| /// fully type-checked body of the function (on success) or a \c nullptr |
| /// value if an error occurred while type checking the transformed body. |
| Optional<BraceStmt *> applyResultBuilderBodyTransform(FuncDecl *func, |
| Type builderType); |
| |
| /// Find the return statements within the body of the given function. |
| std::vector<ReturnStmt *> findReturnStatements(AnyFunctionRef fn); |
| |
| bool typeCheckClosureBody(ClosureExpr *closure); |
| |
| bool typeCheckTapBody(TapExpr *expr, DeclContext *DC); |
| |
| Type typeCheckParameterDefault(Expr *&defaultValue, DeclContext *DC, |
| Type paramType, bool isAutoClosure); |
| |
| void typeCheckTopLevelCodeDecl(TopLevelCodeDecl *TLCD); |
| |
| void typeCheckDecl(Decl *D); |
| |
| void addImplicitDynamicAttribute(Decl *D); |
| void checkDeclAttributes(Decl *D); |
| void checkParameterList(ParameterList *params, DeclContext *owner); |
| |
| void diagnoseDuplicateBoundVars(Pattern *pattern); |
| |
| void diagnoseDuplicateCaptureVars(CaptureListExpr *expr); |
| |
| Type checkReferenceOwnershipAttr(VarDecl *D, Type interfaceType, |
| ReferenceOwnershipAttr *attr); |
| |
| /// Infer default value witnesses for all requirements in the given protocol. |
| 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. |
| 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. |
| void checkReferencedGenericParams(GenericContext *dc); |
| |
| /// Construct a new generic environment for the given declaration context. |
| /// |
| /// \param paramSource The source of generic info: either a generic parameter |
| /// list or a generic context with a \c where clause dependent on outer |
| /// generic parameters. |
| /// |
| /// \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. |
| GenericSignature |
| checkGenericSignature(GenericParamSource paramSource, 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. |
| 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. |
| RequirementCheckResult checkGenericArguments( |
| DeclContext *dc, SourceLoc loc, SourceLoc noteLoc, Type owner, |
| TypeArrayView<GenericTypeParamType> genericParams, |
| ArrayRef<Requirement> requirements, TypeSubstitutionFn substitutions, |
| SubstOptions options = None); |
| |
| bool checkContextualRequirements(GenericTypeDecl *decl, |
| Type parentTy, |
| SourceLoc loc, |
| DeclContext *dc); |
| |
| /// Add any implicitly-defined constructors required for the given |
| /// struct or class. |
| void addImplicitConstructors(NominalTypeDecl *typeDecl); |
| |
| /// Fold the given sequence expression into an (unchecked) expression |
| /// tree. |
| Expr *foldSequence(SequenceExpr *expr, DeclContext *dc); |
| |
| /// Given an pre-folded expression, find LHS from the expression if a binary |
| /// operator \c name appended to the expression. |
| Expr *findLHS(DeclContext *DC, Expr *E, Identifier name); |
| |
| /// Type check the given expression. |
| /// |
| /// \param expr The expression to type-check, which will be modified in |
| /// place. |
| /// |
| /// \param contextualInfo The type that the expression is being converted to, |
| /// or null if the expression is standalone. 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 options Options that control how type checking is performed. |
| /// |
| /// \returns The type of the top-level expression, or Type() if an |
| /// error occurred. |
| Type typeCheckExpression(Expr *&expr, DeclContext *dc, |
| constraints::ContextualTypeInfo contextualInfo = {}, |
| TypeCheckExprOptions options = TypeCheckExprOptions()); |
| |
| Optional<constraints::SolutionApplicationTarget> |
| typeCheckExpression(constraints::SolutionApplicationTarget &target, |
| TypeCheckExprOptions options = TypeCheckExprOptions()); |
| |
| /// Return the type of operator function for specified LHS, or a null |
| /// \c Type on error. |
| FunctionType *getTypeOfCompletionOperator(DeclContext *DC, Expr *LHS, |
| Identifier opName, |
| DeclRefKind refKind, |
| ConcreteDeclRef &refdDecl); |
| |
| /// Type check the given expression and provide results back to code completion |
| /// via specified callback. |
| /// |
| /// This method is designed to be used for code completion which means that |
| /// it doesn't mutate given expression, even if there is a single valid |
| /// solution, and constraint solver is allowed to produce partially correct |
| /// solutions. Such solutions can have any number of holes in them. |
| /// |
| /// \returns `true` if target was applicable and it was possible to infer |
| /// types for code completion, `false` othrewise. |
| bool typeCheckForCodeCompletion( |
| constraints::SolutionApplicationTarget &target, bool needsPrecheck, |
| llvm::function_ref<void(const constraints::Solution &)> callback); |
| |
| /// Check the key-path expression. |
| /// |
| /// Returns the type of the last component of the key-path. |
| Optional<Type> checkObjCKeyPathExpr(DeclContext *dc, KeyPathExpr *expr, |
| bool requireResultType = false); |
| |
| /// Type check whether the given type declaration includes members of |
| /// unsupported recursive value types. |
| /// |
| /// \param decl The declaration to be type-checked. This process will not |
| /// modify the declaration. |
| void checkDeclCircularity(NominalTypeDecl *decl); |
| |
| /// Type check whether the given switch statement exhaustively covers |
| /// its domain. |
| /// |
| /// \param stmt The switch statement to be type-checked. No modification of |
| /// the statement occurs. |
| /// \param DC The decl context containing \p stmt. |
| /// \param limitChecking The checking process relies on the switch statement |
| /// being well-formed. If it is not, pass true to this flag to run a limited |
| /// form of analysis. |
| void checkSwitchExhaustiveness(const SwitchStmt *stmt, const DeclContext *DC, |
| bool limitChecking); |
| |
| /// 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); |
| |
| /// 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 fromExpr The expression describing the input operand. |
| /// \param diagToRange The source range of the destination type. |
| /// |
| /// \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, |
| CheckedCastContextKind ctxKind, |
| DeclContext *dc, SourceLoc diagLoc, |
| Expr *fromExpr, SourceRange diagToRange); |
| |
| /// 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); |
| |
| /// 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. |
| /// |
| /// \returns the type of the pattern, which may be an error type if an |
| /// unrecoverable error occurred. If the options permit it, the type may |
| /// involve \c UnresolvedType (for patterns with no type information) and |
| /// unbound generic types. |
| Type typeCheckPattern(ContextualPattern pattern); |
| |
| /// Coerce a pattern to the given type. |
| /// |
| /// \param pattern The contextual pattern. |
| /// \param type the type to coerce the pattern to. |
| /// \param options Options that control the coercion. |
| /// |
| /// \returns the coerced pattern, or nullptr if the coercion failed. |
| Pattern *coercePatternToType(ContextualPattern pattern, Type type, |
| TypeResolutionOptions options); |
| bool typeCheckExprPattern(ExprPattern *EP, DeclContext *DC, Type type); |
| |
| /// Coerce the specified parameter list of a ClosureExpr to the specified |
| /// contextual type. |
| void coerceParameterListToType(ParameterList *P, ClosureExpr *CE, |
| AnyFunctionType *FN); |
| |
| /// Type-check an initialized variable pattern declaration. |
| bool typeCheckBinding(Pattern *&P, Expr *&Init, DeclContext *DC, |
| Type patternType, |
| PatternBindingDecl *PBD = nullptr, |
| unsigned patternNumber = 0); |
| bool typeCheckPatternBinding(PatternBindingDecl *PBD, unsigned patternNumber, |
| Type patternType = Type()); |
| |
| /// Type-check a for-each loop's pattern binding and sequence together. |
| /// |
| /// \returns true if a failure occurred. |
| bool typeCheckForEachBinding(DeclContext *dc, ForEachStmt *stmt); |
| |
| /// Compute the set of captures for the given function or closure. |
| void computeCaptures(AnyFunctionRef AFR); |
| |
| /// Check for invalid captures from stored property initializers. |
| void checkPatternBindingCaptures(IterableDeclContext *DC); |
| |
| /// Change the context of closures in the given initializer |
| /// expression to the given context. |
| void contextualizeInitializer(Initializer *DC, Expr *init); |
| void contextualizeTopLevelCode(TopLevelCodeDecl *TLCD); |
| |
| /// 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); |
| |
| /// Coerce the given expression to materializable type, if it |
| /// isn't already. |
| Expr *coerceToRValue( |
| ASTContext &Context, Expr *expr, |
| llvm::function_ref<Type(Expr *)> getType = |
| [](Expr *expr) { return expr->getType(); }, |
| llvm::function_ref<void(Expr *, Type)> setType = |
| [](Expr *expr, Type type) { expr->setType(type); }); |
| |
| /// Add implicit load expression to given AST, this is sometimes |
| /// more complicated than simplify wrapping given root in newly created |
| /// `LoadExpr`, because `ForceValueExpr` and `ParenExpr` supposed to appear |
| /// only at certain positions in AST. |
| Expr *addImplicitLoadExpr( |
| ASTContext &Context, Expr *expr, |
| std::function<Type(Expr *)> getType = [](Expr *E) { return E->getType(); }, |
| std::function<void(Expr *, Type)> setType = |
| [](Expr *E, Type type) { E->setType(type); }); |
| |
| /// Determine whether the given type contains the given protocol. |
| /// |
| /// \param DC The context in which to check conformance. This affects, for |
| /// example, extension visibility. |
| /// |
| /// \returns the conformance, if \c T conforms to the protocol \c Proto, or |
| /// an empty optional. |
| ProtocolConformanceRef containsProtocol(Type T, ProtocolDecl *Proto, |
| DeclContext *DC, |
| bool skipConditionalRequirements=false); |
| |
| /// 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. |
| /// |
| /// \returns The protocol conformance, if \c T conforms to the |
| /// protocol \c Proto, or \c None. |
| ProtocolConformanceRef conformsToProtocol(Type T, ProtocolDecl *Proto, |
| DeclContext *DC); |
| |
| /// This is similar to \c conformsToProtocol, but returns \c true for cases where |
| /// the type \p T could be dynamically cast to \p Proto protocol, such as a non-final |
| /// class where a subclass conforms to \p Proto. |
| /// |
| /// \param DC The context in which to check conformance. This affects, for |
| /// example, extension visibility. |
| /// |
| /// |
| /// \returns True if \p T conforms to the protocol \p Proto, false otherwise. |
| bool couldDynamicallyConformToProtocol(Type T, ProtocolDecl *Proto, |
| DeclContext *DC); |
| /// Completely check the given conformance. |
| void checkConformance(NormalProtocolConformance *conformance); |
| |
| /// Check all of the conformances in the given context. |
| void checkConformancesInContext(IterableDeclContext *idc); |
| |
| /// Check that the type of the given property conforms to NSCopying. |
| ProtocolConformanceRef checkConformanceToNSCopying(VarDecl *var); |
| |
| /// 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. |
| std::pair<Type, TypeDecl *> |
| deriveTypeWitness(DeclContext *DC, NominalTypeDecl *nominal, |
| AssociatedTypeDecl *assocType); |
| |
| /// \name Name lookup |
| /// |
| /// Routines that perform name lookup. |
| /// |
| /// @{ |
| |
| /// 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, DeclNameRef name, SourceLoc loc, |
| NameLookupOptions options = defaultUnqualifiedLookupOptions); |
| |
| /// Perform unqualified type 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 lookupUnqualifiedType( |
| DeclContext *dc, DeclNameRef name, SourceLoc loc, |
| NameLookupOptions options = defaultUnqualifiedLookupOptions); |
| |
| /// 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, DeclNameRef name, |
| NameLookupOptions options = defaultMemberLookupOptions); |
| |
| /// 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, DeclNameRef name, |
| NameLookupOptions options = defaultMemberTypeLookupOptions); |
| |
| /// Given an expression that's known to be an infix operator, |
| /// look up its precedence group. |
| PrecedenceGroupDecl *lookupPrecedenceGroupForInfixOperator(DeclContext *dc, |
| Expr *op); |
| |
| PrecedenceGroupLookupResult |
| lookupPrecedenceGroup(DeclContext *dc, Identifier name, SourceLoc nameLoc); |
| |
| enum class UnsupportedMemberTypeAccessKind : uint8_t { |
| None, |
| TypeAliasOfUnboundGeneric, |
| TypeAliasOfExistential, |
| AssociatedTypeOfUnboundGeneric, |
| AssociatedTypeOfExistential |
| }; |
| |
| /// Check whether the given declaration can be written as a |
| /// member of the given base type. |
| UnsupportedMemberTypeAccessKind |
| isUnsupportedMemberTypeAccess(Type type, TypeDecl *typeDecl); |
| |
| /// @} |
| |
| /// \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); |
| |
| /// Build a type-checked reference to the given value. |
| Expr *buildCheckedRefExpr(VarDecl *D, DeclContext *UseDC, DeclNameLoc nameLoc, |
| bool Implicit); |
| |
| /// Build a reference to a declaration, where name lookup returned |
| /// the given set of declarations. |
| Expr *buildRefExpr(ArrayRef<ValueDecl *> Decls, DeclContext *UseDC, |
| DeclNameLoc NameLoc, bool Implicit, |
| FunctionRefKind functionRefKind); |
| /// @} |
| |
| /// 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(ASTContext &ctx, SourceLoc loc, |
| KnownProtocolKind kind); |
| |
| /// 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(ASTContext &ctx, Expr *expr); |
| |
| DeclName getObjectLiteralConstructorName(ASTContext &ctx, |
| 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. |
| ModuleDecl *getStdlibModule(const DeclContext *dc); |
| |
| Expr *buildDefaultInitializer(Type type); |
| |
| /// \name Resilience diagnostics |
| |
| bool diagnoseInlinableDeclRefAccess(SourceLoc loc, const ValueDecl *D, |
| const ExportContext &where); |
| |
| /// Given that a declaration is used from a particular context which |
| /// exposes it in the interface of the current module, diagnose if it cannot |
| /// reasonably be shared. |
| bool diagnoseDeclRefExportability(SourceLoc loc, |
| const ValueDecl *D, |
| const ExportContext &where); |
| |
| /// Given that a conformance is used from a particular context which |
| /// exposes it in the interface of the current module, diagnose if the |
| /// conformance is SPI or visible via an implementation-only import. |
| bool diagnoseConformanceExportability(SourceLoc loc, |
| const RootProtocolConformance *rootConf, |
| const ExtensionDecl *ext, |
| const ExportContext &where); |
| |
| /// \name Availability checking |
| /// |
| /// Routines that perform API availability checking and type checking of |
| /// potentially unavailable API elements |
| /// @{ |
| |
| /// Returns true if the availability of the witness |
| /// is sufficient to safely conform to the requirement in the context |
| /// the provided conformance. On return, requiredAvailability holds th |
| /// availability levels required for conformance. |
| bool |
| isAvailabilitySafeForConformance(ProtocolDecl *proto, ValueDecl *requirement, |
| ValueDecl *witness, DeclContext *dc, |
| AvailabilityContext &requiredAvailability); |
| |
| /// 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. If MostRefined != nullptr, set to the most-refined |
| /// TRC found while approximating. |
| AvailabilityContext overApproximateAvailabilityAtLocation( |
| SourceLoc loc, const DeclContext *DC, |
| const TypeRefinementContext **MostRefined = nullptr); |
| |
| /// Walk the AST to build the hierarchy of TypeRefinementContexts |
| void buildTypeRefinementContextHierarchy(SourceFile &SF); |
| |
| /// 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 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, const ExportContext &Where); |
| |
| /// Checks whether a conformance 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> |
| checkConformanceAvailability(const RootProtocolConformance *Conf, |
| const ExtensionDecl *Ext, |
| const ExportContext &Where); |
| |
| /// 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. |
| 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. |
| void diagnosePotentialUnavailability(const RootProtocolConformance *rootConf, |
| const ExtensionDecl *ext, |
| SourceLoc loc, |
| const DeclContext *dc, |
| const UnavailabilityReason &reason); |
| |
| void |
| diagnosePotentialOpaqueTypeUnavailability(SourceRange ReferenceRange, |
| const DeclContext *ReferenceDC, |
| const UnavailabilityReason &Reason); |
| |
| /// Emits a diagnostic for a reference to a storage accessor that is |
| /// potentially unavailable. |
| void diagnosePotentialAccessorUnavailability( |
| const AccessorDecl *Accessor, SourceRange ReferenceRange, |
| const DeclContext *ReferenceDC, const UnavailabilityReason &Reason, |
| bool ForInout); |
| |
| /// Returns the availability attribute indicating deprecation if the |
| /// declaration is deprecated or null otherwise. |
| const AvailableAttr *getDeprecated(const Decl *D); |
| |
| /// Emits a diagnostic for a reference to a declaration that is deprecated. |
| void diagnoseIfDeprecated(SourceRange SourceRange, |
| const ExportContext &Where, |
| const ValueDecl *DeprecatedDecl, |
| const ApplyExpr *Call); |
| |
| /// Emits a diagnostic for a reference to a conformnace that is deprecated. |
| bool diagnoseIfDeprecated(SourceLoc loc, |
| const RootProtocolConformance *rootConf, |
| const ExtensionDecl *ext, |
| const ExportContext &where); |
| /// @} |
| |
| /// If LangOptions::DebugForbidTypecheckPrefix is set and the given decl |
| /// name starts with that prefix, an llvm fatal_error is triggered. |
| /// This is for testing purposes. |
| void checkForForbiddenPrefix(ASTContext &C, DeclBaseName Name); |
| |
| /// Check error handling in the given type-checked top-level code. |
| void checkTopLevelEffects(TopLevelCodeDecl *D); |
| void checkFunctionEffects(AbstractFunctionDecl *D); |
| void checkInitializerEffects(Initializer *I, Expr *E); |
| void checkEnumElementEffects(EnumElementDecl *D, Expr *expr); |
| void checkPropertyWrapperEffects(PatternBindingDecl *binding, Expr *expr); |
| |
| /// Whether the given expression can throw. |
| bool canThrow(Expr *expr); |
| |
| /// 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, |
| UnresolvedDotExpr *UDE); |
| |
| /// Diagnose assigning variable to itself. |
| bool diagnoseSelfAssignment(const Expr *E); |
| |
| /// Builds a string representing a "default" generic argument list for |
| /// \p typeDecl. In general, this means taking the bound of each generic |
| /// parameter. The \p getPreferredType callback can be used to provide a |
| /// different type from the bound. |
| /// |
| /// It may not always be possible to find a single appropriate type for a |
| /// particular parameter (say, if it has two bounds). In this case, an |
| /// Xcode-style placeholder will be used instead. |
| /// |
| /// Returns true if the arguments list could be constructed, false if for |
| /// some reason it could not. |
| bool getDefaultGenericArgumentsString( |
| SmallVectorImpl<char> &buf, const GenericTypeDecl *typeDecl, |
| llvm::function_ref<Type(const GenericTypeParamDecl *)> getPreferredType = |
| [](const GenericTypeParamDecl *) { return Type(); }); |
| |
| /// Attempt to omit needless words from the name of the given declaration. |
| Optional<DeclName> omitNeedlessWords(AbstractFunctionDecl *afd); |
| |
| /// Attempt to omit needless words from the name of the given declaration. |
| Optional<Identifier> omitNeedlessWords(VarDecl *var); |
| |
| /// Calculate edit distance between declaration names. |
| unsigned getCallEditDistance(DeclNameRef writtenName, DeclName correctedName, |
| unsigned maxEditDistance); |
| |
| enum : unsigned { |
| /// Never consider a candidate that's this distance away or worse. |
| UnreasonableCallEditDistance = 8, |
| |
| /// Don't consider candidates that score worse than the given distance |
| /// from the best candidate. |
| MaxCallEditDistanceFromBestCandidate = 1 |
| }; |
| |
| /// Check for a typo correction. |
| void performTypoCorrection(DeclContext *DC, DeclRefKind refKind, |
| Type baseTypeOrNull, |
| NameLookupOptions lookupOptions, |
| TypoCorrectionResults &corrections, |
| GenericSignatureBuilder *gsb = nullptr, |
| unsigned maxResults = 4); |
| |
| /// Check if the given decl has a @_semantics attribute that gives it |
| /// special case type-checking behavior. |
| DeclTypeCheckingSemantics getDeclTypeCheckingSemantics(ValueDecl *decl); |
| |
| /// Infers the differentiability parameter indices for the given |
| /// original or derivative `AbstractFunctionDecl`. |
| /// |
| /// The differentiability parameters are inferred to be: |
| /// - All parameters of the function that conform to `Differentiable`. |
| /// - If the function result type is a function type (i.e. the function has |
| /// a curried method type), then also all parameters of the function result |
| /// type that conform to `Differentiable`. |
| /// |
| /// Used by `@differentiable` and `@derivative` attribute type-checking. |
| IndexSubset * |
| inferDifferentiabilityParameters(AbstractFunctionDecl *AFD, |
| GenericEnvironment *derivativeGenEnv); |
| |
| /// Require that the library intrinsics for working with Optional<T> |
| /// exist. |
| bool requireOptionalIntrinsics(ASTContext &ctx, SourceLoc loc); |
| |
| /// Require that the library intrinsics for working with |
| /// UnsafeMutablePointer<T> exist. |
| bool requirePointerArgumentIntrinsics(ASTContext &ctx, SourceLoc loc); |
| |
| /// Require that the library intrinsics for creating |
| /// array literals exist. |
| bool requireArrayLiteralIntrinsics(ASTContext &ctx, SourceLoc loc); |
| |
| /// Gets the \c UnresolvedMemberExpr at the base of a chain of member accesses. |
| /// If \c expr is not part of a member chain or the base is something other than |
| /// an \c UnresolvedMemberExpr, \c nullptr is returned. |
| UnresolvedMemberExpr *getUnresolvedMemberChainBase(Expr *expr); |
| |
| /// Checks whether a result builder type has a well-formed result builder |
| /// method with the given name. If provided and non-empty, the argument labels |
| /// are verified against any candidates. |
| bool typeSupportsBuilderOp(Type builderType, DeclContext *dc, Identifier fnName, |
| ArrayRef<Identifier> argLabels = {}, |
| SmallVectorImpl<ValueDecl *> *allResults = nullptr); |
| }; // namespace TypeChecker |
| |
| /// 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, true, true, ~0U)) {} |
| |
| /// The unescaped message to display to the user. |
| const StringRef Message; |
| }; |
| |
| /// Returns the protocol requirement kind of the given declaration. |
| /// Used in diagnostics. |
| /// |
| /// Asserts that the given declaration is a protocol requirement. |
| diag::RequirementKind getProtocolRequirementKind(ValueDecl *Requirement); |
| |
| /// Returns true if the given method is an valid implementation of a |
| /// @dynamicCallable attribute requirement. The method is given to be defined |
| /// as one of the following: `dynamicallyCall(withArguments:)` or |
| /// `dynamicallyCall(withKeywordArguments:)`. |
| bool isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, |
| bool hasKeywordArguments); |
| |
| /// Returns true if the given subscript method is an valid implementation of |
| /// the `subscript(dynamicMember:)` requirement for @dynamicMemberLookup. |
| /// The method is given to be defined as `subscript(dynamicMember:)`. |
| bool isValidDynamicMemberLookupSubscript(SubscriptDecl *decl, DeclContext *DC, |
| bool ignoreLabel = false); |
| |
| /// Returns true if the given subscript method is an valid implementation of |
| /// the `subscript(dynamicMember:)` requirement for @dynamicMemberLookup. |
| /// The method is given to be defined as `subscript(dynamicMember:)` which |
| /// takes a single non-variadic parameter that conforms to |
| /// `ExpressibleByStringLiteral` protocol. |
| bool isValidStringDynamicMemberLookup(SubscriptDecl *decl, DeclContext *DC, |
| bool ignoreLabel = false); |
| |
| /// Returns true if the given subscript method is an valid implementation of |
| /// the `subscript(dynamicMember: {Writable}KeyPath<...>)` requirement for |
| /// @dynamicMemberLookup. |
| /// The method is given to be defined as `subscript(dynamicMember:)` which |
| /// takes a single non-variadic parameter of `{Writable}KeyPath<T, U>` type. |
| bool isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl, |
| bool ignoreLabel = false); |
| |
| /// Compute the wrapped value type for the given property that has attached |
| /// property wrappers, when the backing storage is known to have the given type. |
| /// |
| /// \param var A property that has attached property wrappers. |
| /// \param backingStorageType The type of the backing storage property. |
| /// \param limit How many levels of unwrapping to perform, where 0 means to return the |
| /// \c backingStorageType directly and the maximum is the number of attached property wrappers |
| /// (which will produce the original property type). If not specified, defaults to the maximum. |
| Type computeWrappedValueType(VarDecl *var, Type backingStorageType, |
| Optional<unsigned> limit = None); |
| |
| /// Build a call to the init(wrappedValue:) initializers of the property |
| /// wrappers, filling in the given \c value as the original value. Optionally |
| /// pass a callback that will get invoked with the innermost init(wrappedValue:) |
| /// call. |
| Expr *buildPropertyWrapperWrappedValueCall( |
| VarDecl *var, Type backingStorageType, Expr *value, bool ignoreAttributeArgs, |
| llvm::function_ref<void(ApplyExpr *)> callback = [](ApplyExpr *) {}); |
| |
| /// Whether an overriding declaration requires the 'override' keyword. |
| enum class OverrideRequiresKeyword { |
| /// The keyword is never required. |
| Never, |
| /// The keyword is always required. |
| Always, |
| /// The keyword can be implicit; it is not required. |
| Implicit, |
| }; |
| |
| /// Determine whether overriding the given declaration requires a keyword. |
| OverrideRequiresKeyword overrideRequiresKeyword(ValueDecl *overridden); |
| |
| /// Compute the type of a member that will be used for comparison when |
| /// performing override checking. |
| Type getMemberTypeForComparison(const ValueDecl *member, |
| const ValueDecl *derivedDecl = nullptr); |
| |
| /// Determine whether the given declaration is an override by comparing type |
| /// information. |
| bool isOverrideBasedOnType(const ValueDecl *decl, Type declTy, |
| const ValueDecl *parentDecl, Type parentDeclTy); |
| |
| /// Determine whether the given declaration is an operator defined in a |
| /// protocol. If \p type is not null, check specifically whether \p decl |
| /// could fulfill a protocol requirement for it. |
| bool isMemberOperator(FuncDecl *decl, Type type); |
| |
| /// Returns `true` iff `AdditiveArithmetic` derived conformances are enabled. |
| bool isAdditiveArithmeticConformanceDerivationEnabled(SourceFile &SF); |
| |
| /// Diagnose any Objective-C method overrides that aren't reflected |
| /// as overrides in Swift. |
| bool diagnoseUnintendedObjCMethodOverrides(SourceFile &sf); |
| |
| /// Diagnose all conflicts between members that have the same |
| /// Objective-C selector in the same class. |
| /// |
| /// \param sf The source file for which we are diagnosing conflicts. |
| /// |
| /// \returns true if there were any conflicts diagnosed. |
| bool diagnoseObjCMethodConflicts(SourceFile &sf); |
| |
| /// Diagnose any unsatisfied @objc optional requirements of |
| /// protocols that conflict with methods. |
| bool diagnoseObjCUnsatisfiedOptReqConflicts(SourceFile &sf); |
| |
| /// Retrieve information about the given Objective-C method for |
| /// diagnostic purposes, to be used with OBJC_DIAG_SELECT in |
| /// DiagnosticsSema.def. |
| std::pair<unsigned, DeclName> getObjCMethodDiagInfo( |
| AbstractFunctionDecl *method); |
| |
| bool areGenericRequirementsSatisfied(const DeclContext *DC, |
| GenericSignature sig, |
| SubstitutionMap Substitutions, |
| bool isExtension); |
| |
| /// Check for restrictions on the use of the @unknown attribute on a |
| /// case statement. |
| void checkUnknownAttrRestrictions( |
| ASTContext &ctx, CaseStmt *caseBlock, bool &limitExhaustivityChecks); |
| |
| /// Bind all of the pattern variables that occur within a case statement and |
| /// all of its case items to their "parent" pattern variables, forming chains |
| /// of variables with the same name. |
| /// |
| /// Given a case such as: |
| /// \code |
| /// case .a(let x), .b(let x), .c(let x): |
| /// \endcode |
| /// |
| /// Each case item contains a (different) pattern variable named. |
| /// "x". This function will set the "parent" variable of the |
| /// second and third "x" variables to the "x" variable immediately |
| /// to its left. A fourth "x" will be the body case variable, |
| /// whose parent will be set to the "x" within the final case |
| /// item. |
| /// |
| /// Each of the "x" variables must eventually have the same type, and agree on |
| /// let vs. var. This function does not perform any of that validation, leaving |
| /// it to later stages. |
| void bindSwitchCasePatternVars(DeclContext *dc, CaseStmt *stmt); |
| |
| } // end namespace swift |
| |
| #endif |