//===--- 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 params, ASTContext &ctx) { SmallVector labels; SmallVector labelLocs; SmallVector args; SmallVector 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(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 &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()) { const auto i = pbd->getPatternEntryIndexForVarDecl(var); isExplicitlyInitialized = pbd->isExplicitlyInitialized(i); } // Whether we can default-initialize this property. auto binding = var->getParentPatternBinding(); bool isDefaultInitializable = var->getAttrs().hasAttribute() || (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. bool isNilInitialized = var->getAttrs().hasAttribute() || (!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 params; SmallVector defaultInits; if (ICK == ImplicitConstructorKind::Memberwise) { assert(isa(decl) && "Only struct have memberwise constructor"); for (auto member : decl->getMembers()) { auto var = dyn_cast(member); if (!var) continue; if (!var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true)) continue; accessLevel = std::min(accessLevel, var->getFormalAccess()); auto varInterfaceType = var->getValueInterfaceType(); if (var->getAttrs().hasAttribute()) { // 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(SourceLoc(), Loc, var->getName(), Loc, var->getName(), decl); arg->setSpecifier(ParamSpecifier::Default); 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(decl)) { if (classDecl->getSuperclass()) ctor->getAttrs().add(new (ctx) OverrideAttr(/*IsImplicit=*/true)); } return ctor; } /// Create a stub body that emits a fatal error message. static std::pair synthesizeStubBody(AbstractFunctionDecl *fn, void *) { auto *ctor = cast(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(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 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 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 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(), SourceLoc()); // Build a generic signature for the derived class initializer. // Add the generic parameters. SmallVector newParamTypes; for (auto *newParam : newParams) { newParamTypes.push_back( newParam->getDeclaredInterfaceType()->castTo()); } 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(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 { if (auto conf = subMap.lookupConformance(depTy, proto)) return conf; return ProtocolConformanceRef(proto); }; SmallVector 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()) { // 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()) { 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()) { SmallVector 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 errorConvention; if (superclassCtor->isObjC() && !isRepresentableInObjC(ctor, ObjCReason::MemberOfObjCSubclass, errorConvention)) ctor->getAttrs().add(new (ctx) NonObjCAttr(/*isImplicit=*/true)); } static std::pair synthesizeDesignatedInitOverride(AbstractFunctionDecl *fn, void *context) { auto *ctor = cast(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()) 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()) 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 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 options = (ParameterList::Implicit | ParameterList::Inherited); 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'. 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); } // 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); (void)ctor->getInterfaceType(); 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(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()) 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(member)) { if (pbd->hasStorage() && !pbd->isStatic()) { for (auto idx : range(pbd->getNumPatternEntries())) { if (pbd->isInitialized(idx)) continue; // If one of the bound variables is @NSManaged, go ahead no matter // what. bool CheckDefaultInitializer = true; pbd->getPattern(idx)->forEachVariable([&](VarDecl *vd) { if (vd->getAttrs().hasAttribute()) 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) { 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(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(member)) { // If this is a backing storage property for a property wrapper, // skip it. if (var->getOriginalWrappedProperty()) continue; if (var->isMemberwiseInitialized(/*preferDeclaredProperties=*/true)) FoundMemberwiseInitializedProperty = true; } } if (FoundMemberwiseInitializedProperty) { // Create the implicit memberwise constructor. auto &ctx = decl->getASTContext(); auto ctor = createImplicitConstructor( decl, ImplicitConstructorKind::Memberwise, ctx); decl->addMember(ctor); } if (areAllStoredPropertiesDefaultInitializable(decl)) TypeChecker::defineDefaultConstructor(decl); } static void addImplicitConstructorsToClass(ClassDecl *decl) { // 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(member)) { if (ctor->isRecursiveValidation()) return; } } } decl->setAddedImplicitInitializers(); // Check whether there is a user-declared constructor or an instance // variable. bool FoundDesignatedInit = false; auto &ctx = decl->getASTContext(); SmallVector, 4> declaredInitializers; llvm::SmallPtrSet overriddenInits; if (decl->hasClangNode()) { // Objective-C classes may have interesting initializers in extensions. for (auto member : decl->lookupDirect(DeclBaseName::createConstructor())) { auto ctor = dyn_cast(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(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); } } } 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 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(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(decl)) addImplicitConstructorsToStruct(structDecl); if (auto *classDecl = dyn_cast(decl)) addImplicitConstructorsToClass(classDecl); } 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( 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(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 synthesizeSingleReturnFunctionBody(AbstractFunctionDecl *afd, void *) { ASTContext &ctx = afd->getASTContext(); SmallVector 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); }