blob: 7b3c782ae97dfa60abd6dd8b235738b02b170aef [file] [log] [blame]
//===--- TypeCheckType.h - Type Resolution Code ----------*- C++ -*-===//
//
// This source file is part of the Swift.org open source project
//
// Copyright (c) 2014 - 2018 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 utilities for resolving types.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_SEMA_TYPE_CHECK_TYPE_H
#define SWIFT_SEMA_TYPE_CHECK_TYPE_H
#include "swift/AST/TypeResolutionStage.h"
#include "llvm/ADT/None.h"
namespace swift {
/// Flags that describe the context of type checking a pattern or
/// type.
enum class TypeResolutionFlags : uint16_t {
/// Whether to allow unspecified types within a pattern.
AllowUnspecifiedTypes = 1 << 0,
/// Whether to allow unbound generic types.
AllowUnboundGenerics = 1 << 1,
/// Whether an unavailable protocol can be referenced.
AllowUnavailableProtocol = 1 << 2,
/// Whether we should allow references to unavailable types.
AllowUnavailable = 1 << 3,
/// Whether the given type can override the type of a typed pattern.
OverrideType = 1 << 4,
/// Whether we are validating the type for SIL.
// FIXME: Move this flag to TypeResolverContext.
SILType = 1 << 5,
/// Whether we are parsing a SIL file. Not the same as SILType,
/// because the latter is not set if we're parsing an AST type.
SILMode = 1 << 6,
/// Whether this is a resolution based on a non-inferred type pattern.
FromNonInferredPattern = 1 << 7,
/// Whether this type resolution is guaranteed not to affect downstream files.
KnownNonCascadingDependency = 1 << 8,
/// Whether we are at the direct base of a type expression.
Direct = 1 << 9,
/// Whether we should not produce diagnostics if the type is invalid.
SilenceErrors = 1 << 10,
};
/// Type resolution contexts that require special handling.
enum class TypeResolverContext : uint8_t {
/// No special type handling is required.
None,
/// Whether we are checking the parameter list of a function.
AbstractFunctionDecl,
/// Whether we are checking the parameter list of a subscript.
SubscriptDecl,
/// Whether we are checking the parameter list of a closure.
ClosureExpr,
/// 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.
/// See also: TypeResolutionFlags::Direct
FunctionInput,
/// Whether this is a variadic function input.
VariadicFunctionInput,
/// Whether we are in the result type of a function, including multi-level
/// tuple return values. See also: TypeResolutionFlags::Direct
FunctionResult,
/// Whether we are in the result type of a function body that is
/// known to produce dynamic Self.
DynamicSelfResult,
/// Whether we are in a protocol's where clause
ProtocolWhereClause,
/// Whether this is a pattern binding entry.
PatternBindingDecl,
/// Whether we are the variable type in a for/in statement.
ForEachStmt,
/// Whether we are binding an extension declaration, which limits
/// the lookup.
ExtensionBinding,
/// Whether this type is being used in an expression or local declaration.
///
/// This affects what sort of dependencies are recorded when resolving the
/// type.
InExpression,
/// Whether this type is being used in a cast or coercion expression.
ExplicitCastExpr,
/// Whether this type is the value carried in an enum case.
EnumElementDecl,
/// Whether this is the payload subpattern of an enum pattern.
EnumPatternPayload,
/// Whether we are checking the underlying type of a typealias.
TypeAliasDecl,
/// Whether we are in a requirement of a generic declaration
GenericRequirement,
/// Whether we are in a type argument for an optional
ImmediateOptionalTypeArgument,
/// Whether this is the type of an editor placeholder.
EditorPlaceholderExpr,
};
/// Options that determine how type resolution should work.
class TypeResolutionOptions {
using Context = TypeResolverContext;
// The "base" type resolution context. This never changes.
Context base = Context::None;
// The current type resolution context.
Context context = Context::None;
// TypeResolutionFlags
uint16_t flags = 0;
static_assert(sizeof(TypeResolutionOptions::flags) ==
sizeof(TypeResolutionFlags),
"Flags size error");
public:
~TypeResolutionOptions() = default;
TypeResolutionOptions(const TypeResolutionOptions &) = default;
TypeResolutionOptions(TypeResolutionOptions &&) = default;
TypeResolutionOptions &operator =(const TypeResolutionOptions &) = default;
TypeResolutionOptions &operator =(TypeResolutionOptions &&) = default;
// NOTE: Use either setContext() or explicit construction and assignment.
void operator =(const Context &) = delete;
void operator =(Context &&) = delete;
// NOTE: "None" might be more permissive than one wants, therefore no
// reasonable default context is possible.
TypeResolutionOptions() = delete;
TypeResolutionOptions(Context context) : base(context), context(context),
flags(unsigned(TypeResolutionFlags::Direct)) {}
// Helper forwarding constructors:
TypeResolutionOptions(llvm::NoneType) : TypeResolutionOptions(Context::None){}
/// Test the current type resolution base context.
bool hasBase(Context context) const { return base == context; }
/// Get the base type resolution context.
Context getBaseContext() const { return base; }
/// Test the current type resolution context.
bool is(Context context) const { return this->context == context; }
/// Get the current type resolution context.
Context getContext() const { return context; }
/// Set the current type resolution context.
void setContext(Context newContext) {
context = newContext;
flags &= ~unsigned(TypeResolutionFlags::Direct);
}
void setContext(llvm::NoneType) { setContext(Context::None); }
/// Get the current flags.
TypeResolutionFlags getFlags() const { return TypeResolutionFlags(flags); }
/// Is this type resolution context an expression.
bool isAnyExpr() const {
switch (base) {
case Context::InExpression:
case Context::ExplicitCastExpr:
case Context::ForEachStmt:
case Context::PatternBindingDecl:
case Context::EditorPlaceholderExpr:
case Context::ClosureExpr:
return true;
case Context::None:
case Context::FunctionInput:
case Context::VariadicFunctionInput:
case Context::FunctionResult:
case Context::DynamicSelfResult:
case Context::ProtocolWhereClause:
case Context::ExtensionBinding:
case Context::SubscriptDecl:
case Context::EnumElementDecl:
case Context::EnumPatternPayload:
case Context::TypeAliasDecl:
case Context::GenericRequirement:
case Context::ImmediateOptionalTypeArgument:
case Context::AbstractFunctionDecl:
return false;
}
llvm_unreachable("unhandled kind");
}
/// Determine whether all of the given options are set.
bool contains(TypeResolutionFlags set) const {
return !static_cast<bool>(unsigned(set) & ~unsigned(flags));
}
/// Produce type resolution options with additional flags.
friend TypeResolutionOptions operator|(TypeResolutionOptions lhs,
TypeResolutionFlags rhs) {
return lhs |= rhs;
}
/// Merge additional flags into type resolution options.
friend TypeResolutionOptions &operator|=(TypeResolutionOptions &lhs,
TypeResolutionFlags rhs) {
lhs.flags |= unsigned(rhs);
return lhs;
}
/// Test whether any given flag is set in the type resolution options.
friend bool operator&(TypeResolutionOptions lhs, TypeResolutionFlags rhs) {
return lhs.flags & unsigned(rhs);
}
/// Produce type resolution options with removed flags.
friend TypeResolutionOptions operator-(TypeResolutionOptions lhs,
TypeResolutionFlags rhs) {
return lhs -= rhs;
}
/// Remove the flags from the type resolution options.
friend TypeResolutionOptions &operator-=(TypeResolutionOptions &lhs,
TypeResolutionFlags rhs) {
lhs.flags &= ~unsigned(rhs);
return lhs;
}
/// Strip the contextual options from the given type resolution options.
inline TypeResolutionOptions withoutContext(bool preserveSIL = false) const {
auto copy = *this;
copy.setContext(None);
// FIXME: Move SILType to TypeResolverContext.
if (!preserveSIL) copy -= TypeResolutionFlags::SILType;
return copy;
}
};
/// Handles the resolution of types within a given declaration context,
/// which might involve resolving generic parameters to a particular
/// stage.
class TypeResolution {
DeclContext *dc;
TypeResolutionStage stage;
union {
/// The generic environment used to map to archetypes.
GenericEnvironment *genericEnv;
/// The generic signature
struct {
/// The generic signature to use for type resolution.
GenericSignature *genericSig;
/// The generic signature builder that will answer queries about
/// generic types.
mutable GenericSignatureBuilder *builder;
} complete;
};
TypeResolution(DeclContext *dc, TypeResolutionStage stage)
: dc(dc), stage(stage) { }
GenericSignatureBuilder *getGenericSignatureBuilder() const;
public:
/// Form a type resolution for the structure of a type, which does not
/// attempt to resolve member types of type parameters to a particular
/// associated type.
static TypeResolution forStructural(DeclContext *dc);
/// Form a type resolution for an interface type, which is a complete
/// description of the type using generic parameters.
static TypeResolution forInterface(DeclContext *dc);
/// Form a type resolution for an interface type, which is a complete
/// description of the type using generic parameters.
static TypeResolution forInterface(DeclContext *dc,
GenericSignature *genericSig);
/// Form a type resolution for a contextual type, which is a complete
/// description of the type using the archetypes of the given declaration
/// context.
static TypeResolution forContextual(DeclContext *dc);
/// Form a type resolution for a contextual type, which is a complete
/// description of the type using the archetypes of the given generic
/// environment.
static TypeResolution forContextual(DeclContext *dc,
GenericEnvironment *genericEnv);
/// Retrieve the ASTContext in which this resolution occurs.
ASTContext &getASTContext() const { return dc->getASTContext(); }
/// Retrieve the declaration context in which type resolution will be
/// performed.
DeclContext *getDeclContext() const { return dc; }
/// Retrieve the type resolution stage.
TypeResolutionStage getStage() const { return stage; }
/// Retrieves the generic signature for the context, or NULL if there is
/// no generic signature to resolve types.
GenericSignature *getGenericSignature() const;
/// \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 options Options that alter type resolution.
///
/// \returns a well-formed type or an ErrorType in case of an error.
Type resolveType(TypeRepr *TyR, TypeResolutionOptions options);
/// Whether this type resolution uses archetypes (vs. generic parameters).
bool usesArchetypes() const;
/// Map the given type (that involves generic parameters)
Type mapTypeIntoContext(Type type) const;
/// Resolve a reference to a member type of the given (dependent) base and
/// name.
Type resolveDependentMemberType(Type baseTy, DeclContext *DC,
SourceRange baseRange,
ComponentIdentTypeRepr *ref) const;
/// Resolve an unqualified reference to an associated type or type alias
/// in a protocol.
Type resolveSelfAssociatedType(Type baseTy, DeclContext *DC,
Identifier name) const;
/// Determine whether the given two types are equivalent within this
/// type resolution context.
bool areSameType(Type type1, Type type2) const;
};
} // end namespace swift
#endif /* SWIFT_SEMA_TYPE_CHECK_TYPE_H */