blob: 3b08c7a46af07ceb2c8fe04996a37e4dcaf5a622 [file] [log] [blame]
//===--- CodeSynthesis.h - Typechecker code synthesis -----------*- 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 a typechecker-internal interface to a bunch of
// routines for synthesizing various declarations.
//
//===----------------------------------------------------------------------===//
#ifndef SWIFT_TYPECHECKING_CODESYNTHESIS_H
#define SWIFT_TYPECHECKING_CODESYNTHESIS_H
#include "TypeCheckObjC.h"
#include "swift/AST/ForeignErrorConvention.h"
#include "swift/Basic/ExternalUnion.h"
#include "swift/Basic/LLVM.h"
#include "llvm/ADT/Optional.h"
namespace swift {
class AbstractFunctionDecl;
class AbstractStorageDecl;
class ASTContext;
class ClassDecl;
class ConstructorDecl;
class FuncDecl;
class GenericParamList;
class NominalTypeDecl;
class Type;
class ValueDecl;
class VarDecl;
class TypeChecker;
class ObjCReason;
/// A function which needs to have its body synthesized.
///
/// This class exists in expectation that someone will need to add more
/// information to it.
class SynthesizedFunction {
public:
enum Kind {
Getter,
Setter,
ReadCoroutine,
ModifyCoroutine,
LazyGetter,
LazySetter,
};
private:
FuncDecl *Fn;
Kind K;
using Members = ExternalUnionMembers<void, VarDecl*>;
static Members::Index getIndexForKind(Kind kind) {
switch (kind) {
case Kind::Getter:
case Kind::Setter:
case Kind::ReadCoroutine:
case Kind::ModifyCoroutine:
return Members::indexOf<void>();
case Kind::LazyGetter:
case Kind::LazySetter:
return Members::indexOf<VarDecl*>();
}
llvm_unreachable("bad kind");
};
ExternalUnion<Kind, Members, getIndexForKind> Extra;
static_assert(decltype(Extra)::union_is_trivially_copyable,
"expected all members to be trivial");
public:
SynthesizedFunction(FuncDecl *fn, Kind kind) : Fn(fn), K(kind) {
assert(getIndexForKind(kind) == Members::indexOf<void>() &&
"this storage kind requires extra data");
}
SynthesizedFunction(FuncDecl *fn, Kind kind, VarDecl *var) : Fn(fn), K(kind) {
Extra.emplace<VarDecl*>(K, var);
}
FuncDecl *getDecl() const { return Fn; }
Kind getKind() const { return K; }
VarDecl *getLazyTargetVariable() const { return Extra.get<VarDecl*>(K); }
};
// These are implemented in TypeCheckDecl.cpp.
void makeFinal(ASTContext &ctx, ValueDecl *D);
// Implemented in TypeCheckerOverride.cpp
bool checkOverrides(ValueDecl *decl);
// These are implemented in CodeSynthesis.cpp.
void maybeAddAccessorsToStorage(TypeChecker &TC, AbstractStorageDecl *storage);
void triggerAccessorSynthesis(TypeChecker &TC, AbstractStorageDecl *storage);
/// \brief Describes the kind of implicit constructor that will be
/// generated.
enum class ImplicitConstructorKind {
/// \brief The default constructor, which default-initializes each
/// of the instance variables.
Default,
/// \brief The memberwise constructor, which initializes each of
/// the instance variables from a parameter of the same type and
/// name.
Memberwise
};
/// \brief Create an implicit struct or class constructor.
///
/// \param decl The struct or class for which a constructor will be created.
/// \param ICK The kind of implicit constructor to create.
///
/// \returns The newly-created constructor, which has already been type-checked
/// (but has not been added to the containing struct or class).
ConstructorDecl *createImplicitConstructor(TypeChecker &tc,
NominalTypeDecl *decl,
ImplicitConstructorKind ICK);
/// The kind of designated initializer to synthesize.
enum class DesignatedInitKind {
/// A stub initializer, which is not visible to name lookup and
/// merely aborts at runtime.
Stub,
/// An initializer that simply chains to the corresponding
/// superclass initializer.
Chaining
};
/// Create a new initializer that overrides the given designated
/// initializer.
///
/// \param classDecl The subclass in which the new initializer will
/// be declared.
///
/// \param superclassCtor The superclass initializer for which this
/// routine will create an override.
///
/// \param kind The kind of initializer to synthesize.
///
/// \returns the newly-created initializer that overrides \p
/// superclassCtor.
ConstructorDecl *createDesignatedInitOverride(TypeChecker &TC,
ClassDecl *classDecl,
ConstructorDecl *superclassCtor,
DesignatedInitKind kind);
} // end namespace swift
#endif