blob: 24253def0d94faafaf1b53233a4de0f0258c811c [file] [log] [blame]
//===--- TypeRepr.cpp - Swift Language Type Representation ----------------===//
//
// 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 implements the TypeRepr and related classes.
//
//===----------------------------------------------------------------------===//
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/TypeRepr.h"
#include "swift/AST/ASTContext.h"
#include "swift/AST/ASTVisitor.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericParamList.h"
#include "swift/AST/Module.h"
#include "swift/AST/Types.h"
#include "swift/Basic/Defer.h"
#include "swift/Basic/Statistic.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/raw_ostream.h"
using namespace swift;
#define TYPEREPR(Id, _) \
static_assert(IsTriviallyDestructible<Id##TypeRepr>::value, \
"TypeReprs are BumpPtrAllocated; the d'tor is never called");
#include "swift/AST/TypeReprNodes.def"
SourceLoc TypeRepr::getLoc() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: \
return static_cast<const CLASS##TypeRepr*>(this)->getLocImpl();
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
SourceLoc TypeRepr::getStartLoc() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: \
return static_cast<const CLASS##TypeRepr*>(this)->getStartLocImpl();
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
SourceLoc TypeRepr::getEndLoc() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: \
return static_cast<const CLASS##TypeRepr*>(this)->getEndLocImpl();
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
SourceRange TypeRepr::getSourceRange() const {
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: { \
auto Ty = static_cast<const CLASS##TypeRepr*>(this); \
return SourceRange(Ty->getStartLocImpl(), Ty->getEndLocImpl()); \
}
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
/// Standard allocator for TypeReprs.
void *TypeRepr::operator new(size_t Bytes, const ASTContext &C,
unsigned Alignment) {
return C.Allocate(Bytes, Alignment);
}
DeclNameRef ComponentIdentTypeRepr::getNameRef() const {
if (IdOrDecl.is<DeclNameRef>())
return IdOrDecl.get<DeclNameRef>();
return IdOrDecl.get<TypeDecl *>()->createNameRef();
}
static void printTypeRepr(const TypeRepr *TyR, ASTPrinter &Printer,
const PrintOptions &Opts) {
if (TyR == nullptr)
Printer << "<null>";
else
TyR->print(Printer, Opts);
}
void TypeRepr::print(raw_ostream &OS, const PrintOptions &Opts) const {
StreamPrinter Printer(OS);
print(Printer, Opts);
}
void TypeRepr::print(ASTPrinter &Printer, const PrintOptions &Opts) const {
Printer.printTypePre(TypeLoc(const_cast<TypeRepr *>(this)));
SWIFT_DEFER {
Printer.printTypePost(TypeLoc(const_cast<TypeRepr *>(this)));
};
switch (getKind()) {
#define TYPEREPR(CLASS, PARENT) \
case TypeReprKind::CLASS: { \
auto Ty = static_cast<const CLASS##TypeRepr*>(this); \
return Ty->printImpl(Printer, Opts); \
}
#include "swift/AST/TypeReprNodes.def"
}
llvm_unreachable("unknown kind!");
}
void ErrorTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer << "<<error type>>";
}
void AttributedTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printAttrs(Printer, Opts);
printTypeRepr(Ty, Printer, Opts);
}
void AttributedTypeRepr::printAttrs(llvm::raw_ostream &OS) const {
StreamPrinter Printer(OS);
printAttrs(Printer, PrintOptions());
}
void AttributedTypeRepr::printAttrs(ASTPrinter &Printer,
const PrintOptions &Options) const {
const TypeAttributes &Attrs = getAttrs();
auto hasAttr = [&](TypeAttrKind K) -> bool {
if (Options.excludeAttrKind(K))
return false;
return Attrs.has(K);
};
if (hasAttr(TAK_autoclosure))
Printer.printSimpleAttr("@autoclosure") << " ";
if (hasAttr(TAK_escaping))
Printer.printSimpleAttr("@escaping") << " ";
if (hasAttr(TAK_noDerivative))
Printer.printSimpleAttr("@noDerivative") << " ";
if (hasAttr(TAK_differentiable)) {
if (Attrs.isLinear()) {
Printer.printSimpleAttr("@differentiable(linear)") << " ";
} else {
Printer.printSimpleAttr("@differentiable") << " ";
}
}
if (hasAttr(TAK_thin))
Printer.printSimpleAttr("@thin") << " ";
if (hasAttr(TAK_thick))
Printer.printSimpleAttr("@thick") << " ";
if (hasAttr(TAK_convention) && Attrs.hasConvention()) {
Printer.callPrintStructurePre(PrintStructureKind::BuiltinAttribute);
Printer.printAttrName("@convention");
SmallString<32> convention;
Attrs.getConventionArguments(convention);
Printer << "(" << convention << ")";
Printer.printStructurePost(PrintStructureKind::BuiltinAttribute);
Printer << " ";
}
if (hasAttr(TAK_async))
Printer.printSimpleAttr("@async") << " ";
}
IdentTypeRepr *IdentTypeRepr::create(ASTContext &C,
ArrayRef<ComponentIdentTypeRepr *> Components) {
assert(!Components.empty());
if (Components.size() == 1)
return Components.front();
return CompoundIdentTypeRepr::create(C, Components);
}
static void printGenericArgs(ASTPrinter &Printer, const PrintOptions &Opts,
ArrayRef<TypeRepr *> Args) {
if (Args.empty())
return;
Printer << "<";
interleave(Args, [&](TypeRepr *Arg) { printTypeRepr(Arg, Printer, Opts); },
[&] { Printer << ", "; });
Printer << ">";
}
void ComponentIdentTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
if (auto *TD = dyn_cast_or_null<TypeDecl>(getBoundDecl())) {
if (auto MD = dyn_cast<ModuleDecl>(TD))
Printer.printModuleRef(MD, getNameRef().getBaseIdentifier());
else
Printer.printTypeRef(Type(), TD, getNameRef().getBaseIdentifier());
} else {
Printer.printName(getNameRef().getBaseIdentifier());
}
if (auto GenIdT = dyn_cast<GenericIdentTypeRepr>(this))
printGenericArgs(Printer, Opts, GenIdT->getGenericArgs());
}
void CompoundIdentTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(getComponents().front(), Printer, Opts);
for (auto C : getComponents().slice(1)) {
Printer << ".";
printTypeRepr(C, Printer, Opts);
}
}
void FunctionTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer.callPrintStructurePre(PrintStructureKind::FunctionType);
printTypeRepr(ArgsTy, Printer, Opts);
if (isThrowing()) {
Printer << " ";
Printer.printKeyword("throws", Opts);
}
Printer << " -> ";
Printer.callPrintStructurePre(PrintStructureKind::FunctionReturnType);
printTypeRepr(RetTy, Printer, Opts);
Printer.printStructurePost(PrintStructureKind::FunctionReturnType);
Printer.printStructurePost(PrintStructureKind::FunctionType);
}
void ArrayTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer << "[";
printTypeRepr(getBase(), Printer, Opts);
Printer << "]";
}
void DictionaryTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer << "[";
printTypeRepr(Key, Printer, Opts);
Printer << " : ";
printTypeRepr(Value, Printer, Opts);
Printer << "]";
}
void OptionalTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << "?";
}
void ImplicitlyUnwrappedOptionalTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << "!";
}
TupleTypeRepr::TupleTypeRepr(ArrayRef<TupleTypeReprElement> Elements,
SourceRange Parens,
SourceLoc Ellipsis, unsigned EllipsisIdx)
: TypeRepr(TypeReprKind::Tuple), Parens(Parens) {
Bits.TupleTypeRepr.HasEllipsis = Ellipsis.isValid();
Bits.TupleTypeRepr.NumElements = Elements.size();
// Copy elements.
std::uninitialized_copy(Elements.begin(), Elements.end(),
getTrailingObjects<TupleTypeReprElement>());
// Set ellipsis location and index.
if (Ellipsis.isValid()) {
getTrailingObjects<SourceLocAndIdx>()[0] = {EllipsisIdx, Ellipsis};
}
}
TupleTypeRepr *TupleTypeRepr::create(const ASTContext &C,
ArrayRef<TupleTypeReprElement> Elements,
SourceRange Parens,
SourceLoc Ellipsis, unsigned EllipsisIdx) {
assert(Ellipsis.isValid() ? EllipsisIdx < Elements.size()
: EllipsisIdx == Elements.size());
size_t size =
totalSizeToAlloc<TupleTypeReprElement, SourceLocAndIdx>(
Elements.size(), Ellipsis.isValid() ? 1 : 0);
void *mem = C.Allocate(size, alignof(TupleTypeRepr));
return new (mem) TupleTypeRepr(Elements, Parens,
Ellipsis, EllipsisIdx);
}
TupleTypeRepr *TupleTypeRepr::createEmpty(const ASTContext &C,
SourceRange Parens) {
return create(C, {}, Parens,
/*Ellipsis=*/SourceLoc(), /*EllipsisIdx=*/0);
}
GenericIdentTypeRepr *GenericIdentTypeRepr::create(const ASTContext &C,
DeclNameLoc Loc,
DeclNameRef Id,
ArrayRef<TypeRepr*> GenericArgs,
SourceRange AngleBrackets) {
auto size = totalSizeToAlloc<TypeRepr*>(GenericArgs.size());
auto mem = C.Allocate(size, alignof(GenericIdentTypeRepr));
return new (mem) GenericIdentTypeRepr(Loc, Id, GenericArgs, AngleBrackets);
}
CompoundIdentTypeRepr *CompoundIdentTypeRepr::create(const ASTContext &C,
ArrayRef<ComponentIdentTypeRepr*> Components) {
auto size = totalSizeToAlloc<ComponentIdentTypeRepr*>(Components.size());
auto mem = C.Allocate(size, alignof(CompoundIdentTypeRepr));
return new (mem) CompoundIdentTypeRepr(Components);
}
SILBoxTypeRepr *SILBoxTypeRepr::create(ASTContext &C,
GenericParamList *GenericParams,
SourceLoc LBraceLoc, ArrayRef<Field> Fields,
SourceLoc RBraceLoc,
SourceLoc ArgLAngleLoc, ArrayRef<TypeRepr *> GenericArgs,
SourceLoc ArgRAngleLoc) {
auto size = totalSizeToAlloc<Field, TypeRepr*>(Fields.size(),
GenericArgs.size());
auto mem = C.Allocate(size, alignof(SILBoxTypeRepr));
return new (mem) SILBoxTypeRepr(GenericParams, LBraceLoc, Fields, RBraceLoc,
ArgLAngleLoc, GenericArgs, ArgRAngleLoc);
}
SourceLoc FunctionTypeRepr::getStartLocImpl() const {
return ArgsTy->getStartLoc();
}
SourceLoc SILBoxTypeRepr::getStartLocImpl() const {
if (GenericParams && GenericParams->getSourceRange().isValid())
return GenericParams->getSourceRange().Start;
return LBraceLoc;
}
SourceLoc SILBoxTypeRepr::getEndLocImpl() const {
if (ArgRAngleLoc.isValid())
return ArgRAngleLoc;
return RBraceLoc;
}
SourceLoc SILBoxTypeRepr::getLocImpl() const {
return LBraceLoc;
}
void TupleTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer.callPrintStructurePre(PrintStructureKind::TupleType);
SWIFT_DEFER { Printer.printStructurePost(PrintStructureKind::TupleType); };
Printer << "(";
for (unsigned i = 0, e = Bits.TupleTypeRepr.NumElements; i != e; ++i) {
if (i) Printer << ", ";
Printer.callPrintStructurePre(PrintStructureKind::TupleElement);
auto name = getElementName(i);
if (isNamedParameter(i)) {
// Printing empty Identifier is same as printing '_'.
Printer.printName(Identifier(),
PrintNameContext::FunctionParameterExternal);
if (!name.empty()) {
Printer << " ";
Printer.printName(name, PrintNameContext::FunctionParameterLocal);
}
Printer << ": ";
} else {
if (!name.empty()) {
Printer.printName(name, PrintNameContext::TupleElement);
Printer << ": ";
}
}
printTypeRepr(getElementType(i), Printer, Opts);
Printer.printStructurePost(PrintStructureKind::TupleElement);
if (hasEllipsis() && getEllipsisIndex() == i)
Printer << "...";
}
Printer << ")";
}
CompositionTypeRepr *CompositionTypeRepr::create(const ASTContext &C,
ArrayRef<TypeRepr *> Types,
SourceLoc FirstTypeLoc,
SourceRange CompositionRange) {
auto size = totalSizeToAlloc<TypeRepr*>(Types.size());
auto mem = C.Allocate(size, alignof(CompositionTypeRepr));
return new (mem) CompositionTypeRepr(Types, FirstTypeLoc, CompositionRange);
}
void CompositionTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
if (getTypes().empty()) {
Printer.printKeyword("Any", Opts);
} else {
interleave(getTypes(), [&](TypeRepr *T) { printTypeRepr(T, Printer, Opts);},
[&] { Printer << " & "; });
}
}
void MetatypeTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << ".Type";
}
void ProtocolTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
printTypeRepr(Base, Printer, Opts);
Printer << ".Protocol";
}
void OpaqueReturnTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
Printer.printKeyword("some", Opts, /*Suffix=*/" ");
printTypeRepr(Constraint, Printer, Opts);
}
void SpecifierTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
switch (getKind()) {
case TypeReprKind::InOut:
Printer.printKeyword("inout", Opts, " ");
break;
case TypeReprKind::Shared:
Printer.printKeyword("__shared", Opts, " ");
break;
case TypeReprKind::Owned:
Printer.printKeyword("__owned", Opts, " ");
break;
default:
llvm_unreachable("unknown specifier type repr");
break;
}
printTypeRepr(Base, Printer, Opts);
}
void FixedTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
getType().print(Printer, Opts);
}
void SILBoxTypeRepr::printImpl(ASTPrinter &Printer,
const PrintOptions &Opts) const {
// TODO
Printer.printKeyword("sil_box", Opts);
}
// See swift/Basic/Statistic.h for declaration: this enables tracing
// TypeReprs, is defined here to avoid too much layering violation / circular
// linkage dependency.
struct TypeReprTraceFormatter : public UnifiedStatsReporter::TraceFormatter {
void traceName(const void *Entity, raw_ostream &OS) const override {
if (!Entity)
return;
const TypeRepr *TR = static_cast<const TypeRepr *>(Entity);
TR->print(OS);
}
void traceLoc(const void *Entity, SourceManager *SM,
clang::SourceManager *CSM, raw_ostream &OS) const override {
if (!Entity)
return;
const TypeRepr *TR = static_cast<const TypeRepr *>(Entity);
TR->getSourceRange().print(OS, *SM, false);
}
};
static TypeReprTraceFormatter TF;
template<>
const UnifiedStatsReporter::TraceFormatter*
FrontendStatsTracer::getTraceFormatter<const TypeRepr *>() {
return &TF;
}