blob: 1e8689cc58f3be07454e4f92a24290b4434d6d9f [file] [log] [blame]
//===--- CodeSynthesis.cpp - Type Checking for Declarations ---------------===//
//
// 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 semantic analysis for declarations.
//
//===----------------------------------------------------------------------===//
#include "CodeSynthesis.h"
#include "ConstraintSystem.h"
#include "TypeChecker.h"
#include "TypeCheckDecl.h"
#include "TypeCheckObjC.h"
#include "TypeCheckType.h"
#include "swift/AST/ASTPrinter.h"
#include "swift/AST/Availability.h"
#include "swift/AST/Expr.h"
#include "swift/AST/GenericEnvironment.h"
#include "swift/AST/Initializer.h"
#include "swift/AST/ParameterList.h"
#include "swift/AST/PrettyStackTrace.h"
#include "swift/AST/ProtocolConformance.h"
#include "swift/AST/SourceFile.h"
#include "swift/AST/TypeCheckRequests.h"
#include "swift/Basic/Defer.h"
#include "swift/ClangImporter/ClangModule.h"
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringExtras.h"
using namespace swift;
const bool IsImplicit = true;
Expr *swift::buildSelfReference(VarDecl *selfDecl,
SelfAccessorKind selfAccessorKind,
bool isLValue,
ASTContext &ctx) {
switch (selfAccessorKind) {
case SelfAccessorKind::Peer:
return new (ctx) DeclRefExpr(selfDecl, DeclNameLoc(), IsImplicit,
AccessSemantics::Ordinary,
isLValue
? LValueType::get(selfDecl->getType())
: selfDecl->getType());
case SelfAccessorKind::Super:
assert(!isLValue);
return new (ctx) SuperRefExpr(selfDecl, SourceLoc(), IsImplicit,
selfDecl->getType()->getSuperclass());
}
llvm_unreachable("bad self access kind");
}
/// Build an expression that evaluates the specified parameter list as a tuple
/// or paren expr, suitable for use in an apply expr.
Expr *swift::buildArgumentForwardingExpr(ArrayRef<ParamDecl*> params,
ASTContext &ctx) {
SmallVector<Identifier, 4> labels;
SmallVector<SourceLoc, 4> labelLocs;
SmallVector<Expr *, 4> args;
SmallVector<AnyFunctionType::Param, 4> elts;
for (auto param : params) {
auto type = param->getType();
elts.push_back(param->toFunctionParam(type));
Expr *ref = new (ctx) DeclRefExpr(param, DeclNameLoc(), /*implicit*/ true);
ref->setType(param->isInOut() ? LValueType::get(type) : type);
if (param->isInOut()) {
ref = new (ctx) InOutExpr(SourceLoc(), ref, type, /*isImplicit=*/true);
} else if (param->isVariadic()) {
ref = new (ctx) VarargExpansionExpr(ref, /*implicit*/ true);
ref->setType(type);
}
args.push_back(ref);
labels.push_back(param->getArgumentName());
labelLocs.push_back(SourceLoc());
}
Expr *argExpr;
if (args.size() == 1 &&
labels[0].empty() &&
!isa<VarargExpansionExpr>(args[0])) {
argExpr = new (ctx) ParenExpr(SourceLoc(), args[0], SourceLoc(),
/*hasTrailingClosure=*/false);
argExpr->setImplicit();
} else {
argExpr = TupleExpr::create(ctx, SourceLoc(), args, labels, labelLocs,
SourceLoc(), false, IsImplicit);
}
auto argTy = AnyFunctionType::composeInput(ctx, elts, /*canonical*/false);
argExpr->setType(argTy);
return argExpr;
}
static void maybeAddMemberwiseDefaultArg(ParamDecl *arg, VarDecl *var,
SmallVectorImpl<DefaultArgumentInitializer *> &defaultInits,
unsigned paramSize, ASTContext &ctx) {
// First and foremost, if this is a constant don't bother.
if (var->isLet())
return;
// We can only provide default values for patterns binding a single variable.
// i.e. var (a, b) = getSomeTuple() is not allowed.
if (!var->getParentPattern()->getSingleVar())
return;
// Whether we have explicit initialization.
bool isExplicitlyInitialized = false;
if (auto pbd = var->getParentPatternBinding()) {
auto &entry = pbd->getPatternEntryForVarDecl(var);
isExplicitlyInitialized =
entry.isInitialized() && entry.getEqualLoc().isValid();
}
// Whether we can default-initialize this property.
auto binding = var->getParentPatternBinding();
bool isDefaultInitializable =
var->getAttrs().hasAttribute<LazyAttr>() ||
(binding && binding->isDefaultInitializable());
// If this is neither explicitly initialized nor
// default-initializable, don't add anything.
if (!isExplicitlyInitialized && !isDefaultInitializable)
return;
// We can add a default value now.
// Give this some bogus context right now, we'll fix it after making
// the constructor.
auto *initDC = new (ctx) DefaultArgumentInitializer(
arg->getDeclContext(), paramSize);
defaultInits.push_back(initDC);
// If the variable has a type T? and no initial value, return a nil literal
// default arg. All lazy variables return a nil literal as well. *Note* that
// the type will always be a sugared T? because we don't default init an
// explicit Optional<T>.
bool isNilInitialized =
var->getAttrs().hasAttribute<LazyAttr>() ||
(!isExplicitlyInitialized && isDefaultInitializable &&
var->getValueInterfaceType()->getAnyNominal() == ctx.getOptionalDecl() &&
!var->getAttachedPropertyWrapperTypeInfo(0).defaultInit);
if (isNilInitialized) {
arg->setDefaultArgumentKind(DefaultArgumentKind::NilLiteral);
return;
}
// If there's a backing storage property, the memberwise initializer
// will be in terms of that.
VarDecl *backingStorageVar = var->getPropertyWrapperBackingProperty();
// Set the default value to the variable. When we emit this in silgen
// we're going to call the variable's initializer expression.
arg->setStoredProperty(backingStorageVar ? backingStorageVar : var);
arg->setDefaultArgumentKind(DefaultArgumentKind::StoredProperty);
}
/// Describes the kind of implicit constructor that will be
/// generated.
enum class ImplicitConstructorKind {
/// The default constructor, which default-initializes each
/// of the instance variables.
Default,
/// The memberwise constructor, which initializes each of
/// the instance variables from a parameter of the same type and
/// name.
Memberwise
};
/// 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).
static ConstructorDecl *createImplicitConstructor(NominalTypeDecl *decl,
ImplicitConstructorKind ICK,
ASTContext &ctx) {
assert(!decl->hasClangNode());
SourceLoc Loc = decl->getLoc();
auto accessLevel = AccessLevel::Internal;
// Determine the parameter type of the implicit constructor.
SmallVector<ParamDecl*, 8> params;
SmallVector<DefaultArgumentInitializer *, 8> defaultInits;
if (ICK == ImplicitConstructorKind::Memberwise) {
assert(isa<StructDecl>(decl) && "Only struct have memberwise constructor");
for (auto member : decl->getMembers()) {
auto var = dyn_cast<VarDecl>(member);
if (!var)
continue;
if (!var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true))
continue;
accessLevel = std::min(accessLevel, var->getFormalAccess());
auto varInterfaceType = var->getValueInterfaceType();
if (var->getAttrs().hasAttribute<LazyAttr>()) {
// If var is a lazy property, its value is provided for the underlying
// storage. We thus take an optional of the property's type. We only
// need to do this because the implicit initializer is added before all
// the properties are type checked. Perhaps init() synth should be
// moved later.
varInterfaceType = OptionalType::get(varInterfaceType);
} else if (Type backingPropertyType =
var->getPropertyWrapperBackingPropertyType()) {
// For a property that has a wrapper, writing the initializer
// with an '=' implies that the memberwise initializer should also
// accept a value of the original property type. Otherwise, the
// memberwise initializer will be in terms of the backing storage
// type.
if (!var->isPropertyMemberwiseInitializedWithWrappedType()) {
varInterfaceType = backingPropertyType;
}
}
// Create the parameter.
auto *arg = new (ctx)
ParamDecl(ParamDecl::Specifier::Default, SourceLoc(), Loc,
var->getName(), Loc, var->getName(), decl);
arg->setInterfaceType(varInterfaceType);
arg->setImplicit();
maybeAddMemberwiseDefaultArg(arg, var, defaultInits, params.size(), ctx);
params.push_back(arg);
}
}
auto paramList = ParameterList::create(ctx, params);
// Create the constructor.
DeclName name(ctx, DeclBaseName::createConstructor(), paramList);
auto *ctor =
new (ctx) ConstructorDecl(name, Loc,
/*Failable=*/false, /*FailabilityLoc=*/SourceLoc(),
/*Throws=*/false, /*ThrowsLoc=*/SourceLoc(),
paramList, /*GenericParams=*/nullptr, decl);
// Mark implicit.
ctor->setImplicit();
ctor->setAccess(accessLevel);
if (ICK == ImplicitConstructorKind::Memberwise) {
ctor->setIsMemberwiseInitializer();
// Fix default argument init contexts now that we have a constructor.
for (auto initDC : defaultInits) {
initDC->changeFunction(ctor, paramList);
}
}
// If we are defining a default initializer for a class that has a superclass,
// it overrides the default initializer of its superclass. Add an implicit
// 'override' attribute.
if (auto classDecl = dyn_cast<ClassDecl>(decl)) {
if (classDecl->getSuperclass())
ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/true));
}
return ctor;
}
ConstructorDecl *swift::createMemberwiseImplicitConstructor(
TypeChecker &tc, NominalTypeDecl *decl) {
return createImplicitConstructor(decl, ImplicitConstructorKind::Memberwise,
tc.Context);
}
/// Create a stub body that emits a fatal error message.
static std::pair<BraceStmt *, bool>
synthesizeStubBody(AbstractFunctionDecl *fn, void *) {
auto *ctor = cast<ConstructorDecl>(fn);
auto &ctx = ctor->getASTContext();
auto unimplementedInitDecl = ctx.getUnimplementedInitializer();
auto classDecl = ctor->getDeclContext()->getSelfClassDecl();
if (!unimplementedInitDecl) {
ctx.Diags.diagnose(classDecl->getLoc(),
diag::missing_unimplemented_init_runtime);
return { nullptr, true };
}
auto *staticStringDecl = ctx.getStaticStringDecl();
auto staticStringType = staticStringDecl->getDeclaredType();
auto staticStringInit = ctx.getStringBuiltinInitDecl(staticStringDecl);
auto *uintDecl = ctx.getUIntDecl();
auto uintType = uintDecl->getDeclaredType();
auto uintInit = ctx.getIntBuiltinInitDecl(uintDecl);
// Create a call to Swift._unimplementedInitializer
auto loc = classDecl->getLoc();
Expr *ref = new (ctx) DeclRefExpr(unimplementedInitDecl,
DeclNameLoc(loc),
/*Implicit=*/true);
ref->setType(unimplementedInitDecl->getInterfaceType()
->removeArgumentLabels(1));
llvm::SmallString<64> buffer;
StringRef fullClassName = ctx.AllocateCopy(
(classDecl->getModuleContext()->getName().str() +
"." +
classDecl->getName().str()).toStringRef(buffer));
auto *className = new (ctx) StringLiteralExpr(fullClassName, loc,
/*Implicit=*/true);
className->setBuiltinInitializer(staticStringInit);
assert(isa<ConstructorDecl>(className->getBuiltinInitializer().getDecl()));
className->setType(staticStringType);
auto *initName = new (ctx) MagicIdentifierLiteralExpr(
MagicIdentifierLiteralExpr::Function, loc, /*Implicit=*/true);
initName->setType(staticStringType);
initName->setBuiltinInitializer(staticStringInit);
auto *file = new (ctx) MagicIdentifierLiteralExpr(
MagicIdentifierLiteralExpr::File, loc, /*Implicit=*/true);
file->setType(staticStringType);
file->setBuiltinInitializer(staticStringInit);
auto *line = new (ctx) MagicIdentifierLiteralExpr(
MagicIdentifierLiteralExpr::Line, loc, /*Implicit=*/true);
line->setType(uintType);
line->setBuiltinInitializer(uintInit);
auto *column = new (ctx) MagicIdentifierLiteralExpr(
MagicIdentifierLiteralExpr::Column, loc, /*Implicit=*/true);
column->setType(uintType);
column->setBuiltinInitializer(uintInit);
auto *call = CallExpr::createImplicit(
ctx, ref, { className, initName, file, line, column }, {});
call->setType(ctx.getNeverType());
call->setThrows(false);
SmallVector<ASTNode, 2> stmts;
stmts.push_back(call);
stmts.push_back(new (ctx) ReturnStmt(SourceLoc(), /*Result=*/nullptr));
return { BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
/*implicit=*/true),
/*isTypeChecked=*/true };
}
static std::tuple<GenericSignature, GenericParamList *, SubstitutionMap>
configureGenericDesignatedInitOverride(ASTContext &ctx,
ClassDecl *classDecl,
Type superclassTy,
ConstructorDecl *superclassCtor) {
auto *superclassDecl = superclassTy->getAnyNominal();
auto *moduleDecl = classDecl->getParentModule();
auto subMap = superclassTy->getContextSubstitutionMap(
moduleDecl, superclassDecl);
GenericSignature genericSig;
// Inheriting initializers that have their own generic parameters
auto *genericParams = superclassCtor->getGenericParams();
if (genericParams) {
SmallVector<GenericTypeParamDecl *, 4> newParams;
// First, clone the superclass constructor's generic parameter list,
// but change the depth of the generic parameters to be one greater
// than the depth of the subclass.
unsigned depth = 0;
if (auto genericSig = classDecl->getGenericSignature())
depth = genericSig->getGenericParams().back()->getDepth() + 1;
for (auto *param : genericParams->getParams()) {
auto *newParam = new (ctx) GenericTypeParamDecl(classDecl,
param->getName(),
SourceLoc(),
depth,
param->getIndex());
newParams.push_back(newParam);
}
// We don't have to clone the requirements, because they're not
// used for anything.
genericParams = GenericParamList::create(ctx,
SourceLoc(),
newParams,
SourceLoc(),
ArrayRef<RequirementRepr>(),
SourceLoc());
// Build a generic signature for the derived class initializer.
// Add the generic parameters.
SmallVector<GenericTypeParamType *, 1> newParamTypes;
for (auto *newParam : newParams) {
newParamTypes.push_back(
newParam->getDeclaredInterfaceType()->castTo<GenericTypeParamType>());
}
auto superclassSig = superclassCtor->getGenericSignature();
unsigned superclassDepth = 0;
if (auto genericSig = superclassDecl->getGenericSignature())
superclassDepth = genericSig->getGenericParams().back()->getDepth() + 1;
// We're going to be substituting the requirements of the base class
// initializer to form the requirements of the derived class initializer.
auto substFn = [&](SubstitutableType *type) -> Type {
auto *gp = cast<GenericTypeParamType>(type);
if (gp->getDepth() < superclassDepth)
return Type(gp).subst(subMap);
return CanGenericTypeParamType::get(
gp->getDepth() - superclassDepth + depth,
gp->getIndex(),
ctx);
};
auto lookupConformanceFn =
[&](CanType depTy, Type substTy, ProtocolDecl *proto)
-> Optional<ProtocolConformanceRef> {
if (auto conf = subMap.lookupConformance(depTy, proto))
return conf;
return ProtocolConformanceRef(proto);
};
SmallVector<Requirement, 2> requirements;
for (auto reqt : superclassSig->getRequirements())
if (auto substReqt = reqt.subst(substFn, lookupConformanceFn))
requirements.push_back(*substReqt);
// Now form the substitution map that will be used to remap parameter
// types.
subMap = SubstitutionMap::get(superclassSig,
substFn, lookupConformanceFn);
genericSig = evaluateOrDefault(
ctx.evaluator,
AbstractGenericSignatureRequest{
classDecl->getGenericSignature().getPointer(),
std::move(newParamTypes),
std::move(requirements)
},
GenericSignature());
} else {
genericSig = classDecl->getGenericSignature();
}
return std::make_tuple(genericSig, genericParams, subMap);
}
static void
configureInheritedDesignatedInitAttributes(ClassDecl *classDecl,
ConstructorDecl *ctor,
ConstructorDecl *superclassCtor,
ASTContext &ctx) {
assert(ctor->getDeclContext() == classDecl);
AccessLevel access = classDecl->getFormalAccess();
access = std::max(access, AccessLevel::Internal);
access = std::min(access, superclassCtor->getFormalAccess());
ctor->setAccess(access);
AccessScope superclassInliningAccessScope =
superclassCtor->getFormalAccessScope(/*useDC*/nullptr,
/*usableFromInlineAsPublic=*/true);
if (superclassInliningAccessScope.isPublic()) {
if (superclassCtor->getAttrs().hasAttribute<InlinableAttr>()) {
// Inherit the @inlinable attribute.
auto *clonedAttr = new (ctx) InlinableAttr(/*implicit=*/true);
ctor->getAttrs().add(clonedAttr);
} else if (access == AccessLevel::Internal && !superclassCtor->isDynamic()){
// Inherit the @usableFromInline attribute.
auto *clonedAttr = new (ctx) UsableFromInlineAttr(/*implicit=*/true);
ctor->getAttrs().add(clonedAttr);
}
}
// Inherit the @discardableResult attribute.
if (superclassCtor->getAttrs().hasAttribute<DiscardableResultAttr>()) {
auto *clonedAttr = new (ctx) DiscardableResultAttr(/*implicit=*/true);
ctor->getAttrs().add(clonedAttr);
}
// If the superclass has its own availability, make sure the synthesized
// constructor is only as available as its superclass's constructor.
if (superclassCtor->getAttrs().hasAttribute<AvailableAttr>()) {
SmallVector<Decl *, 2> asAvailableAs;
// We don't have to look at enclosing contexts of the superclass constructor,
// because designated initializers must always be defined in the superclass
// body, and we already enforce that a superclass is at least as available as
// a subclass.
asAvailableAs.push_back(superclassCtor);
Decl *parentDecl = classDecl;
while (parentDecl != nullptr) {
asAvailableAs.push_back(parentDecl);
parentDecl = parentDecl->getDeclContext()->getAsDecl();
}
AvailabilityInference::applyInferredAvailableAttrs(
ctor, asAvailableAs, ctx);
}
// Wire up the overrides.
ctor->setOverriddenDecl(superclassCtor);
if (superclassCtor->isRequired())
ctor->getAttrs().add(new (ctx) RequiredAttr(/*IsImplicit=*/false));
else
ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/false));
// If the superclass constructor is @objc but the subclass constructor is
// not representable in Objective-C, add @nonobjc implicitly.
Optional<ForeignErrorConvention> errorConvention;
if (superclassCtor->isObjC() &&
!isRepresentableInObjC(ctor, ObjCReason::MemberOfObjCSubclass,
errorConvention))
ctor->getAttrs().add(new (ctx) NonObjCAttr(/*isImplicit=*/true));
}
static std::pair<BraceStmt *, bool>
synthesizeDesignatedInitOverride(AbstractFunctionDecl *fn, void *context) {
auto *ctor = cast<ConstructorDecl>(fn);
auto &ctx = ctor->getASTContext();
auto *superclassCtor = (ConstructorDecl *) context;
// Reference to super.init.
auto *selfDecl = ctor->getImplicitSelfDecl();
auto *superRef = buildSelfReference(selfDecl, SelfAccessorKind::Super,
/*isLValue=*/false, ctx);
SubstitutionMap subs;
if (auto *genericEnv = fn->getGenericEnvironment())
subs = genericEnv->getForwardingSubstitutionMap();
subs = SubstitutionMap::getOverrideSubstitutions(superclassCtor, fn, subs);
ConcreteDeclRef ctorRef(superclassCtor, subs);
auto type = superclassCtor->getInitializerInterfaceType().subst(subs);
auto *ctorRefExpr =
new (ctx) OtherConstructorDeclRefExpr(ctorRef, DeclNameLoc(),
IsImplicit, type);
if (auto *funcTy = type->getAs<FunctionType>())
type = funcTy->getResult();
auto *superclassCtorRefExpr =
new (ctx) DotSyntaxCallExpr(ctorRefExpr, SourceLoc(), superRef, type);
superclassCtorRefExpr->setIsSuper(true);
superclassCtorRefExpr->setThrows(false);
auto *bodyParams = ctor->getParameters();
auto ctorArgs = buildArgumentForwardingExpr(bodyParams->getArray(), ctx);
auto *superclassCallExpr =
CallExpr::create(ctx, superclassCtorRefExpr, ctorArgs,
superclassCtor->getFullName().getArgumentNames(), { },
/*hasTrailingClosure=*/false, /*implicit=*/true);
if (auto *funcTy = type->getAs<FunctionType>())
type = funcTy->getResult();
superclassCallExpr->setType(type);
superclassCallExpr->setThrows(superclassCtor->hasThrows());
Expr *expr = superclassCallExpr;
if (superclassCtor->hasThrows()) {
expr = new (ctx) TryExpr(SourceLoc(), expr, type, /*implicit=*/true);
}
auto *rebindSelfExpr =
new (ctx) RebindSelfInConstructorExpr(expr, selfDecl);
SmallVector<ASTNode, 2> stmts;
stmts.push_back(rebindSelfExpr);
stmts.push_back(new (ctx) ReturnStmt(SourceLoc(), /*Result=*/nullptr));
return { BraceStmt::create(ctx, SourceLoc(), stmts, SourceLoc(),
/*implicit=*/true),
/*isTypeChecked=*/true };
}
/// 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.
static ConstructorDecl *
createDesignatedInitOverride(ClassDecl *classDecl,
ConstructorDecl *superclassCtor,
DesignatedInitKind kind,
ASTContext &ctx) {
// Lookup will sometimes give us initializers that are from the ancestors of
// our immediate superclass. So, from the superclass constructor, we look
// one level up to the enclosing type context which will either be a class
// or an extension. We can use the type declared in that context to check
// if it's our immediate superclass and give up if we didn't.
//
// FIXME: Remove this when lookup of initializers becomes restricted to our
// immediate superclass.
auto *superclassCtorDecl =
superclassCtor->getDeclContext()->getSelfNominalTypeDecl();
Type superclassTy = classDecl->getSuperclass();
NominalTypeDecl *superclassDecl = superclassTy->getAnyNominal();
if (superclassCtorDecl != superclassDecl) {
return nullptr;
}
GenericSignature genericSig;
GenericParamList *genericParams;
SubstitutionMap subMap;
std::tie(genericSig, genericParams, subMap) =
configureGenericDesignatedInitOverride(ctx,
classDecl,
superclassTy,
superclassCtor);
// Determine the initializer parameters.
// Create the initializer parameter patterns.
OptionSet<ParameterList::CloneFlags> options
= (ParameterList::Implicit |
ParameterList::Inherited |
ParameterList::WithoutTypes);
auto *superclassParams = superclassCtor->getParameters();
auto *bodyParams = superclassParams->clone(ctx, options);
// If the superclass is generic, we need to map the superclass constructor's
// parameter types into the generic context of our class.
//
// We might have to apply substitutions, if for example we have a declaration
// like 'class A : B<Int>'.
for (unsigned idx : range(superclassParams->size())) {
auto *superclassParam = superclassParams->get(idx);
auto *bodyParam = bodyParams->get(idx);
auto paramTy = superclassParam->getInterfaceType();
auto substTy = paramTy.subst(subMap);
bodyParam->setInterfaceType(substTy);
bodyParam->getTypeLoc() = TypeLoc::withoutLoc(substTy);
}
// Create the initializer declaration, inheriting the name,
// failability, and throws from the superclass initializer.
auto ctor =
new (ctx) ConstructorDecl(superclassCtor->getFullName(),
classDecl->getBraces().Start,
superclassCtor->isFailable(),
/*FailabilityLoc=*/SourceLoc(),
/*Throws=*/superclassCtor->hasThrows(),
/*ThrowsLoc=*/SourceLoc(),
bodyParams, genericParams, classDecl);
ctor->setImplicit();
// Set the interface type of the initializer.
ctor->setGenericSignature(genericSig);
ctor->computeType();
ctor->setImplicitlyUnwrappedOptional(
superclassCtor->isImplicitlyUnwrappedOptional());
configureInheritedDesignatedInitAttributes(classDecl, ctor,
superclassCtor, ctx);
if (kind == DesignatedInitKind::Stub) {
// Make this a stub implementation.
ctor->setBodySynthesizer(synthesizeStubBody);
// Note that this is a stub implementation.
ctor->setStubImplementation(true);
return ctor;
}
// Form the body of a chaining designated initializer.
assert(kind == DesignatedInitKind::Chaining);
ctor->setBodySynthesizer(synthesizeDesignatedInitOverride, superclassCtor);
return ctor;
}
/// Diagnose a missing required initializer.
static void diagnoseMissingRequiredInitializer(
ClassDecl *classDecl,
ConstructorDecl *superInitializer,
ASTContext &ctx) {
// Find the location at which we should insert the new initializer.
SourceLoc insertionLoc;
SourceLoc indentationLoc;
for (auto member : classDecl->getMembers()) {
// If we don't have an indentation location yet, grab one from this
// member.
if (indentationLoc.isInvalid()) {
indentationLoc = member->getLoc();
}
// We only want to look at explicit constructors.
auto ctor = dyn_cast<ConstructorDecl>(member);
if (!ctor)
continue;
if (ctor->isImplicit())
continue;
insertionLoc = ctor->getEndLoc();
indentationLoc = ctor->getLoc();
}
// If no initializers were listed, start at the opening '{' for the class.
if (insertionLoc.isInvalid()) {
insertionLoc = classDecl->getBraces().Start;
}
if (indentationLoc.isInvalid()) {
indentationLoc = classDecl->getBraces().End;
}
// Adjust the insertion location to point at the end of this line (i.e.,
// the start of the next line).
insertionLoc = Lexer::getLocForEndOfLine(ctx.SourceMgr,
insertionLoc);
// Find the indentation used on the indentation line.
StringRef extraIndentation;
StringRef indentation = Lexer::getIndentationForLine(
ctx.SourceMgr, indentationLoc, &extraIndentation);
// Pretty-print the superclass initializer into a string.
// FIXME: Form a new initializer by performing the appropriate
// substitutions of subclass types into the superclass types, so that
// we get the right generic parameters.
std::string initializerText;
{
PrintOptions options;
options.PrintImplicitAttrs = false;
// Render the text.
llvm::raw_string_ostream out(initializerText);
{
ExtraIndentStreamPrinter printer(out, indentation);
printer.printNewline();
// If there is no explicit 'required', print one.
bool hasExplicitRequiredAttr = false;
if (auto requiredAttr
= superInitializer->getAttrs().getAttribute<RequiredAttr>())
hasExplicitRequiredAttr = !requiredAttr->isImplicit();
if (!hasExplicitRequiredAttr)
printer << "required ";
superInitializer->print(printer, options);
}
// Add a dummy body.
out << " {\n";
out << indentation << extraIndentation << "fatalError(\"";
superInitializer->getFullName().printPretty(out);
out << " has not been implemented\")\n";
out << indentation << "}\n";
}
// Complain.
ctx.Diags.diagnose(insertionLoc, diag::required_initializer_missing,
superInitializer->getFullName(),
superInitializer->getDeclContext()->getDeclaredInterfaceType())
.fixItInsert(insertionLoc, initializerText);
ctx.Diags.diagnose(findNonImplicitRequiredInit(superInitializer),
diag::required_initializer_here);
}
static bool areAllStoredPropertiesDefaultInitializable(NominalTypeDecl *decl) {
if (decl->hasClangNode())
return true;
for (auto member : decl->getMembers()) {
// If a stored property lacks an initial value and if there is no way to
// synthesize an initial value (e.g. for an optional) then we suppress
// generation of the default initializer.
if (auto pbd = dyn_cast<PatternBindingDecl>(member)) {
if (pbd->hasStorage() && !pbd->isStatic()) {
for (auto entry : pbd->getPatternList()) {
if (entry.isInitialized()) continue;
// If one of the bound variables is @NSManaged, go ahead no matter
// what.
bool CheckDefaultInitializer = true;
entry.getPattern()->forEachVariable([&](VarDecl *vd) {
if (vd->getAttrs().hasAttribute<NSManagedAttr>())
CheckDefaultInitializer = false;
});
// If we cannot default initialize the property, we cannot
// synthesize a default initializer for the class.
if (CheckDefaultInitializer && !pbd->isDefaultInitializable())
return false;
}
}
}
}
return true;
}
static void addImplicitConstructorsToStruct(StructDecl *decl, ASTContext &ctx) {
assert(!decl->hasClangNode() &&
"ClangImporter is responsible for adding implicit constructors");
assert(!decl->hasUnreferenceableStorage() &&
"User-defined structs cannot have unreferenceable storage");
decl->setAddedImplicitInitializers();
// Check whether there is a user-declared constructor or an instance
// variable.
bool FoundMemberwiseInitializedProperty = false;
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
// Initializers that were synthesized to fulfill derived conformances
// should not prevent default initializer synthesis.
if (ctor->isDesignatedInit() && !ctor->isSynthesized())
return;
}
if (auto var = dyn_cast<VarDecl>(member)) {
// If this is a backing storage property for a property wrapper,
// skip it.
if (var->getOriginalWrappedProperty())
continue;
if (var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true)) {
// Initialized 'let' properties have storage, but don't get an argument
// to the memberwise initializer since they already have an initial
// value that cannot be overridden.
if (var->isLet() && var->isParentInitialized()) {
// We cannot handle properties like:
// let (a,b) = (1,2)
// for now, just disable implicit init synthesization in structs in
// this case.
auto SP = var->getParentPattern();
if (auto *TP = dyn_cast<TypedPattern>(SP))
SP = TP->getSubPattern();
if (!isa<NamedPattern>(SP))
return;
continue;
}
FoundMemberwiseInitializedProperty = true;
}
}
}
if (FoundMemberwiseInitializedProperty) {
// Create the implicit memberwise constructor.
auto ctor = createImplicitConstructor(
decl, ImplicitConstructorKind::Memberwise, ctx);
decl->addMember(ctor);
}
if (areAllStoredPropertiesDefaultInitializable(decl))
TypeChecker::defineDefaultConstructor(decl);
}
static void addImplicitConstructorsToClass(ClassDecl *decl, ASTContext &ctx) {
// Bail out if we're validating one of our constructors already;
// we'll revisit the issue later.
if (!decl->hasClangNode()) {
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
if (ctor->isRecursiveValidation())
return;
}
}
}
decl->setAddedImplicitInitializers();
// Check whether there is a user-declared constructor or an instance
// variable.
bool FoundDesignatedInit = false;
SmallVector<std::pair<ValueDecl *, Type>, 4> declaredInitializers;
llvm::SmallPtrSet<ConstructorDecl *, 4> overriddenInits;
if (decl->hasClangNode()) {
// Objective-C classes may have interesting initializers in extensions.
for (auto member : decl->lookupDirect(DeclBaseName::createConstructor())) {
auto ctor = dyn_cast<ConstructorDecl>(member);
if (!ctor)
continue;
// Swift initializers added in extensions of Objective-C classes can never
// be overrides.
if (!ctor->hasClangNode())
continue;
if (auto overridden = ctor->getOverriddenDecl())
overriddenInits.insert(overridden);
}
} else {
for (auto member : decl->getMembers()) {
if (auto ctor = dyn_cast<ConstructorDecl>(member)) {
// Initializers that were synthesized to fulfill derived conformances
// should not prevent default initializer synthesis.
if (ctor->isDesignatedInit() && !ctor->isSynthesized())
FoundDesignatedInit = true;
if (!ctor->isInvalid()) {
auto type = getMemberTypeForComparison(ctx, ctor, nullptr);
declaredInitializers.push_back({ctor, type});
}
if (auto overridden = ctor->getOverriddenDecl())
overriddenInits.insert(overridden);
continue;
}
}
}
bool SuppressDefaultInitializer =
!areAllStoredPropertiesDefaultInitializable(decl);
// For a class with a superclass, automatically define overrides
// for all of the superclass's designated initializers.
if (Type superclassTy = decl->getSuperclass()) {
bool canInheritInitializers = (!SuppressDefaultInitializer &&
!FoundDesignatedInit);
// We can't define these overrides if we have any uninitialized
// stored properties.
if (SuppressDefaultInitializer && !FoundDesignatedInit &&
!decl->hasClangNode()) {
return;
}
auto *superclassDecl = superclassTy->getClassOrBoundGenericClass();
assert(superclassDecl && "Superclass of class is not a class?");
if (!superclassDecl->addedImplicitInitializers())
ctx.getLazyResolver()->resolveImplicitConstructors(superclassDecl);
auto ctors = TypeChecker::lookupConstructors(
decl, superclassTy,
NameLookupFlags::IgnoreAccessControl);
bool canInheritConvenienceInitalizers =
!superclassDecl->hasMissingDesignatedInitializers();
SmallVector<ConstructorDecl *, 4> requiredConvenienceInitializers;
for (auto memberResult : ctors) {
auto member = memberResult.getValueDecl();
// Skip unavailable superclass initializers.
if (AvailableAttr::isUnavailable(member))
continue;
// Skip invalid superclass initializers.
auto superclassCtor = dyn_cast<ConstructorDecl>(member);
if (superclassCtor->isInvalid())
continue;
// If we have an override for this constructor, it's okay.
if (overriddenInits.count(superclassCtor) > 0)
continue;
// We only care about required or designated initializers.
if (!superclassCtor->isDesignatedInit()) {
if (superclassCtor->isRequired()) {
assert(superclassCtor->isInheritable() &&
"factory initializers cannot be 'required'");
requiredConvenienceInitializers.push_back(superclassCtor);
}
continue;
}
// Otherwise, it may no longer be safe to inherit convenience
// initializers.
canInheritConvenienceInitalizers &= canInheritInitializers;
// Everything after this is only relevant for Swift classes being defined.
if (decl->hasClangNode())
continue;
// If the superclass initializer is not accessible from the derived
// class, don't synthesize an override, since we cannot reference the
// superclass initializer's method descriptor at all.
//
// FIXME: This should be checked earlier as part of calculating
// canInheritInitializers.
if (!superclassCtor->isAccessibleFrom(decl))
continue;
// Diagnose a missing override of a required initializer.
if (superclassCtor->isRequired() && !canInheritInitializers) {
diagnoseMissingRequiredInitializer(decl, superclassCtor, ctx);
continue;
}
// A designated or required initializer has not been overridden.
bool alreadyDeclared = false;
for (const auto &ctorAndType : declaredInitializers) {
auto *ctor = ctorAndType.first;
auto type = ctorAndType.second;
auto parentType = getMemberTypeForComparison(
ctx, superclassCtor, ctor);
if (isOverrideBasedOnType(ctor, type, superclassCtor, parentType)) {
alreadyDeclared = true;
break;
}
}
// If we have already introduced an initializer with this parameter type,
// don't add one now.
if (alreadyDeclared)
continue;
// If we're inheriting initializers, create an override delegating
// to 'super.init'. Otherwise, create a stub which traps at runtime.
auto kind = canInheritInitializers
? DesignatedInitKind::Chaining
: DesignatedInitKind::Stub;
if (auto ctor = createDesignatedInitOverride(
decl, superclassCtor, kind, ctx)) {
decl->addMember(ctor);
}
}
if (canInheritConvenienceInitalizers) {
decl->setInheritsSuperclassInitializers();
} else {
for (ConstructorDecl *requiredCtor : requiredConvenienceInitializers)
diagnoseMissingRequiredInitializer(decl, requiredCtor, ctx);
}
return;
}
if (!FoundDesignatedInit) {
// For a class with no superclass, automatically define a default
// constructor.
// ... unless there are uninitialized stored properties.
if (SuppressDefaultInitializer)
return;
// Clang-imported types should never get a default constructor, just a
// memberwise one.
if (decl->hasClangNode())
return;
TypeChecker::defineDefaultConstructor(decl);
}
}
void TypeChecker::addImplicitConstructors(NominalTypeDecl *decl) {
// If we already added implicit initializers, we're done.
if (decl->addedImplicitInitializers())
return;
// Don't add implicit constructors for an invalid declaration
if (decl->isInvalid())
return;
// Don't add implicit constructors in module interfaces.
if (auto *SF = decl->getParentSourceFile()) {
if (SF->Kind == SourceFileKind::Interface) {
decl->setAddedImplicitInitializers();
return;
}
}
if (auto *structDecl = dyn_cast<StructDecl>(decl))
addImplicitConstructorsToStruct(structDecl, Context);
if (auto *classDecl = dyn_cast<ClassDecl>(decl))
addImplicitConstructorsToClass(classDecl, Context);
}
void TypeChecker::synthesizeMemberForLookup(NominalTypeDecl *target,
DeclName member) {
auto baseName = member.getBaseName();
// Checks whether the target conforms to the given protocol. If the
// conformance is incomplete, force the conformance.
//
// Returns whether the target conforms to the protocol.
auto evaluateTargetConformanceTo = [&](ProtocolDecl *protocol) {
if (!protocol)
return false;
auto targetType = target->getDeclaredInterfaceType();
if (auto ref = conformsToProtocol(
targetType, protocol, target,
ConformanceCheckFlags::SkipConditionalRequirements)) {
if (auto *conformance = dyn_cast<NormalProtocolConformance>(
ref->getConcrete()->getRootConformance())) {
if (conformance->getState() == ProtocolConformanceState::Incomplete) {
checkConformance(conformance);
}
}
return true;
}
return false;
};
if (member.isSimpleName() && !baseName.isSpecial()) {
if (baseName.getIdentifier() == Context.Id_CodingKeys) {
// CodingKeys is a special type which may be synthesized as part of
// Encodable/Decodable conformance. If the target conforms to either
// protocol and would derive conformance to either, the type may be
// synthesized.
// If the target conforms to either and the conformance has not yet been
// evaluated, then we should do that here.
//
// Try to synthesize Decodable first. If that fails, try to synthesize
// Encodable. If either succeeds and CodingKeys should have been
// synthesized, it will be synthesized.
auto *decodableProto = Context.getProtocol(KnownProtocolKind::Decodable);
auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
if (!evaluateTargetConformanceTo(decodableProto))
(void)evaluateTargetConformanceTo(encodableProto);
}
if ((baseName.getIdentifier().str().startswith("$") ||
baseName.getIdentifier().str().startswith("_")) &&
baseName.getIdentifier().str().size() > 1) {
// $- and _-prefixed variables can be generated by properties that have
// attached property wrappers.
auto originalPropertyName =
Context.getIdentifier(baseName.getIdentifier().str().substr(1));
for (auto member : target->lookupDirect(originalPropertyName)) {
if (auto var = dyn_cast<VarDecl>(member)) {
if (var->hasAttachedPropertyWrapper()) {
auto sourceFile = var->getDeclContext()->getParentSourceFile();
if (sourceFile && sourceFile->Kind != SourceFileKind::Interface)
(void)var->getPropertyWrapperBackingPropertyInfo();
}
}
}
}
} else {
auto argumentNames = member.getArgumentNames();
if (member.isCompoundName() && argumentNames.size() != 1)
return;
if (baseName == DeclBaseName::createConstructor() &&
(member.isSimpleName() || argumentNames.front() == Context.Id_from)) {
// init(from:) may be synthesized as part of derived conformance to the
// Decodable protocol.
// If the target should conform to the Decodable protocol, check the
// conformance here to attempt synthesis.
auto *decodableProto = Context.getProtocol(KnownProtocolKind::Decodable);
(void)evaluateTargetConformanceTo(decodableProto);
} else if (!baseName.isSpecial() &&
baseName.getIdentifier() == Context.Id_encode &&
(member.isSimpleName() ||
argumentNames.front() == Context.Id_to)) {
// encode(to:) may be synthesized as part of derived conformance to the
// Encodable protocol.
// If the target should conform to the Encodable protocol, check the
// conformance here to attempt synthesis.
auto *encodableProto = Context.getProtocol(KnownProtocolKind::Encodable);
(void)evaluateTargetConformanceTo(encodableProto);
}
}
}
/// Synthesizer callback for a function body consisting of "return".
static std::pair<BraceStmt *, bool>
synthesizeSingleReturnFunctionBody(AbstractFunctionDecl *afd, void *) {
ASTContext &ctx = afd->getASTContext();
SmallVector<ASTNode, 1> stmts;
stmts.push_back(new (ctx) ReturnStmt(afd->getLoc(), nullptr));
return { BraceStmt::create(ctx, afd->getLoc(), stmts, afd->getLoc(), true),
/*isTypeChecked=*/true };
}
void TypeChecker::defineDefaultConstructor(NominalTypeDecl *decl) {
auto &ctx = decl->getASTContext();
FrontendStatsTracer StatsTracer(ctx.Stats, "define-default-ctor", decl);
PrettyStackTraceDecl stackTrace("defining default constructor for",
decl);
// Create the default constructor.
auto ctor = createImplicitConstructor(decl,
ImplicitConstructorKind::Default,
ctx);
// Add the constructor.
decl->addMember(ctor);
// Lazily synthesize an empty body for the default constructor.
ctor->setBodySynthesizer(synthesizeSingleReturnFunctionBody);
}