//===--- CSApply.cpp - Constraint Application -----------------------------===// // // This source file is part of the Swift.org open source project // // Copyright (c) 2014 - 2018 Apple Inc. and the Swift project authors // Licensed under Apache License v2.0 with Runtime Library Exception // // See https://swift.org/LICENSE.txt for license information // See https://swift.org/CONTRIBUTORS.txt for the list of Swift project authors // //===----------------------------------------------------------------------===// // // This file implements application of a solution to a constraint // system to a particular expression, resulting in a // fully-type-checked expression. // //===----------------------------------------------------------------------===// #include "ConstraintSystem.h" #include "CodeSynthesis.h" #include "CSDiagnostics.h" #include "MiscDiagnostics.h" #include "TypeCheckProtocol.h" #include "swift/AST/ASTVisitor.h" #include "swift/AST/ASTWalker.h" #include "swift/AST/ExistentialLayout.h" #include "swift/AST/Initializer.h" #include "swift/AST/GenericSignature.h" #include "swift/AST/ParameterList.h" #include "swift/AST/ProtocolConformance.h" #include "swift/AST/SubstitutionMap.h" #include "swift/Basic/StringExtras.h" #include "llvm/ADT/APFloat.h" #include "llvm/ADT/APInt.h" #include "llvm/ADT/SmallString.h" #include "llvm/Support/Compiler.h" #include "llvm/Support/SaveAndRestore.h" using namespace swift; using namespace constraints; /// \brief Retrieve the fixed type for the given type variable. Type Solution::getFixedType(TypeVariableType *typeVar) const { auto knownBinding = typeBindings.find(typeVar); assert(knownBinding != typeBindings.end()); return knownBinding->second; } /// Determine whether the given type is an opened AnyObject. /// /// This comes up in computeSubstitutions() when accessing /// members via dynamic lookup. static bool isOpenedAnyObject(Type type) { auto archetype = type->getAs(); if (!archetype) return false; auto existential = archetype->getOpenedExistentialType(); if (!existential) return false; return existential->isAnyObject(); } SubstitutionMap Solution::computeSubstitutions( GenericSignature *sig, ConstraintLocatorBuilder locatorBuilder) const { if (sig == nullptr) return SubstitutionMap(); // Gather the substitutions from dependent types to concrete types. auto locator = getConstraintSystem().getConstraintLocator(locatorBuilder); auto openedTypes = OpenedTypes.find(locator); // If we have a member reference on an existential, there are no // opened types or substitutions. if (openedTypes == OpenedTypes.end()) return SubstitutionMap(); TypeSubstitutionMap subs; for (const auto &opened : openedTypes->second) subs[opened.first] = getFixedType(opened.second); auto &tc = getConstraintSystem().getTypeChecker(); auto lookupConformanceFn = [&](CanType original, Type replacement, ProtocolDecl *protoType) -> Optional { if (replacement->hasError() || isOpenedAnyObject(replacement) || replacement->is()) { return ProtocolConformanceRef(protoType); } return tc.conformsToProtocol(replacement, protoType, getConstraintSystem().DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::Used)); }; return SubstitutionMap::get(sig, QueryTypeSubstitutionMap{subs}, lookupConformanceFn); } /// \brief Find a particular named function witness for a type that conforms to /// the given protocol. /// /// \param tc The type check we're using. /// /// \param dc The context in which we need a witness. /// /// \param type The type whose witness to find. /// /// \param proto The protocol to which the type conforms. /// /// \param name The name of the requirement. /// /// \param diag The diagnostic to emit if the protocol definition doesn't /// have a requirement with the given name. /// /// \returns The named witness, or an empty ConcreteDeclRef if no witness /// could be found. ConcreteDeclRef findNamedWitnessImpl( TypeChecker &tc, DeclContext *dc, Type type, ProtocolDecl *proto, DeclName name, Diag<> diag, Optional conformance = None) { // Find the named requirement. ValueDecl *requirement = nullptr; for (auto member : proto->getMembers()) { auto d = dyn_cast(member); if (!d || !d->hasName()) continue; if (d->getFullName().matchesRef(name)) { requirement = d; break; } } if (!requirement || requirement->isInvalid()) { tc.diagnose(proto->getLoc(), diag); return nullptr; } // Find the member used to satisfy the named requirement. if (!conformance) { conformance = tc.conformsToProtocol(type, proto, dc, ConformanceCheckFlags::InExpression); if (!conformance) return nullptr; } // For a type with dependent conformance, just return the requirement from // the protocol. There are no protocol conformance tables. if (!conformance->isConcrete()) { auto subMap = SubstitutionMap::getProtocolSubstitutions(proto, type, *conformance); return ConcreteDeclRef(requirement, subMap); } auto concrete = conformance->getConcrete(); return concrete->getWitnessDeclRef(requirement, &tc); } static bool shouldAccessStorageDirectly(Expr *base, VarDecl *member, DeclContext *DC) { // This only matters for stored properties. if (!member->hasStorage()) return false; // ... referenced from constructors and destructors. auto *AFD = dyn_cast(DC); if (AFD == nullptr) return false; if (!isa(AFD) && !isa(AFD)) return false; // ... via a "self.property" reference. auto *DRE = dyn_cast(base); if (DRE == nullptr) return false; if (AFD->getImplicitSelfDecl() != cast(base)->getDecl()) return false; // Convenience initializers do not require special handling. // FIXME: This is a language change -- for now, keep the old behavior #if 0 if (auto *CD = dyn_cast(AFD)) if (!CD->isDesignatedInit()) return false; #endif // Ctor or dtor are for immediate class, not a derived class. if (!AFD->getParent()->getDeclaredInterfaceType()->isEqual( member->getDeclContext()->getDeclaredInterfaceType())) return false; // If the storage is resilient, we cannot access it directly at all. if (member->isResilient(DC->getParentModule(), DC->getResilienceExpansion())) return false; return true; } /// Return the implicit access kind for a MemberRefExpr with the /// specified base and member in the specified DeclContext. static AccessSemantics getImplicitMemberReferenceAccessSemantics(Expr *base, VarDecl *member, DeclContext *DC) { // Properties that have storage and accessors are frequently accessed through // accessors. However, in the init and destructor methods for the type // immediately containing the property, accesses are done direct. if (shouldAccessStorageDirectly(base, member, DC)) { // Access this directly instead of going through (e.g.) observing or // trivial accessors. return AccessSemantics::DirectToStorage; } // Check for property behavior initializations. if (auto *AFD_DC = dyn_cast(DC)) { if (member->hasBehaviorNeedingInitialization() && // In a ctor. isa(AFD_DC) && // Ctor is for immediate class, not a derived class. AFD_DC->getParent()->getDeclaredInterfaceType()->isEqual( member->getDeclContext()->getDeclaredInterfaceType()) && // Is a "self.property" reference. isa(base) && AFD_DC->getImplicitSelfDecl() == cast(base)->getDecl()) { // Do definite initialization analysis to handle this property. return AccessSemantics::BehaviorInitialization; } } // Check whether this is a member access on 'self'. bool isAccessOnSelf = false; if (auto *baseDRE = dyn_cast(base->getValueProvidingExpr())) if (auto *baseVar = dyn_cast(baseDRE->getDecl())) isAccessOnSelf = baseVar->isSelfParameter(); // If the value is always directly accessed from this context, do it. return member->getAccessSemanticsFromContext(DC, isAccessOnSelf); } bool ConstraintSystem::isTypeReference(const Expr *E) { return E->isTypeReference([&](const Expr *E) -> Type { return getType(E); }); } bool ConstraintSystem::isStaticallyDerivedMetatype(const Expr *E) { return E->isStaticallyDerivedMetatype( [&](const Expr *E) -> Type { return getType(E); }); } Type ConstraintSystem::getInstanceType(const TypeExpr *E) { return E->getInstanceType([&](const Expr *E) -> bool { return hasType(E); }, [&](const Expr *E) -> Type { return getType(E); }); } Type ConstraintSystem::getResultType(const AbstractClosureExpr *E) { return E->getResultType([&](const Expr *E) -> Type { return getType(E); }); } static bool buildObjCKeyPathString(KeyPathExpr *E, llvm::SmallVectorImpl &buf) { for (auto &component : E->getComponents()) { switch (component.getKind()) { case KeyPathExpr::Component::Kind::OptionalChain: case KeyPathExpr::Component::Kind::OptionalForce: case KeyPathExpr::Component::Kind::OptionalWrap: // KVC propagates nulls, so these don't affect the key path string. continue; case KeyPathExpr::Component::Kind::Property: { // Property references must be to @objc properties. // TODO: If we added special properties matching KVC operators like '@sum', // '@count', etc. those could be mapped too. auto property = cast(component.getDeclRef().getDecl()); if (!property->isObjC()) return false; if (!buf.empty()) { buf.push_back('.'); } auto objcName = property->getObjCPropertyName().str(); buf.append(objcName.begin(), objcName.end()); continue; } case KeyPathExpr::Component::Kind::Subscript: { // Subscripts aren't generally represented in KVC. // TODO: There are some subscript forms we could map to KVC, such as // when indexing a Dictionary or NSDictionary by string, or when applying // a mapping subscript operation to Array/Set or NSArray/NSSet. return false; case KeyPathExpr::Component::Kind::Invalid: case KeyPathExpr::Component::Kind::UnresolvedProperty: case KeyPathExpr::Component::Kind::UnresolvedSubscript: // Don't bother building the key path string if the key path didn't even // resolve. return false; } } } return true; } /// Determine whether the given type refers to a non-final class (or /// dynamic self of one). static bool isNonFinalClass(Type type) { if (auto dynamicSelf = type->getAs()) type = dynamicSelf->getSelfType(); if (auto classDecl = type->getClassOrBoundGenericClass()) return !classDecl->isFinal(); if (auto archetype = type->getAs()) if (auto super = archetype->getSuperclass()) return isNonFinalClass(super); if (type->isExistentialType()) return true; return false; } // Non-required constructors may not be not inherited. Therefore when // constructing a class object, either the metatype must be statically // derived (rather than an arbitrary value of metatype type) or the referenced // constructor must be required. static bool diagnoseInvalidDynamicConstructorReferences(ConstraintSystem &cs, Expr *base, DeclNameLoc memberRefLoc, ConstructorDecl *ctorDecl, bool SuppressDiagnostics) { auto &tc = cs.getTypeChecker(); auto baseTy = cs.getType(base)->getRValueType(); auto instanceTy = baseTy->getMetatypeInstanceType(); bool isStaticallyDerived = base->isStaticallyDerivedMetatype( [&](const Expr *expr) -> Type { return cs.getType(expr); }); // FIXME: The "hasClangNode" check here is a complete hack. if (isNonFinalClass(instanceTy) && !isStaticallyDerived && !ctorDecl->hasClangNode() && !(ctorDecl->isRequired() || ctorDecl->getDeclContext()->getSelfProtocolDecl())) { if (SuppressDiagnostics) return false; tc.diagnose(memberRefLoc, diag::dynamic_construct_class, instanceTy) .highlight(base->getSourceRange()); auto ctor = cast(ctorDecl); tc.diagnose(ctorDecl, diag::note_nonrequired_initializer, ctor->isImplicit(), ctor->getFullName()); // Constructors cannot be called on a protocol metatype, because there is no // metatype to witness it. } else if (isa(ctorDecl) && baseTy->is() && instanceTy->isExistentialType()) { if (SuppressDiagnostics) return false; if (isStaticallyDerived) { tc.diagnose(memberRefLoc, diag::construct_protocol_by_name, instanceTy) .highlight(base->getSourceRange()); } else { tc.diagnose(memberRefLoc, diag::construct_protocol_value, baseTy) .highlight(base->getSourceRange()); } } return true; } /// Form a type checked expression for the index of a @dynamicMemberLookup /// subscript index expression. This will have tuple type of (dynamicMember:T). static Expr *getDMLIndexExpr(StringRef name, Type ty, SourceLoc loc, DeclContext *dc, ConstraintSystem &cs) { auto &ctx = cs.TC.Context; // Build and type check the string literal index value to the specific // string type expected by the subscript. Expr *nameExpr = new (ctx) StringLiteralExpr(name, loc, /*implicit*/true); // Build a tuple so that argument has a label. Expr *tuple = TupleExpr::create(ctx, loc, nameExpr, ctx.Id_dynamicMember, loc, loc, /*hasTrailingClosure*/false, /*implicit*/true); (void)cs.TC.typeCheckExpression(tuple, dc, TypeLoc::withoutLoc(ty), CTP_CallArgument); cs.cacheExprTypes(tuple); return tuple; } namespace { /// \brief Rewrites an expression by applying the solution of a constraint /// system to that expression. class ExprRewriter : public ExprVisitor { public: ConstraintSystem &cs; DeclContext *dc; const Solution &solution; bool SuppressDiagnostics; /// Recognize used conformances from an imported type when we must emit /// the witness table. /// /// This arises in _BridgedStoredNSError, where we wouldn't /// otherwise pull in the witness table, causing dynamic casts to /// perform incorrectly, and _ErrorCodeProtocol, where we need to /// check for _BridgedStoredNSError conformances on the /// corresponding ErrorType. void checkForImportedUsedConformances(Type toType) { cs.getTypeChecker().useBridgedNSErrorConformances(dc, toType); } /// \brief Coerce the given tuple to another tuple type. /// /// \param expr The expression we're converting. /// /// \param fromTuple The tuple type we're converting from, which is the same /// as \c expr->getType(). /// /// \param toTuple The tuple type we're converting to. /// /// \param locator Locator describing where this tuple conversion occurs. /// /// \param sources The sources of each of the elements to be used in the /// resulting tuple, as provided by \c computeTupleShuffle. /// /// \param variadicArgs The source indices that are mapped to the variadic /// parameter of the resulting tuple, as provided by \c computeTupleShuffle. /// /// \param typeFromPattern Optionally, the caller can specify the pattern /// from where the toType is derived, so that we can deliver better fixit. Expr *coerceTupleToTuple(Expr *expr, TupleType *fromTuple, TupleType *toTuple, ConstraintLocatorBuilder locator, SmallVectorImpl &sources, SmallVectorImpl &variadicArgs, Optional typeFromPattern = None); /// \brief Coerce a subclass, class-constrained archetype, class-constrained /// existential or to a superclass type. /// /// Also supports metatypes of the above. /// /// \param expr The expression to be coerced. /// \param toType The type to which the expression will be coerced. /// \param locator Locator describing where this conversion occurs. /// /// \return The coerced expression, whose type will be equivalent to /// \c toType. Expr *coerceSuperclass(Expr *expr, Type toType, ConstraintLocatorBuilder locator); /// \brief Coerce the given value to existential type. /// /// The following conversions are supported: /// - concrete to existential /// - existential to existential /// - concrete metatype to existential metatype /// - existential metatype to existential metatype /// /// \param expr The expression to be coerced. /// \param toType The type to which the expression will be coerced. /// \param locator Locator describing where this conversion occurs. /// /// \return The coerced expression, whose type will be equivalent to /// \c toType. Expr *coerceExistential(Expr *expr, Type toType, ConstraintLocatorBuilder locator); /// \brief Coerce an expression of (possibly unchecked) optional /// type to have a different (possibly unchecked) optional type. Expr *coerceOptionalToOptional(Expr *expr, Type toType, ConstraintLocatorBuilder locator, Optional typeFromPattern = None); /// \brief Coerce an expression of implicitly unwrapped optional type to its /// underlying value type, in the correct way for an implicit /// look-through. Expr *coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy); /// Peephole an array upcast. void peepholeArrayUpcast(ArrayExpr *expr, Type toType, bool bridged, Type elementType, ConstraintLocatorBuilder locator); /// Peephole a dictionary upcast. void peepholeDictionaryUpcast(DictionaryExpr *expr, Type toType, bool bridged, Type keyType, Type valueType, ConstraintLocatorBuilder locator); /// Try to peephole the collection upcast, eliminating the need for /// a separate collection-upcast expression. /// /// \returns true if the peephole operation succeeded, in which case /// \c expr already subsumes the upcast. bool peepholeCollectionUpcast(Expr *expr, Type toType, bool bridged, ConstraintLocatorBuilder locator); /// \brief Build a collection upcast expression. /// /// \param bridged Whether this is a bridging conversion, meaning that the /// element types themselves are bridged (vs. simply coerced). Expr *buildCollectionUpcastExpr(Expr *expr, Type toType, bool bridged, ConstraintLocatorBuilder locator); /// Build the expression that performs a bridging operation from the /// given expression to the given \c toType. Expr *buildObjCBridgeExpr(Expr *expr, Type toType, ConstraintLocatorBuilder locator); static Type getBaseType(AnyFunctionType *fnType, bool wantsRValueInstanceType = true) { auto params = fnType->getParams(); assert(params.size() == 1); const auto &base = params.front(); if (wantsRValueInstanceType) return base.getPlainType()->getMetatypeInstanceType(); return base.getType(); } public: /// \brief Build a reference to the given declaration. Expr *buildDeclRef(OverloadChoice choice, DeclNameLoc loc, Type openedType, ConstraintLocatorBuilder locator, bool implicit, FunctionRefKind functionRefKind, AccessSemantics semantics) { auto *decl = choice.getDecl(); // Determine the declaration selected for this overloaded reference. auto &ctx = cs.getASTContext(); // If this is a member of a nominal type, build a reference to the // member with an implied base type. if (decl->getDeclContext()->isTypeContext() && isa(decl)) { assert(cast(decl)->isOperator() && "Must be an operator"); auto openedFnType = openedType->castTo(); auto simplifiedFnType = simplifyType(openedFnType)->castTo(); auto baseTy = getBaseType(simplifiedFnType); // Handle operator requirements found in protocols. if (auto proto = dyn_cast(decl->getDeclContext())) { // If we don't have an archetype or existential, we have to call the // witness. // FIXME: This is awful. We should be able to handle this as a call to // the protocol requirement with Self == the concrete type, and SILGen // (or later) can devirtualize as appropriate. if (!baseTy->is() && !baseTy->isAnyExistentialType()) { auto &tc = cs.getTypeChecker(); auto conformance = tc.conformsToProtocol( baseTy, proto, cs.DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::Used)); if (conformance && conformance->isConcrete()) { if (auto witness = conformance->getConcrete()->getWitnessDecl(decl, &tc)) { // Hack up an AST that we can type-check (independently) to get // it into the right form. // FIXME: the hop through 'getDecl()' is because // SpecializedProtocolConformance doesn't substitute into // witnesses' ConcreteDeclRefs. Type expectedFnType = simplifiedFnType->getResult(); Expr *refExpr; if (witness->getDeclContext()->isTypeContext()) { Expr *base = TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx); refExpr = new (ctx) MemberRefExpr(base, SourceLoc(), witness, loc, /*Implicit=*/true); } else { auto declRefExpr = new (ctx) DeclRefExpr(witness, loc, /*Implicit=*/false); declRefExpr->setFunctionRefKind(functionRefKind); refExpr = declRefExpr; } auto resultTy = tc.typeCheckExpression( refExpr, cs.DC, TypeLoc::withoutLoc(expectedFnType), CTP_CannotFail); if (!resultTy) return nullptr; cs.cacheExprTypes(refExpr); // Remove an outer function-conversion expression. This // happens when we end up referring to a witness for a // superclass conformance, and 'Self' differs. if (auto fnConv = dyn_cast(refExpr)) refExpr = fnConv->getSubExpr(); return forceUnwrapIfExpected(refExpr, choice, locator); } } } } // Build a reference to the protocol requirement. Expr *base = TypeExpr::createImplicitHack(loc.getBaseNameLoc(), baseTy, ctx); cs.cacheExprTypes(base); return buildMemberRef(base, openedType, SourceLoc(), choice, loc, openedFnType->getResult(), locator, locator, implicit, functionRefKind, semantics, /*isDynamic=*/false); } auto type = solution.simplifyType(openedType); // If we've ended up trying to assign an inout type here, it means we're // missing an ampersand in front of the ref. // // FIXME: This is the wrong place for this diagnostic. if (auto inoutType = type->getAs()) { auto &tc = cs.getTypeChecker(); tc.diagnose(loc.getBaseNameLoc(), diag::missing_address_of, inoutType->getInOutObjectType()) .fixItInsert(loc.getBaseNameLoc(), "&"); return nullptr; } SubstitutionMap substitutions; // Due to a SILGen quirk, unqualified property references do not // need substitutions. if (!isa(decl)) { substitutions = solution.computeSubstitutions( decl->getInnermostDeclContext()->getGenericSignatureOfContext(), locator); } auto declRefExpr = new (ctx) DeclRefExpr(ConcreteDeclRef(decl, substitutions), loc, implicit, semantics, type); cs.cacheType(declRefExpr); declRefExpr->setFunctionRefKind(functionRefKind); return forceUnwrapIfExpected(declRefExpr, choice, locator); } /// Describes an opened existential that has not yet been closed. struct OpenedExistential { /// The archetype describing this opened existential. ArchetypeType *Archetype; /// The existential value being opened. Expr *ExistentialValue; /// The opaque value (of archetype type) stored within the /// existential. OpaqueValueExpr *OpaqueValue; /// The depth of this currently-opened existential. Once the /// depth of the expression stack is equal to this value, the /// existential can be closed. unsigned Depth; }; /// A stack of opened existentials that have not yet been closed. /// Ordered by decreasing depth. llvm::SmallVector OpenedExistentials; /// A stack of expressions being walked, used to compute existential depth. llvm::SmallVector ExprStack; /// Members which are AbstractFunctionDecls but not FuncDecls cannot /// mutate self. bool isNonMutatingMember(ValueDecl *member) { if (!isa(member)) return false; return !isa(member) || !cast(member)->isMutating(); } unsigned getNaturalArgumentCount(ValueDecl *member) { if (isa(member)) { // For functions, close the existential once the function // has been fully applied. return 2; } else { // For storage, close the existential either when it's // accessed (if it's an rvalue only) or when it is loaded or // stored (if it's an lvalue). assert(isa(member) && "unknown member when opening existential"); return 1; } } /// If the expression might be a dynamic method call, return the base /// value for the call. Expr *getBaseExpr(Expr *expr) { // Keep going up as long as this expression is the parent's base. if (auto unresolvedDot = dyn_cast(expr)) { return unresolvedDot->getBase(); // Remaining cases should only come up when we're re-typechecking. // FIXME: really it would be much better if Sema had stricter phase // separation. } else if (auto dotSyntax = dyn_cast(expr)) { return dotSyntax->getArg(); } else if (auto ctorRef = dyn_cast(expr)) { return ctorRef->getArg(); } else if (auto apply = dyn_cast(expr)) { return apply->getFn(); } else if (auto lookupRef = dyn_cast(expr)) { return lookupRef->getBase(); } else if (auto load = dyn_cast(expr)) { return load->getSubExpr(); } else if (auto inout = dyn_cast(expr)) { return inout->getSubExpr(); } else if (auto force = dyn_cast(expr)) { return force->getSubExpr(); } else { return nullptr; } } /// Calculates the nesting depth of the current application. unsigned getArgCount(unsigned maxArgCount) { unsigned e = ExprStack.size(); unsigned argCount; // Starting from the current expression, count up if the expression is // equal to its parent expression's base. Expr *prev = ExprStack.back(); for (argCount = 1; argCount < maxArgCount && argCount < e; argCount++) { Expr *result = ExprStack[e - argCount - 1]; Expr *base = getBaseExpr(result); if (base != prev) break; prev = result; } // Invalid case -- direct call of a metatype. Has one less argument // application because there's no ".init". if (isa(ExprStack.back())) argCount--; return argCount; } /// Open an existential value into a new, opaque value of /// archetype type. /// /// \param base An expression of existential type whose value will /// be opened. /// /// \param archetype The archetype that describes the opened existential /// type. /// /// \param member The member that is being referenced on the existential /// type. /// /// \returns An OpaqueValueExpr that provides a reference to the value /// stored within the expression or its metatype (if the base was a /// metatype). Expr *openExistentialReference(Expr *base, ArchetypeType *archetype, ValueDecl *member) { assert(archetype && "archetype not already opened?"); auto &tc = cs.getTypeChecker(); // Dig out the base type. Type baseTy = cs.getType(base); // Look through lvalues. bool isLValue = false; if (auto lvalueTy = baseTy->getAs()) { isLValue = true; baseTy = lvalueTy->getObjectType(); } // Look through metatypes. bool isMetatype = false; if (auto metaTy = baseTy->getAs()) { isMetatype = true; baseTy = metaTy->getInstanceType(); } assert(baseTy->isAnyExistentialType() && "Type must be existential"); // If the base was an lvalue but it will only be treated as an // rvalue, turn the base into an rvalue now. This results in // better SILGen. if (isLValue && (isNonMutatingMember(member) || member->getDeclContext()->getDeclaredInterfaceType() ->hasReferenceSemantics())) { base = cs.coerceToRValue(base); isLValue = false; } // Determine the number of applications that need to occur before // we can close this existential, and record it. unsigned maxArgCount = getNaturalArgumentCount(member); unsigned depth = ExprStack.size() - getArgCount(maxArgCount); // Create the opaque opened value. If we started with a // metatype, it's a metatype. Type opaqueType = archetype; if (isMetatype) opaqueType = MetatypeType::get(opaqueType); if (isLValue) opaqueType = LValueType::get(opaqueType); ASTContext &ctx = tc.Context; auto archetypeVal = new (ctx) OpaqueValueExpr(base->getLoc(), opaqueType); cs.cacheType(archetypeVal); // Record the opened existential. OpenedExistentials.push_back({archetype, base, archetypeVal, depth}); return archetypeVal; } /// Trying to close the active existential, if there is one. bool closeExistential(Expr *&result, ConstraintLocatorBuilder locator, bool force=false) { if (OpenedExistentials.empty()) return false; auto &record = OpenedExistentials.back(); assert(record.Depth <= ExprStack.size()); if (!force && record.Depth < ExprStack.size() - 1) return false; // If we had a return type of 'Self', erase it. ConstraintSystem &innerCS = solution.getConstraintSystem(); auto &tc = innerCS.getTypeChecker(); Type resultTy; resultTy = cs.getType(result); if (resultTy->hasOpenedExistential(record.Archetype)) { Type erasedTy = resultTy->eraseOpenedExistential(record.Archetype); auto range = result->getSourceRange(); result = coerceToType(result, erasedTy, locator); // FIXME: Implement missing tuple-to-tuple conversion if (result == nullptr) { result = new (tc.Context) ErrorExpr(range); cs.setType(result, erasedTy); // The opaque value is no longer reachable in an AST walk as // a result of the result above being replaced with an // ErrorExpr, but there is code expecting to have a type set // on it. Since we no longer have a reachable reference, // we'll null this out. record.OpaqueValue = nullptr; } } // Form the open-existential expression. result = new (tc.Context) OpenExistentialExpr( record.ExistentialValue, record.OpaqueValue, result, cs.getType(result)); cs.cacheType(result); OpenedExistentials.pop_back(); return true; } /// \brief Build a new member reference with the given base and member. Expr *buildMemberRef(Expr *base, Type openedFullType, SourceLoc dotLoc, OverloadChoice choice, DeclNameLoc memberLoc, Type openedType, ConstraintLocatorBuilder locator, ConstraintLocatorBuilder memberLocator, bool Implicit, FunctionRefKind functionRefKind, AccessSemantics semantics, bool isDynamic) { ValueDecl *member = choice.getDecl(); auto &tc = cs.getTypeChecker(); auto &context = tc.Context; bool isSuper = base->isSuperExpr(); // The formal type of the 'self' value for the call. Type baseTy = cs.getType(base)->getRValueType(); // Figure out the actual base type, and whether we have an instance of // that type or its metatype. bool baseIsInstance = true; if (auto baseMeta = baseTy->getAs()) { baseIsInstance = false; baseTy = baseMeta->getInstanceType(); // If the member is a constructor, verify that it can be legally // referenced from this base. if (auto ctor = dyn_cast(member)) { if (!diagnoseInvalidDynamicConstructorReferences(cs, base, memberLoc, ctor, SuppressDiagnostics)) return nullptr; } } // Build a member reference. SubstitutionMap substitutions = solution.computeSubstitutions( member->getInnermostDeclContext()->getGenericSignatureOfContext(), memberLocator); auto memberRef = ConcreteDeclRef(member, substitutions); cs.TC.requestMemberLayout(member); auto refTy = solution.simplifyType(openedFullType); // If we're referring to the member of a module, it's just a simple // reference. if (baseTy->is()) { assert(semantics == AccessSemantics::Ordinary && "Direct property access doesn't make sense for this"); auto ref = new (context) DeclRefExpr(memberRef, memberLoc, Implicit); cs.setType(ref, refTy); ref->setFunctionRefKind(functionRefKind); auto *DSBI = cs.cacheType(new (context) DotSyntaxBaseIgnoredExpr( base, dotLoc, ref, cs.getType(ref))); return forceUnwrapIfExpected(DSBI, choice, memberLocator); } // The formal type of the 'self' value for the member's declaration. Type containerTy = getBaseType(refTy->castTo()); // If we have an opened existential, selfTy and baseTy will both be // the same opened existential type. Type selfTy = containerTy; // If we opened up an existential when referencing this member, update // the base accordingly. auto knownOpened = solution.OpenedExistentialTypes.find( getConstraintSystem().getConstraintLocator( memberLocator)); bool openedExistential = false; if (knownOpened != solution.OpenedExistentialTypes.end()) { base = openExistentialReference(base, knownOpened->second, member); baseTy = knownOpened->second; selfTy = baseTy; openedExistential = true; } // If this is a method whose result type is dynamic Self, or a // construction, replace the result type with the actual object type. Type dynamicSelfFnType; if (!member->getDeclContext()->getSelfProtocolDecl()) { if (auto func = dyn_cast(member)) { if ((isa(func) && cast(func)->hasDynamicSelf()) || (isa(func) && containerTy->getClassOrBoundGenericClass())) { refTy = refTy->replaceCovariantResultType(containerTy, 2); if (!baseTy->isEqual(containerTy)) { dynamicSelfFnType = refTy->replaceCovariantResultType(baseTy, 2); } } } } // References to properties with accessors and storage usually go // through the accessors, but sometimes are direct. if (auto *VD = dyn_cast(member)) { if (semantics == AccessSemantics::Ordinary) semantics = getImplicitMemberReferenceAccessSemantics(base, VD, dc); } if (baseIsInstance) { // Convert the base to the appropriate container type, turning it // into an lvalue if required. // If the base is already an lvalue with the right base type, we can // pass it as an inout qualified type. auto selfParamTy = isDynamic ? selfTy : containerTy; if (selfTy->isEqual(baseTy)) if (cs.getType(base)->is()) selfParamTy = InOutType::get(selfTy); base = coerceObjectArgumentToType( base, selfParamTy, member, semantics, locator.withPathElement(ConstraintLocator::MemberRefBase)); } else { // Convert the base to an rvalue of the appropriate metatype. base = coerceToType(base, MetatypeType::get(isDynamic ? selfTy : containerTy), locator.withPathElement( ConstraintLocator::MemberRefBase)); if (!base) return nullptr; base = cs.coerceToRValue(base); } assert(base && "Unable to convert base?"); // Handle dynamic references. if (isDynamic || member->getAttrs().hasAttribute()) { base = cs.coerceToRValue(base); Expr *ref = new (context) DynamicMemberRefExpr(base, dotLoc, memberRef, memberLoc); ref->setImplicit(Implicit); // FIXME: FunctionRefKind // Compute the type of the reference. Type refType = simplifyType(openedType); // If the base was an opened existential, erase the opened // existential. if (openedExistential && refType->hasOpenedExistential(knownOpened->second)) { refType = refType->eraseOpenedExistential(knownOpened->second); } cs.setType(ref, refType); closeExistential(ref, locator, /*force=*/openedExistential); // If this attribute was inferred based on deprecated Swift 3 rules, // complain. if (auto attr = member->getAttrs().getAttribute()) { if (attr->isSwift3Inferred() && tc.Context.LangOpts.WarnSwift3ObjCInference == Swift3ObjCInferenceWarnings::Minimal) { tc.diagnose(memberLoc, diag::expr_dynamic_lookup_swift3_objc_inference, member->getDescriptiveKind(), member->getFullName(), member->getDeclContext() ->getSelfNominalTypeDecl() ->getName()); tc.diagnose(member, diag::make_decl_objc, member->getDescriptiveKind()) .fixItInsert(member->getAttributeInsertionLoc(false), "@objc "); } } if (isDynamic) { // Rewrite for implicit unwrapping if the solution requires it. auto *dynamicLocator = cs.getConstraintLocator(memberLocator.withPathElement( ConstraintLocator::DynamicLookupResult)); if (solution.getDisjunctionChoice(dynamicLocator)) { auto *forceValue = new (context) ForceValueExpr(ref, ref->getEndLoc()); auto optTy = cs.getType(forceValue->getSubExpr()); cs.setType(forceValue, optTy->getOptionalObjectType()); ref = forceValue; } } // We also need to handle the implicitly unwrap of the result // of the called function if that's the type checking solution // we ended up with. return forceUnwrapIfExpected( ref, choice, memberLocator, member->getAttrs().hasAttribute()); } // For types and properties, build member references. if (isa(member) || isa(member)) { assert(!dynamicSelfFnType && "Converted type doesn't make sense here"); if (!baseIsInstance && member->isInstanceMember()) { assert(memberLocator.getBaseLocator() && cs.UnevaluatedRootExprs.count( memberLocator.getBaseLocator()->getAnchor()) && "Attempt to reference an instance member of a metatype"); auto baseInstanceTy = cs.getType(base) ->getInOutObjectType()->getMetatypeInstanceType(); base = new (context) UnevaluatedInstanceExpr(base, baseInstanceTy); cs.cacheType(base); base->setImplicit(); } auto memberRefExpr = new (context) MemberRefExpr(base, dotLoc, memberRef, memberLoc, Implicit, semantics); memberRefExpr->setIsSuper(isSuper); // Skip the synthesized 'self' input type of the opened type. cs.setType(memberRefExpr, simplifyType(openedType)); Expr *result = memberRefExpr; closeExistential(result, locator); return forceUnwrapIfExpected(result, choice, memberLocator); } // Handle all other references. auto declRefExpr = new (context) DeclRefExpr(memberRef, memberLoc, Implicit, semantics); declRefExpr->setFunctionRefKind(functionRefKind); cs.setType(declRefExpr, refTy); Expr *ref = declRefExpr; // If the reference needs to be converted, do so now. if (dynamicSelfFnType) { ref = new (context) CovariantFunctionConversionExpr(ref, dynamicSelfFnType); cs.cacheType(ref); } ApplyExpr *apply; if (isa(member)) { // FIXME: Provide type annotation. ref = forceUnwrapIfExpected(ref, choice, memberLocator); apply = new (context) ConstructorRefCallExpr(ref, base); } else if (!baseIsInstance && member->isInstanceMember()) { // Reference to an unbound instance method. Expr *result = new (context) DotSyntaxBaseIgnoredExpr(base, dotLoc, ref, cs.getType(ref)); cs.cacheType(result); closeExistential(result, locator, /*force=*/openedExistential); return forceUnwrapIfExpected(result, choice, memberLocator); } else { assert((!baseIsInstance || member->isInstanceMember()) && "can't call a static method on an instance"); ref = forceUnwrapIfExpected(ref, choice, memberLocator); apply = new (context) DotSyntaxCallExpr(ref, dotLoc, base); if (Implicit) { apply->setImplicit(); } } return finishApply(apply, openedType, locator); } /// \brief Describes either a type or the name of a type to be resolved. using TypeOrName = llvm::PointerUnion; /// \brief Convert the given literal expression via a protocol pair. /// /// This routine handles the two-step literal conversion process used /// by integer, float, character, extended grapheme cluster, and string /// literals. The first step uses \c builtinProtocol while the second /// step uses \c protocol. /// /// \param literal The literal expression. /// /// \param type The literal type. This type conforms to \c protocol, /// and may also conform to \c builtinProtocol. /// /// \param openedType The literal type as it was opened in the type system. /// /// \param protocol The protocol that describes the literal requirement. /// /// \param literalType Either the name of the associated type in /// \c protocol that describes the argument type of the conversion function /// (\c literalFuncName) or the argument type itself. /// /// \param literalFuncName The name of the conversion function requirement /// in \c protocol. /// /// \param builtinProtocol The "builtin" form of the protocol, which /// always takes builtin types and can only be properly implemented /// by standard library types. If \c type does not conform to this /// protocol, it's literal type will. /// /// \param builtinLiteralType Either the name of the associated type in /// \c builtinProtocol that describes the argument type of the builtin /// conversion function (\c builtinLiteralFuncName) or the argument type /// itself. /// /// \param builtinLiteralFuncName The name of the conversion function /// requirement in \c builtinProtocol. /// /// \param isBuiltinArgType Function that determines whether the given /// type is acceptable as the argument type for the builtin conversion. /// /// \param brokenProtocolDiag The diagnostic to emit if the protocol /// is broken. /// /// \param brokenBuiltinProtocolDiag The diagnostic to emit if the builtin /// protocol is broken. /// /// \returns the converted literal expression. Expr *convertLiteral(Expr *literal, Type type, Type openedType, ProtocolDecl *protocol, TypeOrName literalType, DeclName literalFuncName, ProtocolDecl *builtinProtocol, TypeOrName builtinLiteralType, DeclName builtinLiteralFuncName, bool (*isBuiltinArgType)(Type), Diag<> brokenProtocolDiag, Diag<> brokenBuiltinProtocolDiag); /// \brief Convert the given literal expression via a protocol pair. /// /// This routine handles the two-step literal conversion process used /// by integer, float, character, extended grapheme cluster, and string /// literals. The first step uses \c builtinProtocol while the second /// step uses \c protocol. /// /// \param literal The literal expression. /// /// \param type The literal type. This type conforms to \c protocol, /// and may also conform to \c builtinProtocol. /// /// \param protocol The protocol that describes the literal requirement. /// /// \param literalType The name of the associated type in \c protocol that /// describes the argument type of the conversion function (\c /// literalFuncName). /// /// \param literalFuncName The name of the conversion function requirement /// in \c protocol. /// /// \param builtinProtocol The "builtin" form of the protocol, which /// always takes builtin types and can only be properly implemented /// by standard library types. If \c type does not conform to this /// protocol, it's literal type will. /// /// \param builtinLiteralFuncName The name of the conversion function /// requirement in \c builtinProtocol. /// /// \param brokenProtocolDiag The diagnostic to emit if the protocol /// is broken. /// /// \param brokenBuiltinProtocolDiag The diagnostic to emit if the builtin /// protocol is broken. /// /// \returns the converted literal expression. Expr *convertLiteralInPlace(Expr *literal, Type type, ProtocolDecl *protocol, Identifier literalType, DeclName literalFuncName, ProtocolDecl *builtinProtocol, DeclName builtinLiteralFuncName, Diag<> brokenProtocolDiag, Diag<> brokenBuiltinProtocolDiag); /// \brief Finish a function application by performing the appropriate /// conversions on the function and argument expressions and setting /// the resulting type. /// /// \param apply The function application to finish type-checking, which /// may be a newly-built expression. /// /// \param openedType The "opened" type this expression had during /// type checking, which will be used to specialize the resulting, /// type-checked expression appropriately. /// /// \param locator The locator for the original expression. Expr *finishApply(ApplyExpr *apply, Type openedType, ConstraintLocatorBuilder locator); private: /// \brief Simplify the given type by substituting all occurrences of /// type variables for their fixed types. Type simplifyType(Type type) { return solution.simplifyType(type); } public: /// \brief Coerce a closure expression with a non-Void return type to a /// contextual function type with a Void return type. /// /// This operation cannot fail. /// /// \param expr The closure expression to coerce. /// /// \returns The coerced closure expression. /// ClosureExpr *coerceClosureExprToVoid(ClosureExpr *expr); /// \brief Coerce a closure expression with a Never return type to a /// contextual function type with some other return type. /// /// This operation cannot fail. /// /// \param expr The closure expression to coerce. /// /// \returns The coerced closure expression. /// ClosureExpr *coerceClosureExprFromNever(ClosureExpr *expr); /// \brief Coerce the given expression to the given type. /// /// This operation cannot fail. /// /// \param expr The expression to coerce. /// \param toType The type to coerce the expression to. /// \param locator Locator used to describe where in this expression we are. /// \param typeFromPattern Optionally, the caller can specify the pattern /// from where the toType is derived, so that we can deliver better fixit. /// /// \returns the coerced expression, which will have type \c ToType. Expr *coerceToType(Expr *expr, Type toType, ConstraintLocatorBuilder locator, Optional typeFromPattern = None); /// \brief Coerce the given expression (which is the argument to a call) to /// the given parameter type. /// /// This operation cannot fail. /// /// \param arg The argument expression. /// \param funcType The function type. /// \param apply The ApplyExpr that forms the call. /// \param argLabels The argument labels provided for the call. /// \param hasTrailingClosure Whether the last argument is a trailing /// closure. /// \param locator Locator used to describe where in this expression we are. /// /// \returns the coerced expression, which will have type \c ToType. Expr * coerceCallArguments(Expr *arg, AnyFunctionType *funcType, ApplyExpr *apply, ArrayRef argLabels, bool hasTrailingClosure, ConstraintLocatorBuilder locator); /// \brief Coerce the given object argument (e.g., for the base of a /// member expression) to the given type. /// /// \param expr The expression to coerce. /// /// \param baseTy The base type /// /// \param member The member being accessed. /// /// \param semantics The kind of access we've been asked to perform. /// /// \param locator Locator used to describe where in this expression we are. Expr *coerceObjectArgumentToType(Expr *expr, Type baseTy, ValueDecl *member, AccessSemantics semantics, ConstraintLocatorBuilder locator); private: /// \brief Build a new subscript. /// /// \param base The base of the subscript. /// \param index The index of the subscript. /// \param locator The locator used to refer to the subscript. /// \param isImplicit Whether this is an implicit subscript. Expr *buildSubscript(Expr *base, Expr *index, ArrayRef argLabels, bool hasTrailingClosure, ConstraintLocatorBuilder locator, bool isImplicit, AccessSemantics semantics, Optional selected = None) { // Determine the declaration selected for this subscript operation. if (!selected) selected = solution.getOverloadChoiceIfAvailable( cs.getConstraintLocator( locator.withPathElement( ConstraintLocator::SubscriptMember))); // Handles situation where there was a solution available but it didn't // have a proper overload selected from subscript call, might be because // solver was allowed to return free or unresolved types, which can // happen while running diagnostics on one of the expressions. if (!selected.hasValue()) { auto &tc = cs.TC; auto baseType = cs.getType(base); if (auto errorType = baseType->getAs()) { tc.diagnose(base->getLoc(), diag::cannot_subscript_base, errorType->getOriginalType()) .highlight(base->getSourceRange()); } else { tc.diagnose(base->getLoc(), diag::cannot_subscript_ambiguous_base) .highlight(base->getSourceRange()); } return nullptr; } // Build the new subscript. auto newSubscript = buildSubscriptHelper(base, index, argLabels, *selected, hasTrailingClosure, locator, isImplicit, semantics); if (selected->choice.getKind() == OverloadChoiceKind::DeclViaDynamic) { // Rewrite for implicit unwrapping if the solution requires it. auto *dynamicLocator = cs.getConstraintLocator( locator.withPathElement(ConstraintLocator::SubscriptMember) .withPathElement(ConstraintLocator::DynamicLookupResult)); if (solution.getDisjunctionChoice(dynamicLocator)) { auto *forceValue = new (cs.getASTContext()) ForceValueExpr(newSubscript, newSubscript->getEndLoc()); auto optTy = cs.getType(forceValue->getSubExpr()); cs.setType(forceValue, optTy->getOptionalObjectType()); newSubscript = forceValue; } } if (selected->choice.isDecl()) { auto locatorKind = ConstraintLocator::SubscriptMember; if (selected->choice.getKind() == OverloadChoiceKind::DynamicMemberLookup) locatorKind = ConstraintLocator::Member; newSubscript = forceUnwrapIfExpected(newSubscript, selected->choice, locator.withPathElement(locatorKind)); } return newSubscript; } Expr *buildSubscriptHelper(Expr *base, Expr *index, ArrayRef argLabels, SelectedOverload &selected, bool hasTrailingClosure, ConstraintLocatorBuilder locator, bool isImplicit, AccessSemantics semantics) { auto choice = selected.choice; // Apply a key path if we have one. if (choice.getKind() == OverloadChoiceKind::KeyPathApplication) { auto applicationTy = simplifyType(selected.openedType)->castTo(); index = cs.coerceToRValue(index); // The index argument should be (keyPath: KeyPath). // Dig the key path expression out of the arguments. auto indexKP = cast(index)->getElement(0); auto keyPathExprTy = cs.getType(indexKP); auto keyPathTy = applicationTy->getParams().front().getType(); Type valueTy; Type baseTy; bool resultIsLValue; if (auto nom = keyPathTy->getAs()) { // AnyKeyPath is rvalue T -> rvalue Any? if (nom->getDecl() == cs.getASTContext().getAnyKeyPathDecl()) { valueTy = ProtocolCompositionType::get(cs.getASTContext(), {}, /*explicit anyobject*/ false); valueTy = OptionalType::get(valueTy); resultIsLValue = false; base = cs.coerceToRValue(base); baseTy = cs.getType(base); // We don't really want to attempt AnyKeyPath application // if we know a more specific key path type is being applied. if (!keyPathTy->isEqual(keyPathExprTy)) { cs.TC.diagnose(base->getLoc(), diag::expr_smart_keypath_application_type_mismatch, keyPathExprTy, baseTy) .highlight(index->getSourceRange()); } } else { llvm_unreachable("unknown key path class!"); } } else { auto keyPathBGT = keyPathTy->castTo(); baseTy = keyPathBGT->getGenericArgs()[0]; // Coerce the base to the key path's expected base type. if (!baseTy->isEqual(cs.getType(base)->getRValueType())) base = coerceToType(base, baseTy, locator); if (keyPathBGT->getDecl() == cs.getASTContext().getPartialKeyPathDecl()) { // PartialKeyPath is rvalue T -> rvalue Any valueTy = ProtocolCompositionType::get(cs.getASTContext(), {}, /*explicit anyobject*/ false); resultIsLValue = false; base = cs.coerceToRValue(base); } else { // *KeyPath is T -> U, with rvalueness based on mutability // of base and keypath valueTy = keyPathBGT->getGenericArgs()[1]; // The result may be an lvalue based on the base and key path kind. if (keyPathBGT->getDecl() == cs.getASTContext().getKeyPathDecl()) { resultIsLValue = false; base = cs.coerceToRValue(base); } else if (keyPathBGT->getDecl() == cs.getASTContext().getWritableKeyPathDecl()) { resultIsLValue = cs.getType(base)->hasLValueType(); } else if (keyPathBGT->getDecl() == cs.getASTContext().getReferenceWritableKeyPathDecl()) { resultIsLValue = true; base = cs.coerceToRValue(base); } else { llvm_unreachable("unknown key path class!"); } } } if (resultIsLValue) valueTy = LValueType::get(valueTy); auto keyPathAp = new (cs.getASTContext()) KeyPathApplicationExpr(base, index->getStartLoc(), indexKP, index->getEndLoc(), valueTy, base->isImplicit() && index->isImplicit()); cs.setType(keyPathAp, valueTy); return keyPathAp; } auto subscript = cast(choice.getDecl()); cs.TC.requestMemberLayout(subscript); auto &tc = cs.getTypeChecker(); auto baseTy = cs.getType(base)->getRValueType(); // Check whether the base is 'super'. bool isSuper = base->isSuperExpr(); // Use the correct kind of locator depending on how this subscript came // to be. auto locatorKind = ConstraintLocator::SubscriptMember; if (choice.getKind() == OverloadChoiceKind::DynamicMemberLookup) locatorKind = ConstraintLocator::Member; // If we opened up an existential when performing the subscript, open // the base accordingly. auto knownOpened = solution.OpenedExistentialTypes.find( getConstraintSystem().getConstraintLocator( locator.withPathElement(locatorKind))); if (knownOpened != solution.OpenedExistentialTypes.end()) { base = openExistentialReference(base, knownOpened->second, subscript); baseTy = knownOpened->second; } // Figure out the index and result types. Type resultTy; if (choice.getKind() != OverloadChoiceKind::DynamicMemberLookup) { auto subscriptTy = simplifyType(selected.openedType); auto *subscriptFnTy = subscriptTy->castTo(); resultTy = subscriptFnTy->getResult(); // Coerce the index argument. index = coerceCallArguments(index, subscriptFnTy, nullptr, argLabels, hasTrailingClosure, locator.withPathElement( ConstraintLocator::ApplyArgument)); if (!index) return nullptr; } else { // If this is a @dynamicMemberLookup, then the type of the selection is // actually the property/result type. That's fine though, and we // already have the index type adjusted to the correct type expected by // the subscript. resultTy = simplifyType(selected.openedType); } auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; // Form the subscript expression. // Compute the substitutions used to reference the subscript. SubstitutionMap substitutions = solution.computeSubstitutions( subscript->getInnermostDeclContext()->getGenericSignatureOfContext(), locator.withPathElement(locatorKind)); ConcreteDeclRef subscriptRef(subscript, substitutions); // Handle dynamic lookup. if (choice.getKind() == OverloadChoiceKind::DeclViaDynamic || subscript->getAttrs().hasAttribute()) { base = coerceObjectArgumentToType(base, baseTy, subscript, AccessSemantics::Ordinary, locator); if (!base) return nullptr; // TODO: diagnose if semantics != AccessSemantics::Ordinary? auto subscriptExpr = DynamicSubscriptExpr::create(tc.Context, base, index, subscriptRef, isImplicit, getType); cs.setType(subscriptExpr, resultTy); Expr *result = subscriptExpr; closeExistential(result, locator); return result; } // Convert the base. auto openedFullFnType = selected.openedFullType->castTo(); auto openedBaseType = getBaseType(openedFullFnType, /*wantsRValue*/ false); auto containerTy = solution.simplifyType(openedBaseType); base = coerceObjectArgumentToType( base, containerTy, subscript, AccessSemantics::Ordinary, locator.withPathElement(ConstraintLocator::MemberRefBase)); if (!base) return nullptr; // Form the subscript expression. auto subscriptExpr = SubscriptExpr::create( tc.Context, base, index, subscriptRef, isImplicit, semantics, getType); cs.setType(subscriptExpr, resultTy); subscriptExpr->setIsSuper(isSuper); Expr *result = subscriptExpr; closeExistential(result, locator); return result; } /// \brief Build a new reference to another constructor. Expr *buildOtherConstructorRef(Type openedFullType, ConstructorDecl *ctor, Expr *base, DeclNameLoc loc, ConstraintLocatorBuilder locator, bool implicit) { auto &tc = cs.getTypeChecker(); auto &ctx = tc.Context; // Compute the concrete reference. SubstitutionMap substitutions = solution.computeSubstitutions(ctor->getGenericSignature(), locator); auto ref = ConcreteDeclRef(ctor, substitutions); // The constructor was opened with the allocating type, not the // initializer type. Map the former into the latter. auto resultTy = solution.simplifyType(openedFullType); auto selfTy = getBaseType(resultTy->castTo()); // Also replace the result type with the base type, so that calls // to constructors defined in a superclass will know to cast the // result to the derived type. resultTy = resultTy->replaceCovariantResultType(selfTy, 2); ParameterTypeFlags flags; if (!selfTy->hasReferenceSemantics()) flags = flags.withInOut(true); auto selfParam = AnyFunctionType::Param(selfTy, Identifier(), flags); resultTy = FunctionType::get({selfParam}, resultTy->castTo()->getResult(), resultTy->castTo()->getExtInfo()); // Build the constructor reference. Expr *ctorRef = cs.cacheType( new (ctx) OtherConstructorDeclRefExpr(ref, loc, implicit, resultTy)); // Wrap in covariant `Self` return if needed. if (selfTy->hasReferenceSemantics()) { auto covariantTy = resultTy->replaceCovariantResultType( cs.getType(base)->getWithoutSpecifierType(), 2); if (!covariantTy->isEqual(resultTy)) ctorRef = cs.cacheType( new (ctx) CovariantFunctionConversionExpr(ctorRef, covariantTy)); } return ctorRef; } /// Bridge the given value (which is an error type) to NSError. Expr *bridgeErrorToObjectiveC(Expr *value) { auto &tc = cs.getTypeChecker(); auto nsErrorDecl = tc.Context.getNSErrorDecl(); assert(nsErrorDecl && "Missing NSError?"); Type nsErrorType = nsErrorDecl->getDeclaredInterfaceType(); auto result = new (tc.Context) BridgeToObjCExpr(value, nsErrorType); return cs.cacheType(result); } /// Bridge the given value to its corresponding Objective-C object /// type. /// /// This routine should only be used for bridging value types. /// /// \param value The value to be bridged. Expr *bridgeToObjectiveC(Expr *value, Type objcType) { auto &tc = cs.getTypeChecker(); auto result = new (tc.Context) BridgeToObjCExpr(value, objcType); return cs.cacheType(result); } /// Bridge the given object from Objective-C to its value type. /// /// This routine should only be used for bridging value types. /// /// \param object The object, whose type should already be of the type /// that the value type bridges through. /// /// \param valueType The value type to which we are bridging. /// /// \param conditional Whether the bridging should be conditional. If false, /// uses forced bridging. /// /// \returns a value of type \c valueType (optional if \c conditional) that /// stores the bridged result or (when \c conditional) an empty optional if /// conditional bridging fails. Expr *bridgeFromObjectiveC(Expr *object, Type valueType, bool conditional) { auto &tc = cs.getTypeChecker(); if (!conditional) { auto result = new (tc.Context) BridgeFromObjCExpr(object, valueType); return cs.cacheType(result); } // Find the _BridgedToObjectiveC protocol. auto bridgedProto = tc.Context.getProtocol(KnownProtocolKind::ObjectiveCBridgeable); // Try to find the conformance of the value type to _BridgedToObjectiveC. auto bridgedToObjectiveCConformance = tc.conformsToProtocol(valueType, bridgedProto, cs.DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::Used)); FuncDecl *fn = nullptr; if (bridgedToObjectiveCConformance) { assert(bridgedToObjectiveCConformance->getConditionalRequirements() .empty() && "cannot conditionally conform to _BridgedToObjectiveC"); // The conformance to _BridgedToObjectiveC is statically known. // Retrieve the bridging operation to be used if a static conformance // to _BridgedToObjectiveC can be proven. fn = conditional ? tc.Context.getConditionallyBridgeFromObjectiveCBridgeable(&tc) : tc.Context.getForceBridgeFromObjectiveCBridgeable(&tc); } else { // Retrieve the bridging operation to be used if a static conformance // to _BridgedToObjectiveC cannot be proven. fn = conditional ? tc.Context.getConditionallyBridgeFromObjectiveC(&tc) : tc.Context.getForceBridgeFromObjectiveC(&tc); } if (!fn) { tc.diagnose(object->getLoc(), diag::missing_bridging_function, conditional); return nullptr; } tc.validateDecl(fn); // Form a reference to the function. The bridging operations are generic, // so we need to form substitutions and compute the resulting type. auto genericSig = fn->getGenericSignature(); auto subMap = SubstitutionMap::get( genericSig, [&](SubstitutableType *type) -> Type { assert(type->isEqual(genericSig->getGenericParams()[0])); return valueType; }, [&](CanType origType, Type replacementType, ProtocolDecl *protoType) -> ProtocolConformanceRef { assert(bridgedToObjectiveCConformance); return *bridgedToObjectiveCConformance; }); ConcreteDeclRef fnSpecRef(fn, subMap); auto resultType = OptionalType::get(valueType); auto result = new (tc.Context) ConditionalBridgeFromObjCExpr(object, resultType, fnSpecRef); return cs.cacheType(result); } /// Bridge the given object from Objective-C to its value type. /// /// This routine should only be used for bridging value types. /// /// \param object The object, whose type should already be of the type /// that the value type bridges through. /// /// \param valueType The value type to which we are bridging. /// /// \returns a value of type \c valueType that stores the bridged result. Expr *forceBridgeFromObjectiveC(Expr *object, Type valueType) { return bridgeFromObjectiveC(object, valueType, false); } TypeAliasDecl *MaxFloatTypeDecl = nullptr; public: ExprRewriter(ConstraintSystem &cs, const Solution &solution, bool suppressDiagnostics) : cs(cs), dc(cs.DC), solution(solution), SuppressDiagnostics(suppressDiagnostics) {} ConstraintSystem &getConstraintSystem() const { return cs; } /// \brief Simplify the expression type and return the expression. /// /// This routine is used for 'simple' expressions that only need their /// types simplified, with no further computation. Expr *simplifyExprType(Expr *expr) { auto toType = simplifyType(cs.getType(expr)); cs.setType(expr, toType); return expr; } Expr *visitErrorExpr(ErrorExpr *expr) { // Do nothing with error expressions. return expr; } Expr *visitCodeCompletionExpr(CodeCompletionExpr *expr) { // Do nothing with code completion expressions. auto toType = simplifyType(cs.getType(expr)); cs.setType(expr, toType); return expr; } Expr *handleIntegerLiteralExpr(LiteralExpr *expr) { // If the literal has been assigned a builtin integer type, // don't mess with it. if (cs.getType(expr)->is()) return expr; auto &tc = cs.getTypeChecker(); ProtocolDecl *protocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByIntegerLiteral); ProtocolDecl *builtinProtocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinIntegerLiteral); // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(cs.getType(expr)); if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } if (auto floatProtocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByFloatLiteral)) { if (auto defaultFloatType = tc.getDefaultType(floatProtocol, dc)) { if (defaultFloatType->isEqual(type)) type = defaultFloatType; } } DeclName initName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_integerLiteral }); DeclName builtinInitName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_builtinIntegerLiteral }); return convertLiteral( expr, type, cs.getType(expr), protocol, tc.Context.Id_IntegerLiteralType, initName, builtinProtocol, // Note that 'MaxIntegerType' is guaranteed to be available. // Otherwise it would be caught by CSGen::visitLiteralExpr tc.getMaxIntegerType(dc), builtinInitName, nullptr, diag::integer_literal_broken_proto, diag::builtin_integer_literal_broken_proto); } Expr *visitNilLiteralExpr(NilLiteralExpr *expr) { auto &tc = cs.getTypeChecker(); auto *protocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByNilLiteral); // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(cs.getType(expr)); if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } // By far the most common 'nil' literal is for Optional.none. // // Emit this case directly instead of calling Optional.init(nilLiteral:), // since this generates more efficient SIL. if (auto objectType = type->getOptionalObjectType()) { auto *nilDecl = tc.Context.getOptionalNoneDecl(); tc.validateDecl(nilDecl); if (!nilDecl->hasInterfaceType()) return nullptr; auto genericSig = nilDecl->getDeclContext()->getGenericSignatureOfContext(); SubstitutionMap subs = SubstitutionMap::get(genericSig, llvm::makeArrayRef(objectType), { }); ConcreteDeclRef concreteDeclRef(nilDecl, subs); auto nilType = FunctionType::get( {FunctionType::Param(MetatypeType::get(type))}, type); auto *nilRefExpr = new (tc.Context) DeclRefExpr( concreteDeclRef, DeclNameLoc(expr->getLoc()), /*implicit=*/true, AccessSemantics::Ordinary, nilType); cs.cacheType(nilRefExpr); auto *typeExpr = TypeExpr::createImplicitHack( expr->getLoc(), type, tc.Context); cs.cacheType(typeExpr); auto *callExpr = new (tc.Context) DotSyntaxCallExpr( nilRefExpr, expr->getLoc(), typeExpr, type); callExpr->setImplicit(true); cs.cacheType(callExpr); return callExpr; } DeclName initName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_nilLiteral }); return convertLiteral(expr, type, cs.getType(expr), protocol, Identifier(), initName, nullptr, Identifier(), Identifier(), [] (Type type) -> bool { return false; }, diag::nil_literal_broken_proto, diag::nil_literal_broken_proto); } Expr *visitIntegerLiteralExpr(IntegerLiteralExpr *expr) { return handleIntegerLiteralExpr(expr); } Expr *visitFloatLiteralExpr(FloatLiteralExpr *expr) { // If the literal has been assigned a builtin float type, // don't mess with it. if (cs.getType(expr)->is()) return expr; auto &tc = cs.getTypeChecker(); ProtocolDecl *protocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByFloatLiteral); ProtocolDecl *builtinProtocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinFloatLiteral); // For type-sugar reasons, prefer the spelling of the default literal // type. auto type = simplifyType(cs.getType(expr)); if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } // Find the maximum-sized builtin float type. // FIXME: Cache name lookup. if (!MaxFloatTypeDecl) { SmallVector lookupResults; tc.getStdlibModule(dc)->lookupValue(/*AccessPath=*/{}, tc.Context.Id_MaxBuiltinFloatType, NLKind::QualifiedLookup, lookupResults); if (lookupResults.size() == 1) MaxFloatTypeDecl = dyn_cast(lookupResults.front()); } if (!MaxFloatTypeDecl || !MaxFloatTypeDecl->hasInterfaceType() || !MaxFloatTypeDecl->getDeclaredInterfaceType()->is()) { tc.diagnose(expr->getLoc(), diag::no_MaxBuiltinFloatType_found); return nullptr; } tc.validateDecl(MaxFloatTypeDecl); auto maxType = MaxFloatTypeDecl->getUnderlyingTypeLoc().getType(); DeclName initName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_floatLiteral }); DeclName builtinInitName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_builtinFloatLiteral }); return convertLiteral( expr, type, cs.getType(expr), protocol, tc.Context.Id_FloatLiteralType, initName, builtinProtocol, maxType, builtinInitName, nullptr, diag::float_literal_broken_proto, diag::builtin_float_literal_broken_proto); } Expr *visitBooleanLiteralExpr(BooleanLiteralExpr *expr) { if (cs.getType(expr) && cs.getType(expr)->is()) return expr; auto &tc = cs.getTypeChecker(); ProtocolDecl *protocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByBooleanLiteral); ProtocolDecl *builtinProtocol = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinBooleanLiteral); if (!protocol || !builtinProtocol) return nullptr; auto type = simplifyType(cs.getType(expr)); DeclName initName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_booleanLiteral }); DeclName builtinInitName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_builtinBooleanLiteral }); return convertLiteral( expr, type, cs.getType(expr), protocol, tc.Context.Id_BooleanLiteralType, initName, builtinProtocol, Type(BuiltinIntegerType::get(BuiltinIntegerWidth::fixed(1), tc.Context)), builtinInitName, nullptr, diag::boolean_literal_broken_proto, diag::builtin_boolean_literal_broken_proto); } Expr *handleStringLiteralExpr(LiteralExpr *expr) { if (cs.getType(expr) && !cs.getType(expr)->hasTypeVariable()) return expr; auto stringLiteral = dyn_cast(expr); auto magicLiteral = dyn_cast(expr); assert(bool(stringLiteral) != bool(magicLiteral) && "literal must be either a string literal or a magic literal"); auto type = simplifyType(cs.getType(expr)); auto &tc = cs.getTypeChecker(); bool isStringLiteral = true; bool isGraphemeClusterLiteral = false; ProtocolDecl *protocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByStringLiteral); if (!tc.conformsToProtocol(type, protocol, cs.DC, ConformanceCheckFlags::InExpression)) { // If the type does not conform to ExpressibleByStringLiteral, it should // be ExpressibleByExtendedGraphemeClusterLiteral. protocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByExtendedGraphemeClusterLiteral); isStringLiteral = false; isGraphemeClusterLiteral = true; } if (!tc.conformsToProtocol(type, protocol, cs.DC, ConformanceCheckFlags::InExpression)) { // ... or it should be ExpressibleByUnicodeScalarLiteral. protocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByUnicodeScalarLiteral); isStringLiteral = false; isGraphemeClusterLiteral = false; } // For type-sugar reasons, prefer the spelling of the default literal // type. if (auto defaultType = tc.getDefaultType(protocol, dc)) { if (defaultType->isEqual(type)) type = defaultType; } ProtocolDecl *builtinProtocol; Identifier literalType; DeclName literalFuncName; DeclName builtinLiteralFuncName; Diag<> brokenProtocolDiag; Diag<> brokenBuiltinProtocolDiag; if (isStringLiteral) { // If the string contains only ASCII, force a UTF8 representation bool forceASCII = stringLiteral != nullptr; if (forceASCII) { for (auto c: stringLiteral->getValue()) { if (c & (1 << 7)) { forceASCII = false; break; } } } literalType = tc.Context.Id_StringLiteralType; literalFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_stringLiteral }); // If the string contains non-ASCII and the type can handle // UTF-16 string literals, prefer them. builtinProtocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinUTF16StringLiteral); if (!forceASCII && (tc.conformsToProtocol( type, builtinProtocol, cs.DC, ConformanceCheckFlags::InExpression))) { builtinLiteralFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), {tc.Context.Id_builtinUTF16StringLiteral, tc.Context.getIdentifier("utf16CodeUnitCount")}); if (stringLiteral) stringLiteral->setEncoding(StringLiteralExpr::UTF16); else magicLiteral->setStringEncoding(StringLiteralExpr::UTF16); } else { // Otherwise, fall back to UTF-8. builtinProtocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinStringLiteral); builtinLiteralFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_builtinStringLiteral, tc.Context.getIdentifier("utf8CodeUnitCount"), tc.Context.getIdentifier("isASCII") }); if (stringLiteral) stringLiteral->setEncoding(StringLiteralExpr::UTF8); else magicLiteral->setStringEncoding(StringLiteralExpr::UTF8); } brokenProtocolDiag = diag::string_literal_broken_proto; brokenBuiltinProtocolDiag = diag::builtin_string_literal_broken_proto; } else if (isGraphemeClusterLiteral) { literalType = tc.Context.Id_ExtendedGraphemeClusterLiteralType; literalFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), {tc.Context.Id_extendedGraphemeClusterLiteral}); builtinLiteralFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_builtinExtendedGraphemeClusterLiteral, tc.Context.getIdentifier("utf8CodeUnitCount"), tc.Context.getIdentifier("isASCII") }); builtinProtocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinExtendedGraphemeClusterLiteral); brokenProtocolDiag = diag::extended_grapheme_cluster_literal_broken_proto; brokenBuiltinProtocolDiag = diag::builtin_extended_grapheme_cluster_literal_broken_proto; auto *builtinUTF16ExtendedGraphemeClusterProtocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinUTF16ExtendedGraphemeClusterLiteral); if (tc.conformsToProtocol(type, builtinUTF16ExtendedGraphemeClusterProtocol, cs.DC, ConformanceCheckFlags::InExpression)) { builtinLiteralFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_builtinExtendedGraphemeClusterLiteral, tc.Context.getIdentifier("utf16CodeUnitCount") }); builtinProtocol = builtinUTF16ExtendedGraphemeClusterProtocol; brokenBuiltinProtocolDiag = diag::builtin_utf16_extended_grapheme_cluster_literal_broken_proto; if (stringLiteral) stringLiteral->setEncoding(StringLiteralExpr::UTF16); else magicLiteral->setStringEncoding(StringLiteralExpr::UTF16); } } else { // Otherwise, we should have just one Unicode scalar. literalType = tc.Context.Id_UnicodeScalarLiteralType; literalFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), {tc.Context.Id_unicodeScalarLiteral}); builtinLiteralFuncName = DeclName(tc.Context, DeclBaseName::createConstructor(), {tc.Context.Id_builtinUnicodeScalarLiteral}); builtinProtocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByBuiltinUnicodeScalarLiteral); brokenProtocolDiag = diag::unicode_scalar_literal_broken_proto; brokenBuiltinProtocolDiag = diag::builtin_unicode_scalar_literal_broken_proto; stringLiteral->setEncoding(StringLiteralExpr::OneUnicodeScalar); } return convertLiteralInPlace(expr, type, protocol, literalType, literalFuncName, builtinProtocol, builtinLiteralFuncName, brokenProtocolDiag, brokenBuiltinProtocolDiag); } Expr *visitStringLiteralExpr(StringLiteralExpr *expr) { return handleStringLiteralExpr(expr); } Expr * visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *expr) { // Figure out the string type we're converting to. auto openedType = cs.getType(expr); auto type = simplifyType(openedType); cs.setType(expr, type); // Find the string interpolation protocol we need. auto &tc = cs.getTypeChecker(); auto interpolationProto = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByStringInterpolation); assert(interpolationProto && "Missing string interpolation protocol?"); DeclName name(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_stringInterpolation }); auto member = findNamedWitnessImpl( tc, dc, type, interpolationProto, name, diag::interpolation_broken_proto); DeclName segmentName(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_stringInterpolationSegment }); auto segmentMember = findNamedWitnessImpl( tc, dc, type, interpolationProto, segmentName, diag::interpolation_broken_proto); if (!member || !segmentMember || !isa(member.getDecl()) || !isa(segmentMember.getDecl())) return nullptr; // Build a reference to the init(stringInterpolation:) initializer. // FIXME: This location info is bogus. auto *typeRef = TypeExpr::createImplicitHack(expr->getStartLoc(), type, tc.Context); Expr *memberRef = new (tc.Context) MemberRefExpr(typeRef, expr->getStartLoc(), member.getDecl(), DeclNameLoc(expr->getStartLoc()), /*Implicit=*/true); cs.cacheSubExprTypes(memberRef); cs.setSubExprTypes(memberRef); bool failed = tc.typeCheckExpressionShallow(memberRef, cs.DC); cs.cacheExprTypes(memberRef); assert(!failed && "Could not reference string interpolation witness"); (void)failed; // Create a tuple containing all of the segments. SmallVector segments; SmallVector names; ConstraintLocatorBuilder locatorBuilder(cs.getConstraintLocator(expr)); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; for (auto segment : expr->getSegments()) { ApplyExpr *apply = CallExpr::createImplicit( tc.Context, typeRef, { segment }, { tc.Context.Id_stringInterpolationSegment }, getType); cs.cacheSubExprTypes(apply); Expr *convertedSegment = apply; cs.setSubExprTypes(convertedSegment); if (tc.typeCheckExpressionShallow(convertedSegment, cs.DC)) continue; cs.cacheExprTypes(convertedSegment); segments.push_back(convertedSegment); if (names.empty()) { names.push_back(tc.Context.Id_stringInterpolation); } else { names.push_back(Identifier()); } } // If all of the segments had errors, bail out. if (segments.empty()) return nullptr; // Call the init(stringInterpolation:) initializer with the arguments. ApplyExpr *apply = CallExpr::createImplicit(tc.Context, memberRef, segments, names, getType); cs.cacheExprTypes(apply); expr->setSemanticExpr(finishApply(apply, openedType, locatorBuilder)); return expr; } Expr *visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *expr) { switch (expr->getKind()) { case MagicIdentifierLiteralExpr::File: case MagicIdentifierLiteralExpr::Function: return handleStringLiteralExpr(expr); case MagicIdentifierLiteralExpr::Line: case MagicIdentifierLiteralExpr::Column: return handleIntegerLiteralExpr(expr); case MagicIdentifierLiteralExpr::DSOHandle: return expr; } llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch."); } Expr *visitObjectLiteralExpr(ObjectLiteralExpr *expr) { if (cs.getType(expr) && !cs.getType(expr)->hasTypeVariable()) return expr; auto &ctx = cs.getASTContext(); auto &tc = cs.getTypeChecker(); // Figure out the type we're converting to. auto openedType = cs.getType(expr); auto type = simplifyType(openedType); cs.setType(expr, type); if (type->is()) return expr; Type conformingType = type; if (auto baseType = conformingType->getOptionalObjectType()) { // The type may be optional due to a failable initializer in the // protocol. conformingType = baseType; } // Find the appropriate object literal protocol. auto proto = tc.getLiteralProtocol(expr); assert(proto && "Missing object literal protocol?"); auto conformance = tc.conformsToProtocol(conformingType, proto, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "object literal type conforms to protocol"); Expr *base = TypeExpr::createImplicitHack(expr->getLoc(), conformingType, ctx); cs.cacheExprTypes(base); SmallVector args; if (!isa(expr->getArg())) return nullptr; auto tupleArg = cast(expr->getArg()); for (auto elt : tupleArg->getElements()) { cs.setExprTypes(elt); args.push_back(elt); } DeclName constrName(tc.getObjectLiteralConstructorName(expr)); cs.cacheExprTypes(base); cs.setExprTypes(base); Expr *semanticExpr = tc.callWitness(base, dc, proto, *conformance, constrName, args, diag::object_literal_broken_proto); if (semanticExpr) cs.cacheExprTypes(semanticExpr); expr->setSemanticExpr(semanticExpr); return expr; } // Add a forced unwrap of an expression which either has type Optional // or is a function that returns an Optional. The latter turns into a // conversion expression that we will hoist above the ApplyExpr // that needs to be forced during the process of rewriting the expression. // // forForcedOptional is used to indicate that we will further need // to hoist this result above an explicit force of an optional that is // in place for something like an @optional protocol member from // Objective C that we might otherwise mistake for the thing we mean to // force here. Expr *forceUnwrapResult(Expr *expr, bool forForcedOptional =false) { auto ty = simplifyType(cs.getType(expr)); if (forForcedOptional) ty = ty->getOptionalObjectType(); if (auto *fnTy = ty->getAs()) { auto underlyingType = cs.replaceFinalResultTypeWithUnderlying(fnTy); auto &ctx = cs.getTypeChecker().Context; return cs.cacheType(new (ctx) ImplicitlyUnwrappedFunctionConversionExpr( expr, underlyingType)); } else { return coerceImplicitlyUnwrappedOptionalToValue( expr, ty->getWithoutSpecifierType()->getOptionalObjectType()); } } bool shouldForceUnwrapResult(OverloadChoice choice, ConstraintLocatorBuilder locator) { if (!choice.isImplicitlyUnwrappedValueOrReturnValue()) return false; auto *choiceLocator = cs.getConstraintLocator(locator.withPathElement( ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice)); return solution.getDisjunctionChoice(choiceLocator); } Expr *forceUnwrapIfExpected(Expr *expr, OverloadChoice choice, ConstraintLocatorBuilder locator, bool forForcedOptional = false) { if (!shouldForceUnwrapResult(choice, locator)) return expr; // Force the expression if required for the solution. return forceUnwrapResult(expr, forForcedOptional); } Expr *visitDeclRefExpr(DeclRefExpr *expr) { auto locator = cs.getConstraintLocator(expr); // Find the overload choice used for this declaration reference. auto selected = solution.getOverloadChoiceIfAvailable(locator); if (!selected.hasValue()) { auto *varDecl = cast(expr->getDecl()); assert(varDecl->getType()->is() && "should only happen for closure arguments in CSDiags"); cs.setType(expr, varDecl->getType()); return expr; } return buildDeclRef(selected->choice, expr->getNameLoc(), selected->openedFullType, locator, expr->isImplicit(), expr->getFunctionRefKind(), expr->getAccessSemantics()); } Expr *visitSuperRefExpr(SuperRefExpr *expr) { simplifyExprType(expr); return expr; } Expr *visitTypeExpr(TypeExpr *expr) { auto toType = simplifyType(cs.getType(expr->getTypeLoc())); expr->getTypeLoc().setType(toType); cs.setType(expr, MetatypeType::get(toType)); return expr; } Expr *visitOtherConstructorDeclRefExpr(OtherConstructorDeclRefExpr *expr) { cs.setType(expr, expr->getDecl()->getInitializerInterfaceType()); return expr; } Expr *visitDotSyntaxBaseIgnoredExpr(DotSyntaxBaseIgnoredExpr *expr) { return simplifyExprType(expr); } Expr *visitOverloadedDeclRefExpr(OverloadedDeclRefExpr *expr) { // Determine the declaration selected for this overloaded reference. auto locator = cs.getConstraintLocator(expr); auto selected = solution.getOverloadChoice(locator); auto choice = selected.choice; return buildDeclRef(choice, expr->getNameLoc(), selected.openedFullType, locator, expr->isImplicit(), choice.getFunctionRefKind(), AccessSemantics::Ordinary); } Expr *visitUnresolvedDeclRefExpr(UnresolvedDeclRefExpr *expr) { // FIXME: We should have generated an overload set from this, in which // case we can emit a typo-correction error here but recover well. return nullptr; } Expr *visitUnresolvedSpecializeExpr(UnresolvedSpecializeExpr *expr) { // Our specializations should have resolved the subexpr to the right type. return expr->getSubExpr(); } Expr *visitMemberRefExpr(MemberRefExpr *expr) { auto memberLocator = cs.getConstraintLocator(expr, ConstraintLocator::Member); auto selected = solution.getOverloadChoice(memberLocator); bool isDynamic = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic; return buildMemberRef( expr->getBase(), selected.openedFullType, expr->getDotLoc(), selected.choice, expr->getNameLoc(), selected.openedType, cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(), selected.choice.getFunctionRefKind(), expr->getAccessSemantics(), isDynamic); } Expr *visitDynamicMemberRefExpr(DynamicMemberRefExpr *expr) { llvm_unreachable("already type-checked?"); } Expr *visitUnresolvedMemberExpr(UnresolvedMemberExpr *expr) { // Dig out the type of the base, which will be the result type of this // expression. If constraint solving resolved this to an UnresolvedType, // then we're in an ambiguity tolerant mode used for diagnostic // generation. Just leave this as an unresolved member reference. Type resultTy = simplifyType(cs.getType(expr)); if (resultTy->getRValueType()->is()) { cs.setType(expr, resultTy); return expr; } Type baseTy = resultTy->getRValueType(); auto &tc = cs.getTypeChecker(); // Find the selected member. auto memberLocator = cs.getConstraintLocator( expr, ConstraintLocator::UnresolvedMember); auto selected = solution.getOverloadChoice(memberLocator); // If the member came by optional unwrapping, then unwrap the base type. if (selected.choice.getKind() == OverloadChoiceKind::DeclViaUnwrappedOptional) { baseTy = baseTy->getOptionalObjectType(); assert(baseTy && "got unwrapped optional decl from non-optional base?!"); } // The base expression is simply the metatype of the base type. // FIXME: This location info is bogus. auto base = TypeExpr::createImplicitHack(expr->getDotLoc(), baseTy, tc.Context); cs.cacheExprTypes(base); // Build the member reference. bool isDynamic = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic; auto result = buildMemberRef( base, selected.openedFullType, expr->getDotLoc(), selected.choice, expr->getNameLoc(), selected.openedType, cs.getConstraintLocator(expr), memberLocator, expr->isImplicit(), selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary, isDynamic); if (!result) return nullptr; auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; // If there was an argument, apply it. if (auto arg = expr->getArgument()) { ApplyExpr *apply = CallExpr::create( tc.Context, result, arg, expr->getArgumentLabels(), expr->getArgumentLabelLocs(), expr->hasTrailingClosure(), /*implicit=*/expr->isImplicit(), Type(), getType); result = finishApply(apply, Type(), cs.getConstraintLocator(expr)); } return coerceToType(result, resultTy, cs.getConstraintLocator(expr)); } private: /// A list of "suspicious" optional injections that come from /// forced downcasts. SmallVector SuspiciousOptionalInjections; public: /// A list of optional injections that have been diagnosed. llvm::SmallPtrSet DiagnosedOptionalInjections; private: /// Create a member reference to the given constructor. Expr *applyCtorRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc, DeclNameLoc nameLoc, bool implicit, ConstraintLocator *ctorLocator, OverloadChoice choice, FunctionRefKind functionRefKind, Type openedType) { auto *ctor = cast(choice.getDecl()); // If the subexpression is a metatype, build a direct reference to the // constructor. if (cs.getType(base)->is()) { return buildMemberRef( base, openedType, dotLoc, choice, nameLoc, cs.getType(expr), ConstraintLocatorBuilder(cs.getConstraintLocator(expr)), ctorLocator, implicit, functionRefKind, AccessSemantics::Ordinary, /*isDynamic=*/false); } // The subexpression must be either 'self' or 'super'. if (!base->isSuperExpr()) { // 'super' references have already been fully checked; handle the // 'self' case below. auto &tc = cs.getTypeChecker(); bool diagnoseBadInitRef = true; auto arg = base->getSemanticsProvidingExpr(); if (auto dre = dyn_cast(arg)) { if (dre->getDecl()->getFullName() == cs.getASTContext().Id_self) { // We have a reference to 'self'. diagnoseBadInitRef = false; // Special case -- in a protocol extension initializer with a class // constrainted Self type, 'self' has archetype type, and only // required initializers can be called. if (cs.getType(dre)->getRValueType()->is()) { if (!diagnoseInvalidDynamicConstructorReferences(cs, base, nameLoc, ctor, SuppressDiagnostics)) return nullptr; } // Make sure the reference to 'self' occurs within an initializer. if (!dyn_cast_or_null( cs.DC->getInnermostMethodContext())) { if (!SuppressDiagnostics) tc.diagnose(dotLoc, diag::init_delegation_outside_initializer); return nullptr; } } } // If we need to diagnose this as a bad reference to an initializer, // do so now. if (diagnoseBadInitRef) { // Determine whether 'super' would have made sense as a base. bool hasSuper = false; if (auto func = cs.DC->getInnermostMethodContext()) { if (auto classDecl = func->getDeclContext()->getSelfClassDecl()) { hasSuper = classDecl->hasSuperclass(); } } if (SuppressDiagnostics) return nullptr; tc.diagnose(dotLoc, diag::bad_init_ref_base, hasSuper); } } // Build a partial application of the delegated initializer. Expr *ctorRef = buildOtherConstructorRef(openedType, ctor, base, nameLoc, ctorLocator, implicit); auto *call = new (cs.getASTContext()) DotSyntaxCallExpr(ctorRef, dotLoc, base); return finishApply(call, cs.getType(expr), ConstraintLocatorBuilder( cs.getConstraintLocator(expr))); } Expr *applyMemberRefExpr(Expr *expr, Expr *base, SourceLoc dotLoc, DeclNameLoc nameLoc, bool implicit) { // If we have a constructor member, handle it as a constructor. auto ctorLocator = cs.getConstraintLocator( expr, ConstraintLocator::ConstructorMember); if (auto selected = solution.getOverloadChoiceIfAvailable(ctorLocator)) { auto choice = selected->choice; return applyCtorRefExpr( expr, base, dotLoc, nameLoc, implicit, ctorLocator, choice, choice.getFunctionRefKind(), selected->openedFullType); } // Determine the declaration selected for this overloaded reference. auto memberLocator = cs.getConstraintLocator(expr, ConstraintLocator::Member); auto selectedElt = solution.getOverloadChoiceIfAvailable(memberLocator); if (!selectedElt) { // If constraint solving resolved this to an UnresolvedType, then we're // in an ambiguity tolerant mode used for diagnostic generation. Just // leave this as whatever type of member reference it already is. Type resultTy = simplifyType(cs.getType(expr)); cs.setType(expr, resultTy); return expr; } auto selected = *selectedElt; if (!selected.choice.getBaseType()) { // This is one of the "outer alternatives", meaning the innermost // methods didn't work out. // // The only way to get here is via an UnresolvedDotExpr with outer // alternatives. auto UDE = cast(expr); cs.diagnoseDeprecatedConditionalConformanceOuterAccess( UDE, selected.choice.getDecl()); return buildDeclRef(selected.choice, nameLoc, selected.openedFullType, memberLocator, implicit, selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary); } switch (selected.choice.getKind()) { case OverloadChoiceKind::DeclViaBridge: { base = cs.coerceToRValue(base); // Look through an implicitly unwrapped optional. auto baseTy = cs.getType(base); auto &tc = cs.getTypeChecker(); auto &ctx = tc.Context; auto baseMetaTy = baseTy->getAs(); auto baseInstTy = (baseMetaTy ? baseMetaTy->getInstanceType() : baseTy); auto classTy = ctx.getBridgedToObjC(cs.DC, baseInstTy); if (baseMetaTy) { // FIXME: We're dropping side effects in the base here! base = TypeExpr::createImplicitHack(base->getLoc(), classTy, tc.Context); cs.cacheExprTypes(base); } else { // Bridge the base to its corresponding Objective-C object. base = bridgeToObjectiveC(base, classTy); } // Fall through to build the member reference. LLVM_FALLTHROUGH; } case OverloadChoiceKind::Decl: case OverloadChoiceKind::DeclViaUnwrappedOptional: case OverloadChoiceKind::DeclViaDynamic: { bool isDynamic = selected.choice.getKind() == OverloadChoiceKind::DeclViaDynamic; return buildMemberRef(base, selected.openedFullType, dotLoc, selected.choice, nameLoc, selected.openedType, cs.getConstraintLocator(expr), memberLocator, implicit, selected.choice.getFunctionRefKind(), AccessSemantics::Ordinary, isDynamic); } case OverloadChoiceKind::TupleIndex: { Type toType = simplifyType(cs.getType(expr)); auto baseTy = cs.getType(base); // If the base type is not a tuple l-value, access to // its elements supposed to be r-value as well. // // This is modeled in constraint system in a way // that when member type is resolved by `resolveOverload` // it would take r-value type of the element at // specified index, but if it's a type variable it // could still be bound to l-value later. if (!baseTy->is()) toType = toType->getRValueType(); // If the result type is an rvalue and the base contains lvalues, // need a full tuple coercion to properly load & set access kind // on all underlying elements before taking a single element. if (!toType->hasLValueType() && baseTy->hasLValueType()) base = coerceToType(base, baseTy->getRValueType(), cs.getConstraintLocator(base)); return cs.cacheType(new (cs.getASTContext()) TupleElementExpr(base, dotLoc, selected.choice.getTupleIndex(), nameLoc.getBaseNameLoc(), toType)); } case OverloadChoiceKind::BaseType: return base; case OverloadChoiceKind::KeyPathApplication: llvm_unreachable("should only happen in a subscript"); case OverloadChoiceKind::DynamicMemberLookup: { // Application of a DynamicMemberLookup result turns a member access of // x.foo into x[dynamicMember: "foo"]. auto &ctx = cs.getASTContext(); auto loc = nameLoc.getStartLoc(); // Figure out the expected type of the string. We know the // openedFullType will be "xType -> indexType -> resultType". Dig out // its index type. auto declTy = solution.simplifyType(selected.openedFullType); auto subscriptTy = declTy->castTo()->getResult(); auto refFnType = subscriptTy->castTo(); assert(refFnType->getParams().size() == 1 && "subscript always has one arg"); auto stringType = refFnType->getParams()[0].getPlainType(); auto tupleTy = TupleType::get(TupleTypeElt(stringType, ctx.Id_dynamicMember), ctx); // Build and type check the string literal index value to the specific // string type expected by the subscript. auto fieldName = selected.choice.getName().getBaseIdentifier().str(); auto index = getDMLIndexExpr(fieldName, tupleTy, loc, dc, cs); // Build and return a subscript that uses this string as the index. return buildSubscript(base, index, ctx.Id_dynamicMember, /*trailingClosure*/false, cs.getConstraintLocator(expr), /*isImplicit*/false, AccessSemantics::Ordinary, selected); } } llvm_unreachable("Unhandled OverloadChoiceKind in switch."); } public: Expr *visitUnresolvedDotExpr(UnresolvedDotExpr *expr) { return applyMemberRefExpr(expr, expr->getBase(), expr->getDotLoc(), expr->getNameLoc(), expr->isImplicit()); } Expr *visitSequenceExpr(SequenceExpr *expr) { llvm_unreachable("Expression wasn't parsed?"); } Expr *visitArrowExpr(ArrowExpr *expr) { llvm_unreachable("Arrow expr wasn't converted to type?"); } Expr *visitIdentityExpr(IdentityExpr *expr) { cs.setType(expr, cs.getType(expr->getSubExpr())); return expr; } Expr *visitAnyTryExpr(AnyTryExpr *expr) { cs.setType(expr, cs.getType(expr->getSubExpr())); return expr; } Expr *visitOptionalTryExpr(OptionalTryExpr *expr) { return simplifyExprType(expr); } Expr *visitParenExpr(ParenExpr *expr) { auto &ctx = cs.getASTContext(); auto pty = cs.getType(expr->getSubExpr()); cs.setType(expr, ParenType::get(ctx, pty->getInOutObjectType(), ParameterTypeFlags().withInOut(pty->is()))); return expr; } Expr *visitTupleExpr(TupleExpr *expr) { return simplifyExprType(expr); } Expr *visitSubscriptExpr(SubscriptExpr *expr) { return buildSubscript(expr->getBase(), expr->getIndex(), expr->getArgumentLabels(), expr->hasTrailingClosure(), cs.getConstraintLocator(expr), expr->isImplicit(), expr->getAccessSemantics()); } /// "Finish" an array expression by filling in the semantic expression. ArrayExpr *finishArrayExpr(ArrayExpr *expr) { Type arrayTy = cs.getType(expr); auto &tc = cs.getTypeChecker(); ProtocolDecl *arrayProto = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByArrayLiteral); assert(arrayProto && "type-checked array literal w/o protocol?!"); auto conformance = tc.conformsToProtocol(arrayTy, arrayProto, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "Type does not conform to protocol?"); // Call the witness that builds the array literal. // FIXME: callWitness() may end up re-doing some work we already did // to convert the array literal elements to the element type. It would // be nicer to re-use them. // FIXME: This location info is bogus. Expr *typeRef = TypeExpr::createImplicitHack(expr->getLoc(), arrayTy, tc.Context); cs.cacheExprTypes(typeRef); DeclName name(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_arrayLiteral }); // Coerce the array elements to be rvalues, so that other type-checker // code that attempts to peephole the AST doesn't have to re-load the // elements (and break the invariant that lvalue nodes only get their // access kind set once). for (auto &element : expr->getElements()) { element = cs.coerceToRValue(element); } // Restructure the argument to provide the appropriate labels in the // tuple. SmallVector typeElements; SmallVector names; bool first = true; for (auto elt : expr->getElements()) { if (first) { typeElements.push_back(TupleTypeElt(cs.getType(elt), tc.Context.Id_arrayLiteral)); names.push_back(tc.Context.Id_arrayLiteral); first = false; continue; } typeElements.push_back(cs.getType(elt)); names.push_back(Identifier()); } Type argType = TupleType::get(typeElements, tc.Context); assert(isa(argType.getPointer())); Expr *arg = TupleExpr::create(tc.Context, SourceLoc(), expr->getElements(), names, { }, SourceLoc(), /*HasTrailingClosure=*/false, /*Implicit=*/true, argType); cs.cacheExprTypes(arg); cs.setExprTypes(typeRef); cs.setExprTypes(arg); Expr *result = tc.callWitness(typeRef, dc, arrayProto, *conformance, name, arg, diag::array_protocol_broken); if (!result) return nullptr; cs.cacheExprTypes(result); expr->setSemanticExpr(result); return expr; } Expr *visitArrayExpr(ArrayExpr *expr) { Type openedType = cs.getType(expr); Type arrayTy = simplifyType(openedType); cs.setType(expr, arrayTy); if (!finishArrayExpr(expr)) return nullptr; // If the array element type was defaulted, note that in the expression. if (solution.DefaultedConstraints.count(cs.getConstraintLocator(expr))) expr->setIsTypeDefaulted(); return expr; } /// "Finish" a dictionary expression by filling in the semantic expression. DictionaryExpr *finishDictionaryExpr(DictionaryExpr *expr) { Type dictionaryTy = cs.getType(expr); auto &tc = cs.getTypeChecker(); ProtocolDecl *dictionaryProto = tc.getProtocol(expr->getLoc(), KnownProtocolKind::ExpressibleByDictionaryLiteral); auto conformance = tc.conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC, ConformanceCheckFlags::InExpression); if (!conformance) return nullptr; // Call the witness that builds the dictionary literal. // FIXME: callWitness() may end up re-doing some work we already did // to convert the dictionary literal elements to the (key, value) tuple. // It would be nicer to re-use them. // FIXME: Cache the name. // FIXME: This location info is bogus. Expr *typeRef = TypeExpr::createImplicitHack(expr->getLoc(), dictionaryTy, tc.Context); cs.cacheExprTypes(typeRef); DeclName name(tc.Context, DeclBaseName::createConstructor(), { tc.Context.Id_dictionaryLiteral }); // Restructure the argument to provide the appropriate labels in the // tuple. SmallVector typeElements; SmallVector names; bool first = true; for (auto elt : expr->getElements()) { if (first) { typeElements.push_back(TupleTypeElt(cs.getType(elt), tc.Context.Id_dictionaryLiteral)); names.push_back(tc.Context.Id_dictionaryLiteral); first = false; continue; } typeElements.push_back(cs.getType(elt)); names.push_back(Identifier()); } Type argType = TupleType::get(typeElements, tc.Context); assert(isa(argType.getPointer())); Expr *arg = TupleExpr::create(tc.Context, expr->getLBracketLoc(), expr->getElements(), names, { }, expr->getRBracketLoc(), /*HasTrailingClosure=*/false, /*Implicit=*/true, argType); cs.cacheExprTypes(arg); cs.setExprTypes(typeRef); cs.setExprTypes(arg); Expr *result = tc.callWitness(typeRef, dc, dictionaryProto, *conformance, name, arg, diag::dictionary_protocol_broken); if (!result) return nullptr; cs.cacheExprTypes(result); expr->setSemanticExpr(result); return expr; } Expr *visitDictionaryExpr(DictionaryExpr *expr) { Type openedType = cs.getType(expr); Type dictionaryTy = simplifyType(openedType); cs.setType(expr, dictionaryTy); if (!finishDictionaryExpr(expr)) return nullptr; // If the dictionary key or value type was defaulted, note that in the // expression. if (solution.DefaultedConstraints.count(cs.getConstraintLocator(expr))) expr->setIsTypeDefaulted(); return expr; } Expr *visitDynamicSubscriptExpr(DynamicSubscriptExpr *expr) { return buildSubscript(expr->getBase(), expr->getIndex(), expr->getArgumentLabels(), expr->hasTrailingClosure(), cs.getConstraintLocator(expr), expr->isImplicit(), AccessSemantics::Ordinary); } Expr *visitTupleElementExpr(TupleElementExpr *expr) { simplifyExprType(expr); return expr; } Expr *visitCaptureListExpr(CaptureListExpr *expr) { // The type of the capture list is the type of the closure contained // inside it. cs.setType(expr, cs.getType(expr->getClosureBody())); return expr; } Expr *visitClosureExpr(ClosureExpr *expr) { llvm_unreachable("Handled by the walker directly"); } Expr *visitAutoClosureExpr(AutoClosureExpr *expr) { llvm_unreachable("Already type-checked"); } Expr *visitInOutExpr(InOutExpr *expr) { auto objectTy = cs.getType(expr->getSubExpr())->getRValueType(); // The type is simply inout of whatever the lvalue's object type was. cs.setType(expr, InOutType::get(objectTy)); return expr; } Expr *visitVarargExpansionExpr(VarargExpansionExpr *expr) { simplifyExprType(expr); auto elementTy = cs.getType(expr); auto arrayTy = cs.getTypeChecker().getArraySliceType(expr->getLoc(), elementTy); if (!arrayTy) return expr; expr->setSubExpr(coerceToType(expr->getSubExpr(), arrayTy, cs.getConstraintLocator(expr))); return expr; } Expr *visitDynamicTypeExpr(DynamicTypeExpr *expr) { Expr *base = expr->getBase(); base = cs.coerceToRValue(base); expr->setBase(base); return simplifyExprType(expr); } Expr *visitOpaqueValueExpr(OpaqueValueExpr *expr) { llvm_unreachable("Already type-checked"); } Expr *visitApplyExpr(ApplyExpr *expr) { return finishApply(expr, cs.getType(expr), ConstraintLocatorBuilder( cs.getConstraintLocator(expr))); } Expr *visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *expr) { // A non-failable initializer cannot delegate to a failable // initializer. Expr *unwrappedSubExpr = expr->getSubExpr()->getSemanticsProvidingExpr(); Type valueTy = cs.getType(unwrappedSubExpr)->getOptionalObjectType(); auto inCtor = cast(cs.DC->getInnermostMethodContext()); if (valueTy && inCtor->getFailability() == OTK_None) { bool isChaining; auto *otherCtorRef = expr->getCalledConstructor(isChaining); ConstructorDecl *ctor = otherCtorRef->getDecl(); assert(ctor); // If the initializer we're calling is not declared as // checked, it's an error. bool isError = !ctor->getAttrs().hasAttribute(); // If we're suppressing diagnostics, just fail. if (isError && SuppressDiagnostics) return nullptr; auto &tc = cs.getTypeChecker(); auto &ctx = tc.Context; if (isError) { if (auto *optTry = dyn_cast(unwrappedSubExpr)) { tc.diagnose(optTry->getTryLoc(), diag::delegate_chain_nonoptional_to_optional_try, isChaining); tc.diagnose(optTry->getTryLoc(), diag::init_delegate_force_try) .fixItReplace({optTry->getTryLoc(), optTry->getQuestionLoc()}, "try!"); tc.diagnose(inCtor->getLoc(), diag::init_propagate_failure) .fixItInsertAfter(inCtor->getLoc(), "?"); } else { // Give the user the option of adding '!' or making the enclosing // initializer failable. tc.diagnose(otherCtorRef->getLoc(), diag::delegate_chain_nonoptional_to_optional, isChaining, ctor->getFullName()); tc.diagnose(otherCtorRef->getLoc(), diag::init_force_unwrap) .fixItInsertAfter(expr->getEndLoc(), "!"); tc.diagnose(inCtor->getLoc(), diag::init_propagate_failure) .fixItInsertAfter(inCtor->getLoc(), "?"); } } // Recover by injecting the force operation (the first option). Expr *newSub = new (ctx) ForceValueExpr(expr->getSubExpr(), expr->getEndLoc()); cs.setType(newSub, valueTy); newSub->setImplicit(); expr->setSubExpr(newSub); } return expr; } Expr *visitIfExpr(IfExpr *expr) { auto resultTy = simplifyType(cs.getType(expr)); cs.setType(expr, resultTy); // Convert the condition to a logic value. auto cond = solution.convertBooleanTypeToBuiltinI1(expr->getCondExpr(), cs.getConstraintLocator(expr)); expr->setCondExpr(cond); // Coerce the then/else branches to the common type. expr->setThenExpr(coerceToType(expr->getThenExpr(), resultTy, cs.getConstraintLocator(expr->getThenExpr()))); expr->setElseExpr(coerceToType(expr->getElseExpr(), resultTy, cs.getConstraintLocator(expr->getElseExpr()))); return expr; } Expr *visitImplicitConversionExpr(ImplicitConversionExpr *expr) { llvm_unreachable("Already type-checked"); } Expr *visitIsExpr(IsExpr *expr) { // Turn the subexpression into an rvalue. auto &tc = cs.getTypeChecker(); auto toType = simplifyType(cs.getType(expr->getCastTypeLoc())); auto sub = cs.coerceToRValue(expr->getSubExpr()); checkForImportedUsedConformances(toType); expr->setSubExpr(sub); // Set the type we checked against. expr->getCastTypeLoc().setType(toType); auto fromType = cs.getType(sub); auto castContextKind = SuppressDiagnostics ? CheckedCastContextKind::None : CheckedCastContextKind::IsExpr; auto castKind = tc.typeCheckCheckedCast( fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub, expr->getCastTypeLoc().getSourceRange()); switch (castKind) { case CheckedCastKind::Unresolved: expr->setCastKind(CheckedCastKind::ValueCast); break; case CheckedCastKind::Coercion: case CheckedCastKind::BridgingCoercion: // Check is trivially true. tc.diagnose(expr->getLoc(), diag::isa_is_always_true, "is"); expr->setCastKind(castKind); break; case CheckedCastKind::ValueCast: // Check the cast target is a non-foreign type if (auto cls = toType->getAs()) { if (cls->getDecl()->getForeignClassKind() == ClassDecl::ForeignKind::CFType) { tc.diagnose(expr->getLoc(), diag::isa_is_foreign_check, toType); } } expr->setCastKind(castKind); break; case CheckedCastKind::ArrayDowncast: case CheckedCastKind::DictionaryDowncast: case CheckedCastKind::SetDowncast: // Valid checks. expr->setCastKind(castKind); break; } // SIL-generation magically turns this into a Bool; make sure it can. if (!cs.getASTContext().getGetBoolDecl(&cs.getTypeChecker())) { tc.diagnose(expr->getLoc(), diag::bool_intrinsics_not_found); // Continue anyway. } // Dig through the optionals in the from/to types. SmallVector fromOptionals; fromType->lookThroughAllOptionalTypes(fromOptionals); SmallVector toOptionals; toType->lookThroughAllOptionalTypes(toOptionals); // If we have an imbalance of optionals or a collection // downcast, handle this as a checked cast followed by a // a 'hasValue' check. if (fromOptionals.size() != toOptionals.size() || castKind == CheckedCastKind::ArrayDowncast || castKind == CheckedCastKind::DictionaryDowncast || castKind == CheckedCastKind::SetDowncast) { auto toOptType = OptionalType::get(toType); ConditionalCheckedCastExpr *cast = new (tc.Context) ConditionalCheckedCastExpr( sub, expr->getLoc(), SourceLoc(), TypeLoc::withoutLoc(toType)); cs.setType(cast, toOptType); cs.setType(cast->getCastTypeLoc(), toType); if (expr->isImplicit()) cast->setImplicit(); // Type-check this conditional case. Expr *result = handleConditionalCheckedCastExpr(cast, true); if (!result) return nullptr; // Extract a Bool from the resulting expression. return solution.convertOptionalToBool(result, cs.getConstraintLocator(expr)); } return expr; } /// The kind of cast we're working with for handling optional bindings. enum class OptionalBindingsCastKind { /// An explicit bridging conversion, spelled "as". Bridged, /// A forced cast, spelled "as!". Forced, /// A conditional cast, spelled "as?". Conditional, }; /// Handle optional operands and results in an explicit cast. Expr *handleOptionalBindingsForCast(ExplicitCastExpr *cast, Type finalResultType, OptionalBindingsCastKind castKind) { return handleOptionalBindings(cast->getSubExpr(), finalResultType, castKind, [&](Expr *sub, Type resultType) -> Expr* { // Complain about conditional casts to CF class types; they can't // actually be conditionally checked. if (castKind == OptionalBindingsCastKind::Conditional) { Type destValueType = resultType->getOptionalObjectType(); auto destObjectType = destValueType; if (auto metaTy = destObjectType->getAs()) destObjectType = metaTy->getInstanceType(); if (auto destClass = destObjectType->getClassOrBoundGenericClass()) { if (destClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType) { if (SuppressDiagnostics) return nullptr; auto &tc = cs.getTypeChecker(); tc.diagnose(cast->getLoc(), diag::conditional_downcast_foreign, destValueType); ConcreteDeclRef refDecl = sub->getReferencedDecl(); if (refDecl) { tc.diagnose(cast->getLoc(), diag::note_explicitly_compare_cftypeid, refDecl.getDecl()->getBaseName(), destValueType); } } } } // Set the expression as the sub-expression of the cast, then // use the cast as the inner operation. cast->setSubExpr(sub); cs.setType(cast, resultType); return cast; }); } /// A helper function to build an operation. The inner result type /// is the expected type of the operation; it will be a non-optional /// type unless the castKind is Conditional. using OperationBuilderRef = llvm::function_ref; /// Handle optional operands and results in an explicit cast. Expr *handleOptionalBindings(Expr *subExpr, Type finalResultType, OptionalBindingsCastKind castKind, OperationBuilderRef buildInnerOperation) { auto &tc = cs.getTypeChecker(); unsigned destExtraOptionals; bool forceExtraSourceOptionals; switch (castKind) { case OptionalBindingsCastKind::Bridged: destExtraOptionals = 0; forceExtraSourceOptionals = true; break; case OptionalBindingsCastKind::Forced: destExtraOptionals = 0; forceExtraSourceOptionals = true; break; case OptionalBindingsCastKind::Conditional: destExtraOptionals = 1; forceExtraSourceOptionals = false; break; } // FIXME: some of this work needs to be delayed until runtime to // properly account for archetypes dynamically being optional // types. For example, if we're casting T to NSView?, that // should succeed if T=NSObject? and its value is actually nil. Type srcType = cs.getType(subExpr); SmallVector srcOptionals; srcType = srcType->lookThroughAllOptionalTypes(srcOptionals); SmallVector destOptionals; auto destValueType = finalResultType->lookThroughAllOptionalTypes(destOptionals); auto isBridgeToAnyObject = castKind == OptionalBindingsCastKind::Bridged && destValueType->isAnyObject(); // If the destination value type is 'AnyObject' when performing a // bridging operation, or if the destination value type could dynamically // be an optional type, leave any extra optionals on the source in place. if (isBridgeToAnyObject || destValueType->canDynamicallyBeOptionalType( /* includeExistential */ false)) { auto destOptionalsCount = destOptionals.size() - destExtraOptionals; if (srcOptionals.size() > destOptionalsCount) { srcType = srcOptionals[destOptionalsCount]; srcOptionals.erase(srcOptionals.begin() + destOptionalsCount, srcOptionals.end()); } } // When performing a bridging operation, if the destination type // is more optional than the source, we'll add extra optional injections // at the end. SmallVector destOptionalInjections; if (castKind == OptionalBindingsCastKind::Bridged && destOptionals.size() > srcOptionals.size()) { // Remove the extra optionals from destOptionals, but keep them around // separately so we can perform the injections on the final result of // the cast. auto cutPoint = destOptionals.end() - srcOptionals.size(); destOptionalInjections.append(destOptionals.begin(), cutPoint); destOptionals.erase(destOptionals.begin(), cutPoint); finalResultType = destOptionals.empty() ? destValueType : destOptionals.front(); } // Local function to add the optional injections to final result. auto addFinalOptionalInjections = [&](Expr *result) { for (auto destType : reversed(destOptionalInjections)) { result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(result, destType)); } return result; }; // There's nothing special to do if the operand isn't optional // and we don't need any bridging. if (srcOptionals.empty()) { Expr *result = buildInnerOperation(subExpr, finalResultType); if (!result) return nullptr; return addFinalOptionalInjections(result); } // The result type (without the final optional) is a subtype of // the operand type, so it will never have a higher depth. assert(destOptionals.size() - destExtraOptionals <= srcOptionals.size()); // The outermost N levels of optionals on the operand must all // be present or the cast fails. The innermost M levels of // optionals on the operand are reflected in the requested // destination type, so we should map these nils into the result. unsigned numRequiredOptionals = srcOptionals.size() - (destOptionals.size() - destExtraOptionals); // The number of OptionalEvaluationExprs between the point of the // inner cast and the enclosing OptionalEvaluationExpr (exclusive) // which represents failure for the entire operation. unsigned failureDepth = destOptionals.size() - destExtraOptionals; // Drill down on the operand until it's non-optional. SourceLoc fakeQuestionLoc = subExpr->getEndLoc(); for (unsigned i : indices(srcOptionals)) { Type valueType = (i + 1 == srcOptionals.size() ? srcType : srcOptionals[i+1]); // As we move into the range of mapped optionals, start // lowering the depth. unsigned depth = failureDepth; if (i >= numRequiredOptionals) { depth -= (i - numRequiredOptionals) + 1; } else if (forceExtraSourceOptionals) { // For a forced cast, force the required optionals. subExpr = new (tc.Context) ForceValueExpr(subExpr, fakeQuestionLoc); cs.setType(subExpr, valueType); subExpr->setImplicit(true); continue; } subExpr = cs.cacheType(new (tc.Context) BindOptionalExpr(subExpr, fakeQuestionLoc, depth, valueType)); subExpr->setImplicit(true); } // If this is a conditional cast, the result type will always // have at least one level of optional, which should become the // type of the checked-cast expression. Expr *result; if (castKind == OptionalBindingsCastKind::Conditional) { assert(!destOptionals.empty() && "result of checked cast is not an optional type"); result = buildInnerOperation(subExpr, destOptionals.back()); } else { result = buildInnerOperation(subExpr, destValueType); } if (!result) return nullptr; // If we're casting to an optional type, we need to capture the // final M bindings. if (destOptionals.size() > destExtraOptionals) { if (castKind == OptionalBindingsCastKind::Conditional) { // If the innermost cast fails, the entire expression fails. To // get this behavior, we have to bind and then re-inject the result. // (SILGen should know how to peephole this.) result = cs.cacheType(new (tc.Context) BindOptionalExpr(result, result->getEndLoc(), failureDepth, destValueType)); result->setImplicit(true); } for (unsigned i = destOptionals.size(); i != 0; --i) { Type destType = destOptionals[i-1]; result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(result, destType)); result = cs.cacheType(new (tc.Context) OptionalEvaluationExpr(result, destType)); } // Otherwise, we just need to capture the failure-depth binding. } else if (!forceExtraSourceOptionals) { result = cs.cacheType(new (tc.Context) OptionalEvaluationExpr(result, finalResultType)); } return addFinalOptionalInjections(result); } bool hasForcedOptionalResult(ExplicitCastExpr *expr) { auto *TR = expr->getCastTypeLoc().getTypeRepr(); if (TR && TR->getKind() == TypeReprKind::ImplicitlyUnwrappedOptional) { auto *locator = cs.getConstraintLocator( expr, ConstraintLocator::ImplicitlyUnwrappedDisjunctionChoice); return solution.getDisjunctionChoice(locator); } return false; } Expr *visitCoerceExpr(CoerceExpr *expr) { // If we need to insert a force-unwrap for coercions of the form // 'as T!', do so now. if (hasForcedOptionalResult(expr)) { auto *coerced = visitCoerceExpr(expr, None); if (!coerced) return nullptr; return coerceImplicitlyUnwrappedOptionalToValue( coerced, cs.getType(coerced)->getOptionalObjectType()); } return visitCoerceExpr(expr, None); } Expr *visitCoerceExpr(CoerceExpr *expr, Optional choice) { // Simplify the type we're casting to. auto toType = simplifyType(cs.getType(expr->getCastTypeLoc())); expr->getCastTypeLoc().setType(toType); checkForImportedUsedConformances(toType); auto &tc = cs.getTypeChecker(); // Since this is literal initialization, we don't // really need to keep wrapping coercion around. if (expr->isLiteralInit()) { auto *literalInit = expr->getSubExpr(); // If literal got converted into constructor call // lets put proper source information in place. if (auto *call = dyn_cast(literalInit)) { call->getFn()->forEachChildExpr([&](Expr *subExpr) -> Expr * { auto *TE = dyn_cast(subExpr); if (!TE) return subExpr; auto type = TE->getInstanceType( [&](const Expr *expr) { return cs.hasType(expr); }, [&](const Expr *expr) { return cs.getType(expr); }); assert(!type->hasError()); if (!type->isEqual(toType)) return subExpr; return cs.cacheType(new (tc.Context) TypeExpr(expr->getCastTypeLoc())); }); } literalInit->setImplicit(false); return literalInit; } // Turn the subexpression into an rvalue. auto rvalueSub = cs.coerceToRValue(expr->getSubExpr()); expr->setSubExpr(rvalueSub); // If we weren't explicitly told by the caller which disjunction choice, // get it from the solution to determine whether we've picked a coercion // or a bridging conversion. auto *locator = cs.getConstraintLocator(expr); if (!choice) { choice = solution.getDisjunctionChoice(locator); } // Handle the coercion/bridging of the underlying subexpression, where // optionality has been removed. if (*choice == 0) { // Convert the subexpression. Expr *sub = expr->getSubExpr(); cs.setExprTypes(sub); if (tc.convertToType(sub, toType, cs.DC)) return nullptr; cs.cacheExprTypes(sub); expr->setSubExpr(sub); cs.setType(expr, toType); return expr; } // Bridging conversion. assert(*choice == 1 && "should be bridging"); // Handle optional bindings. Expr *sub = handleOptionalBindings(expr->getSubExpr(), toType, OptionalBindingsCastKind::Bridged, [&](Expr *sub, Type toInstanceType) { return buildObjCBridgeExpr(sub, toInstanceType, locator); }); if (!sub) return nullptr; expr->setSubExpr(sub); cs.setType(expr, toType); return expr; } // Rewrite ForcedCheckedCastExpr based on what the solver computed. Expr *visitForcedCheckedCastExpr(ForcedCheckedCastExpr *expr) { // Simplify the type we're casting to. auto toType = simplifyType(cs.getType(expr->getCastTypeLoc())); if (hasForcedOptionalResult(expr)) toType = toType->getOptionalObjectType(); expr->getCastTypeLoc().setType(toType); checkForImportedUsedConformances(toType); // The subexpression is always an rvalue. auto &tc = cs.getTypeChecker(); auto sub = cs.coerceToRValue(expr->getSubExpr()); expr->setSubExpr(sub); auto castContextKind = SuppressDiagnostics ? CheckedCastContextKind::None : CheckedCastContextKind::ForcedCast; auto fromType = cs.getType(sub); auto castKind = tc.typeCheckCheckedCast( fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub, expr->getCastTypeLoc().getSourceRange()); switch (castKind) { /// Invalid cast. case CheckedCastKind::Unresolved: return nullptr; case CheckedCastKind::Coercion: case CheckedCastKind::BridgingCoercion: { if (SuppressDiagnostics) return nullptr; if (cs.getType(sub)->isEqual(toType)) { tc.diagnose(expr->getLoc(), diag::forced_downcast_noop, toType) .fixItRemove(SourceRange(expr->getLoc(), expr->getCastTypeLoc().getSourceRange().End)); } else { tc.diagnose(expr->getLoc(), diag::forced_downcast_coercion, cs.getType(sub), toType) .fixItReplace(SourceRange(expr->getLoc(), expr->getExclaimLoc()), "as"); } // Transmute the checked cast into a coercion expression. auto *result = new (tc.Context) CoerceExpr(sub, expr->getLoc(), expr->getCastTypeLoc()); cs.setType(result, toType); cs.setType(result->getCastTypeLoc(), toType); unsigned disjunctionChoice = (castKind == CheckedCastKind::Coercion ? 0 : 1); return visitCoerceExpr(result, disjunctionChoice); } // Valid casts. case CheckedCastKind::ArrayDowncast: case CheckedCastKind::DictionaryDowncast: case CheckedCastKind::SetDowncast: case CheckedCastKind::ValueCast: expr->setCastKind(castKind); break; } return handleOptionalBindingsForCast(expr, simplifyType(cs.getType(expr)), OptionalBindingsCastKind::Forced); } Expr *visitConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr) { // If we need to insert a force-unwrap for coercions of the form // 'as! T!', do so now. if (hasForcedOptionalResult(expr)) { auto *coerced = handleConditionalCheckedCastExpr(expr); if (!coerced) return nullptr; return coerceImplicitlyUnwrappedOptionalToValue( coerced, cs.getType(coerced)->getOptionalObjectType()); } return handleConditionalCheckedCastExpr(expr); } Expr *handleConditionalCheckedCastExpr(ConditionalCheckedCastExpr *expr, bool isInsideIsExpr = false) { // Simplify the type we're casting to. auto toType = simplifyType(cs.getType(expr->getCastTypeLoc())); checkForImportedUsedConformances(toType); expr->getCastTypeLoc().setType(toType); // The subexpression is always an rvalue. auto &tc = cs.getTypeChecker(); auto sub = cs.coerceToRValue(expr->getSubExpr()); expr->setSubExpr(sub); auto castContextKind = (SuppressDiagnostics || isInsideIsExpr) ? CheckedCastContextKind::None : CheckedCastContextKind::ConditionalCast; auto fromType = cs.getType(sub); auto castKind = tc.typeCheckCheckedCast( fromType, toType, castContextKind, cs.DC, expr->getLoc(), sub, expr->getCastTypeLoc().getSourceRange()); switch (castKind) { /// Invalid cast. case CheckedCastKind::Unresolved: expr->setCastKind(CheckedCastKind::ValueCast); break; case CheckedCastKind::Coercion: case CheckedCastKind::BridgingCoercion: { if (SuppressDiagnostics) return nullptr; tc.diagnose(expr->getLoc(), diag::conditional_downcast_coercion, cs.getType(sub), toType); // Transmute the checked cast into a coercion expression. auto *coerce = new (tc.Context) CoerceExpr(sub, expr->getLoc(), expr->getCastTypeLoc()); cs.setType(coerce, toType); cs.setType(coerce->getCastTypeLoc(), toType); unsigned disjunctionChoice = (castKind == CheckedCastKind::Coercion ? 0 : 1); Expr *result = visitCoerceExpr(coerce, disjunctionChoice); if (!result) return nullptr; // Wrap the result in an optional. Mark the optional injection as // explicit, because the user did in fact write the '?' as part of // 'as?', even though it wasn't necessary. result = new (tc.Context) InjectIntoOptionalExpr( result, OptionalType::get(toType)); result->setImplicit(false); return cs.cacheType(result); } // Valid casts. case CheckedCastKind::ArrayDowncast: case CheckedCastKind::DictionaryDowncast: case CheckedCastKind::SetDowncast: case CheckedCastKind::ValueCast: expr->setCastKind(castKind); break; } return handleOptionalBindingsForCast(expr, simplifyType(cs.getType(expr)), OptionalBindingsCastKind::Conditional); } Expr *visitAssignExpr(AssignExpr *expr) { // Convert the source to the simplified destination type. auto destTy = simplifyType(cs.getType(expr->getDest())); auto locator = ConstraintLocatorBuilder(cs.getConstraintLocator(expr->getSrc())); Expr *src = coerceToType(expr->getSrc(), destTy->getRValueType(), locator); if (!src) return nullptr; expr->setSrc(src); if (!SuppressDiagnostics) { // If we're performing an assignment to a weak or unowned variable from // a constructor call, emit a warning that the instance will be // immediately deallocated. diagnoseUnownedImmediateDeallocation(cs.getTypeChecker(), expr); } return expr; } Expr *visitDiscardAssignmentExpr(DiscardAssignmentExpr *expr) { return simplifyExprType(expr); } Expr *visitUnresolvedPatternExpr(UnresolvedPatternExpr *expr) { // If we end up here, we should have diagnosed somewhere else // already. Expr *simplified = simplifyExprType(expr); if (!SuppressDiagnostics && !cs.getType(simplified)->is()) { cs.TC.diagnose(simplified->getLoc(), diag::pattern_in_expr, expr->getSubPattern()->getKind()); } return simplified; } Expr *visitBindOptionalExpr(BindOptionalExpr *expr) { return simplifyExprType(expr); } Expr *visitOptionalEvaluationExpr(OptionalEvaluationExpr *expr) { Type optType = simplifyType(cs.getType(expr)); // If this is an optional chain that isn't chaining anything, and if the // subexpression is already optional (not IUO), then this is a noop: // reject it. This avoids confusion of the model (where the programmer // thought it was doing something) and keeps pointless ?'s out of the // code. if (!SuppressDiagnostics) if (auto *Bind = dyn_cast( expr->getSubExpr()->getSemanticsProvidingExpr())) { if (cs.getType(Bind->getSubExpr())->isEqual(optType)) cs.TC.diagnose(expr->getLoc(), diag::optional_chain_noop, optType).fixItRemove(Bind->getQuestionLoc()); else cs.TC.diagnose(expr->getLoc(), diag::optional_chain_isnt_chaining); } Expr *subExpr = coerceToType(expr->getSubExpr(), optType, cs.getConstraintLocator(expr)); if (!subExpr) return nullptr; expr->setSubExpr(subExpr); cs.setType(expr, optType); return expr; } Expr *visitForceValueExpr(ForceValueExpr *expr) { // Check to see if we are forcing an // ImplicitlyUnwrappedFunctionConversionExpr. This can happen // in cases where we had a ForceValueExpr of an optional for a // declaration for a function whose result type we need to // implicitly force after applying. We need to hoist the function // conversion above the ForceValueExpr, so that we may ultimately // hoist it above the ApplyExpr where we will eventually rewrite the // function conversion into a force of the result. Expr *replacement = expr; if (auto fnConv = dyn_cast(expr->getSubExpr())) { auto fnConvSubExpr = fnConv->getSubExpr(); auto fnConvSubObjTy = cs.getType(fnConvSubExpr)->getOptionalObjectType(); cs.setType(expr, fnConvSubObjTy); expr->setSubExpr(fnConvSubExpr); fnConv->setSubExpr(expr); replacement = fnConv; } Type valueType = simplifyType(cs.getType(expr)); cs.setType(expr, valueType); // Coerce the object type, if necessary. auto subExpr = expr->getSubExpr(); if (auto objectTy = cs.getType(subExpr)->getOptionalObjectType()) { if (objectTy && !objectTy->isEqual(valueType)) { auto coercedSubExpr = coerceToType(subExpr, OptionalType::get(valueType), cs.getConstraintLocator(subExpr)); expr->setSubExpr(coercedSubExpr); } } return replacement; } Expr *visitOpenExistentialExpr(OpenExistentialExpr *expr) { llvm_unreachable("Already type-checked"); } Expr *visitMakeTemporarilyEscapableExpr(MakeTemporarilyEscapableExpr *expr){ llvm_unreachable("Already type-checked"); } Expr *visitKeyPathApplicationExpr(KeyPathApplicationExpr *expr){ // This should already be type-checked, but we may have had to re- // check it for failure diagnosis. return simplifyExprType(expr); } Expr *visitEnumIsCaseExpr(EnumIsCaseExpr *expr) { // Should already be type-checked. return simplifyExprType(expr); } Expr *visitLazyInitializerExpr(LazyInitializerExpr *expr) { simplifyExprType(expr); assert(expr->getType()->isEqual(expr->getSubExpr()->getType())); return expr; } Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) { simplifyExprType(E); auto valueType = cs.getType(E); auto &tc = cs.getTypeChecker(); auto &ctx = tc.Context; // Synthesize a call to _undefined() of appropriate type. FuncDecl *undefinedDecl = ctx.getUndefinedDecl(&tc); if (!undefinedDecl) { tc.diagnose(E->getLoc(), diag::missing_undefined_runtime); return nullptr; } DeclRefExpr *fnRef = new (ctx) DeclRefExpr(undefinedDecl, DeclNameLoc(), /*Implicit=*/true); fnRef->setFunctionRefKind(FunctionRefKind::SingleApply); StringRef msg = "attempt to evaluate editor placeholder"; Expr *argExpr = new (ctx) StringLiteralExpr(msg, E->getLoc(), /*implicit*/true); Expr *callExpr = CallExpr::createImplicit(ctx, fnRef, { argExpr }, { Identifier() }); auto resultTy = tc.typeCheckExpression( callExpr, cs.DC, TypeLoc::withoutLoc(valueType), CTP_CannotFail); assert(resultTy && "Conversion cannot fail!"); (void)resultTy; cs.cacheExprTypes(callExpr); E->setSemanticExpr(callExpr); return E; } Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) { // Dig out the reference to a declaration. Expr *subExpr = E->getSubExpr(); ValueDecl *foundDecl = nullptr; while (subExpr) { // Declaration reference. if (auto declRef = dyn_cast(subExpr)) { foundDecl = declRef->getDecl(); break; } // Constructor reference. if (auto ctorRef = dyn_cast(subExpr)) { foundDecl = ctorRef->getDecl(); break; } // Member reference. if (auto memberRef = dyn_cast(subExpr)) { foundDecl = memberRef->getMember().getDecl(); break; } // Dynamic member reference. if (auto dynMemberRef = dyn_cast(subExpr)) { foundDecl = dynMemberRef->getMember().getDecl(); break; } // Look through parentheses. if (auto paren = dyn_cast(subExpr)) { subExpr = paren->getSubExpr(); continue; } // Look through "a.b" to "b". if (auto dotSyntax = dyn_cast(subExpr)) { subExpr = dotSyntax->getRHS(); continue; } // Look through self-rebind expression. if (auto rebindSelf = dyn_cast(subExpr)) { subExpr = rebindSelf->getSubExpr(); continue; } // Look through optional binding within the monadic "?". if (auto bind = dyn_cast(subExpr)) { subExpr = bind->getSubExpr(); continue; } // Look through optional evaluation of the monadic "?". if (auto optEval = dyn_cast(subExpr)) { subExpr = optEval->getSubExpr(); continue; } // Look through an implicit force-value. if (auto force = dyn_cast(subExpr)) { subExpr = force->getSubExpr(); continue; } // Look through implicit open-existential operations. if (auto open = dyn_cast(subExpr)) { if (open->isImplicit()) { subExpr = open->getSubExpr(); continue; } break; } // Look to the referenced member in a self-application. if (auto selfApply = dyn_cast(subExpr)) { subExpr = selfApply->getFn(); continue; } // Look through implicit conversions. if (auto conversion = dyn_cast(subExpr)) { subExpr = conversion->getSubExpr(); continue; } // Look through explicit coercions. if (auto coercion = dyn_cast(subExpr)) { subExpr = coercion->getSubExpr(); continue; } break; } if (!subExpr) return nullptr; // If we didn't find any declaration at all, we're stuck. auto &tc = cs.getTypeChecker(); if (!foundDecl) { tc.diagnose(E->getLoc(), diag::expr_selector_no_declaration) .highlight(subExpr->getSourceRange()); return E; } // Check whether we found an entity that #selector could refer to. // If we found a method or initializer, check it. AbstractFunctionDecl *method = nullptr; if (auto func = dyn_cast(foundDecl)) { // Methods and initializers. // If this isn't a method, complain. if (!func->getDeclContext()->isTypeContext()) { tc.diagnose(E->getLoc(), diag::expr_selector_not_method, func->getDeclContext()->isModuleScopeContext(), func->getFullName()) .highlight(subExpr->getSourceRange()); tc.diagnose(func, diag::decl_declared_here, func->getFullName()); return E; } // Check that we requested a method. switch (E->getSelectorKind()) { case ObjCSelectorExpr::Method: break; case ObjCSelectorExpr::Getter: case ObjCSelectorExpr::Setter: // Complain that we cannot ask for the getter or setter of a // method. tc.diagnose(E->getModifierLoc(), diag::expr_selector_expected_property, E->getSelectorKind() == ObjCSelectorExpr::Setter, foundDecl->getDescriptiveKind(), foundDecl->getFullName()) .fixItRemoveChars(E->getModifierLoc(), E->getSubExpr()->getStartLoc()); // Update the AST to reflect the fix. E->overrideObjCSelectorKind(ObjCSelectorExpr::Method, SourceLoc()); break; } // Note the method we're referring to. method = func; } else if (auto var = dyn_cast(foundDecl)) { // Properties. maybeAddAccessorsToStorage(tc, var); // If this isn't a property on a type, complain. if (!var->getDeclContext()->isTypeContext()) { tc.diagnose(E->getLoc(), diag::expr_selector_not_property, isa(var), var->getFullName()) .highlight(subExpr->getSourceRange()); tc.diagnose(var, diag::decl_declared_here, var->getFullName()); return E; } // Check that we requested a property getter or setter. switch (E->getSelectorKind()) { case ObjCSelectorExpr::Method: { bool isSettable = var->isSettable(cs.DC) && var->isSetterAccessibleFrom(cs.DC); auto primaryDiag = tc.diagnose(E->getLoc(), diag::expr_selector_expected_method, isSettable, var->getFullName()); primaryDiag.highlight(subExpr->getSourceRange()); // The point at which we will insert the modifier. SourceLoc modifierLoc = E->getSubExpr()->getStartLoc(); // If the property is settable, we don't know whether the // user wanted the getter or setter. Provide notes for each. if (isSettable) { // Flush the primary diagnostic. We have notes to add. primaryDiag.flush(); // Add notes for the getter and setter, respectively. tc.diagnose(modifierLoc, diag::expr_selector_add_modifier, false, var->getFullName()) .fixItInsert(modifierLoc, "getter: "); tc.diagnose(modifierLoc, diag::expr_selector_add_modifier, true, var->getFullName()) .fixItInsert(modifierLoc, "setter: "); // Bail out now. We don't know what the user wanted, so // don't fill in the details. return E; } // The property is non-settable, so add "getter:". primaryDiag.fixItInsert(modifierLoc, "getter: "); E->overrideObjCSelectorKind(ObjCSelectorExpr::Getter, modifierLoc); method = var->getGetter(); break; } case ObjCSelectorExpr::Getter: method = var->getGetter(); break; case ObjCSelectorExpr::Setter: // Make sure we actually have a setter. if (!var->isSettable(cs.DC)) { tc.diagnose(E->getLoc(), diag::expr_selector_property_not_settable, var->getDescriptiveKind(), var->getFullName()); tc.diagnose(var, diag::decl_declared_here, var->getFullName()); return E; } // Make sure the setter is accessible. if (!var->isSetterAccessibleFrom(cs.DC)) { tc.diagnose(E->getLoc(), diag::expr_selector_property_setter_inaccessible, var->getDescriptiveKind(), var->getFullName()); tc.diagnose(var, diag::decl_declared_here, var->getFullName()); return E; } method = var->getSetter(); break; } } else { // Cannot reference with #selector. tc.diagnose(E->getLoc(), diag::expr_selector_no_declaration) .highlight(subExpr->getSourceRange()); tc.diagnose(foundDecl, diag::decl_declared_here, foundDecl->getFullName()); return E; } assert(method && "Didn't find a method?"); // The declaration we found must be exposed to Objective-C. tc.validateDecl(method); if (!method->isObjC()) { tc.diagnose(E->getLoc(), diag::expr_selector_not_objc, foundDecl->getDescriptiveKind(), foundDecl->getFullName()) .highlight(subExpr->getSourceRange()); tc.diagnose(foundDecl, diag::make_decl_objc, foundDecl->getDescriptiveKind()) .fixItInsert(foundDecl->getAttributeInsertionLoc(false), "@objc "); return E; } else if (auto attr = foundDecl->getAttrs().getAttribute()) { // If this attribute was inferred based on deprecated Swift 3 rules, // complain. if (attr->isSwift3Inferred() && tc.Context.LangOpts.WarnSwift3ObjCInference == Swift3ObjCInferenceWarnings::Minimal) { tc.diagnose(E->getLoc(), diag::expr_selector_swift3_objc_inference, foundDecl->getDescriptiveKind(), foundDecl->getFullName(), foundDecl->getDeclContext() ->getSelfNominalTypeDecl() ->getName()) .highlight(subExpr->getSourceRange()); tc.diagnose(foundDecl, diag::make_decl_objc, foundDecl->getDescriptiveKind()) .fixItInsert(foundDecl->getAttributeInsertionLoc(false), "@objc "); } } // Note which method we're referencing. E->setMethod(method); return E; } private: // Key path components we need to SmallVector, 4> KeyPathSubscriptComponents; public: Expr *visitKeyPathExpr(KeyPathExpr *E) { if (E->isObjC()) { cs.setType(E, cs.getType(E->getObjCStringLiteralExpr())); return E; } simplifyExprType(E); if (cs.getType(E)->hasError()) return E; // If a component is already resolved, then all of them should be // resolved, and we can let the expression be. This might happen when // re-checking a failed system for diagnostics. if (!E->getComponents().empty() && E->getComponents().front().isResolved()) { assert([&]{ for (auto &c : E->getComponents()) if (!c.isResolved()) return false; return true; }()); return E; } SmallVector resolvedComponents; // Resolve each of the components. bool didOptionalChain = false; auto keyPathTy = cs.getType(E)->castTo(); Type baseTy = keyPathTy->getGenericArgs()[0]; Type leafTy = keyPathTy->getGenericArgs()[1]; for (unsigned i : indices(E->getComponents())) { auto &origComponent = E->getMutableComponents()[i]; // If there were unresolved types, we may end up with a null base for // following components. if (!baseTy) { resolvedComponents.push_back(origComponent); continue; } auto getObjectType = [](Type optionalTy) -> Type { Type objectTy; if (auto lvalue = optionalTy->getAs()) { objectTy = lvalue->getObjectType()->getOptionalObjectType(); if (optionalTy->hasUnresolvedType() && !objectTy) { objectTy = optionalTy; } objectTy = LValueType::get(objectTy); } else { objectTy = optionalTy->getOptionalObjectType(); if (optionalTy->hasUnresolvedType() && !objectTy) { objectTy = optionalTy; } } assert(objectTy); return objectTy; }; auto kind = origComponent.getKind(); Optional foundDecl; auto locator = cs.getConstraintLocator(E, ConstraintLocator::PathElement::getKeyPathComponent(i)); if (kind == KeyPathExpr::Component::Kind::UnresolvedSubscript) { locator = cs.getConstraintLocator(locator, ConstraintLocator::SubscriptMember); } // If this is an unresolved link, make sure we resolved it. if (kind == KeyPathExpr::Component::Kind::UnresolvedProperty || kind == KeyPathExpr::Component::Kind::UnresolvedSubscript) { foundDecl = solution.getOverloadChoiceIfAvailable(locator); // Leave the component unresolved if the overload was not resolved. if (foundDecl) { // If this was a @dynamicMemberLookup property, then we actually // form a subscript reference, so switch the kind. if (foundDecl->choice.getKind() == OverloadChoiceKind::DynamicMemberLookup) { kind = KeyPathExpr::Component::Kind::UnresolvedSubscript; } } } KeyPathExpr::Component component; switch (kind) { case KeyPathExpr::Component::Kind::UnresolvedProperty: { // If we couldn't resolve the component, leave it alone. if (!foundDecl) { component = origComponent; break; } auto property = foundDecl->choice.getDecl(); // Key paths can only refer to properties currently. if (!isa(property)) { cs.TC.diagnose(origComponent.getLoc(), diag::expr_keypath_not_property, property->getDescriptiveKind(), property->getFullName()); } else { // Key paths don't work with mutating-get properties. auto varDecl = cast(property); if (varDecl->isGetterMutating()) { cs.TC.diagnose(origComponent.getLoc(), diag::expr_keypath_mutating_getter, property->getFullName()); } // Key paths don't currently support static members. if (varDecl->isStatic()) { cs.TC.diagnose(origComponent.getLoc(), diag::expr_keypath_static_member, property->getFullName()); } } cs.TC.requestMemberLayout(property); auto dc = property->getInnermostDeclContext(); // Compute substitutions to refer to the member. SubstitutionMap subs = solution.computeSubstitutions(dc->getGenericSignatureOfContext(), locator); auto resolvedTy = foundDecl->openedType; resolvedTy = simplifyType(resolvedTy); auto ref = ConcreteDeclRef(property, subs); component = KeyPathExpr::Component::forProperty(ref, resolvedTy, origComponent.getLoc()); baseTy = component.getComponentType(); resolvedComponents.push_back(component); if (shouldForceUnwrapResult(foundDecl->choice, locator)) { auto objectTy = getObjectType(baseTy); auto loc = origComponent.getLoc(); component = KeyPathExpr::Component::forOptionalForce(objectTy, loc); baseTy = component.getComponentType(); resolvedComponents.push_back(component); } break; } case KeyPathExpr::Component::Kind::UnresolvedSubscript: { // Leave the component unresolved if the overload was not resolved. if (!foundDecl) { component = origComponent; break; } auto subscript = cast(foundDecl->choice.getDecl()); if (subscript->isGetterMutating()) { cs.TC.diagnose(origComponent.getLoc(), diag::expr_keypath_mutating_getter, subscript->getFullName()); } cs.TC.requestMemberLayout(subscript); auto dc = subscript->getInnermostDeclContext(); // FIXME: It's not correct to turn the subscript's parameter list // into a single type here. Further down we pass it to coerceToType(), // but the rules for argument list conversions are different than // tuple conversions, and coerceToType() doesn't handle varargs or // default arguments. auto indexType = AnyFunctionType::composeInput( cs.TC.Context, subscript->getInterfaceType() ->castTo() ->getParams(), /*canonicalVararg=*/false); SubstitutionMap subs; if (auto sig = dc->getGenericSignatureOfContext()) { // Compute substitutions to refer to the member. subs = solution.computeSubstitutions(sig, locator); indexType = indexType.subst(subs); } // If this is a @dynamicMemberLookup reference to resolve a property // through the subscript(dynamicMember:) member, restore the // openedType and origComponent to its full reference as if the user // wrote out the subscript manually. if (foundDecl->choice.getKind() == OverloadChoiceKind::DynamicMemberLookup) { foundDecl->openedType = foundDecl->openedFullType ->castTo()->getResult(); auto &ctx = cs.TC.Context; auto loc = origComponent.getLoc(); auto fieldName = foundDecl->choice.getName().getBaseIdentifier().str(); auto index = getDMLIndexExpr(fieldName, indexType, loc, dc, cs); origComponent = KeyPathExpr::Component:: forUnresolvedSubscript(ctx, loc, index, {}, loc, loc, /*trailingClosure*/nullptr); cs.setType(origComponent.getIndexExpr(), index->getType()); } auto resolvedTy = foundDecl->openedType->castTo() ->getResult(); resolvedTy = simplifyType(resolvedTy); auto ref = ConcreteDeclRef(subscript, subs); // Coerce the indices to the type the subscript expects. auto indexExpr = coerceToType(origComponent.getIndexExpr(), indexType, locator); component = KeyPathExpr::Component ::forSubscriptWithPrebuiltIndexExpr(ref, indexExpr, origComponent.getSubscriptLabels(), resolvedTy, origComponent.getLoc(), {}); // Save a reference to the component so we can do a post-pass to check // the Hashable conformance of the indexes. KeyPathSubscriptComponents.push_back({E, resolvedComponents.size()}); baseTy = component.getComponentType(); resolvedComponents.push_back(component); if (shouldForceUnwrapResult(foundDecl->choice, locator)) { auto objectTy = getObjectType(baseTy); auto loc = origComponent.getLoc(); component = KeyPathExpr::Component::forOptionalForce(objectTy, loc); baseTy = component.getComponentType(); resolvedComponents.push_back(component); } break; } case KeyPathExpr::Component::Kind::OptionalChain: { didOptionalChain = true; // Chaining always forces the element to be an rvalue. auto objectTy = baseTy->getWithoutSpecifierType()->getOptionalObjectType(); if (baseTy->hasUnresolvedType() && !objectTy) { objectTy = baseTy; } assert(objectTy); auto loc = origComponent.getLoc(); component = KeyPathExpr::Component::forOptionalChain(objectTy, loc); baseTy = component.getComponentType(); resolvedComponents.push_back(component); break; } case KeyPathExpr::Component::Kind::OptionalForce: { auto objectTy = getObjectType(baseTy); auto loc = origComponent.getLoc(); component = KeyPathExpr::Component::forOptionalForce(objectTy, loc); baseTy = component.getComponentType(); resolvedComponents.push_back(component); break; } case KeyPathExpr::Component::Kind::Invalid: component = origComponent; component.setComponentType(leafTy); baseTy = component.getComponentType(); resolvedComponents.push_back(component); break; case KeyPathExpr::Component::Kind::Property: case KeyPathExpr::Component::Kind::Subscript: case KeyPathExpr::Component::Kind::OptionalWrap: llvm_unreachable("already resolved"); } } // Wrap a non-optional result if there was chaining involved. if (didOptionalChain && baseTy && !baseTy->hasUnresolvedType() && !baseTy->getWithoutSpecifierType()->isEqual(leafTy)) { assert(leafTy->getOptionalObjectType()->isEqual( baseTy->getWithoutSpecifierType())); auto component = KeyPathExpr::Component::forOptionalWrap(leafTy); resolvedComponents.push_back(component); baseTy = leafTy; } E->resolveComponents(cs.getASTContext(), resolvedComponents); // See whether there's an equivalent ObjC key path string we can produce // for interop purposes. if (cs.getASTContext().LangOpts.EnableObjCInterop) { SmallString<64> compatStringBuf; if (buildObjCKeyPathString(E, compatStringBuf)) { auto stringCopy = cs.getASTContext().AllocateCopy(compatStringBuf.begin(), compatStringBuf.end()); auto stringExpr = new (cs.getASTContext()) StringLiteralExpr( StringRef(stringCopy, compatStringBuf.size()), SourceRange(), /*implicit*/ true); cs.setType(stringExpr, cs.getType(E)); E->setObjCStringLiteralExpr(stringExpr); } } // The final component type ought to line up with the leaf type of the // key path. assert(!baseTy || baseTy->hasUnresolvedType() || baseTy->getWithoutSpecifierType()->isEqual(leafTy)); return E; } Expr *visitKeyPathDotExpr(KeyPathDotExpr *E) { llvm_unreachable("found KeyPathDotExpr in CSApply"); } /// Interface for ExprWalker void walkToExprPre(Expr *expr) { ExprStack.push_back(expr); } Expr *walkToExprPost(Expr *expr) { Expr *result = visit(expr); // Mark any _ObjectiveCBridgeable conformances as 'used'. if (result) { useObjectiveCBridgeableConformances(cs.DC, cs.getType(result)); } assert(expr == ExprStack.back()); ExprStack.pop_back(); return result; } void finalize(Expr *&result) { assert(ExprStack.empty()); assert(OpenedExistentials.empty()); auto &tc = cs.getTypeChecker(); // Look at all of the suspicious optional injections for (auto injection : SuspiciousOptionalInjections) { // If we already diagnosed this injection, we're done. if (DiagnosedOptionalInjections.count(injection)) { continue; } auto *cast = findForcedDowncast(tc.Context, injection->getSubExpr()); if (!cast) continue; if (isa(injection->getSubExpr())) continue; tc.diagnose(injection->getLoc(), diag::inject_forced_downcast, cs.getType(injection->getSubExpr())->getRValueType()); auto exclaimLoc = cast->getExclaimLoc(); tc.diagnose(exclaimLoc, diag::forced_to_conditional_downcast, cs.getType(injection)->getOptionalObjectType()) .fixItReplace(exclaimLoc, "?"); tc.diagnose(cast->getStartLoc(), diag::silence_inject_forced_downcast) .fixItInsert(cast->getStartLoc(), "(") .fixItInsertAfter(cast->getEndLoc(), ")"); } // Look at key path subscript components to verify that they're hashable. for (auto componentRef : KeyPathSubscriptComponents) { auto &component = componentRef.first ->getMutableComponents()[componentRef.second]; // We need to be able to hash the captured index values in order for // KeyPath itself to be hashable, so check that all of the subscript // index components are hashable and collect their conformances here. SmallVector hashables; bool allIndexesHashable = true; ArrayRef indexTypes; TupleTypeElt singleIndexTypeBuf; if (auto tup = cs.getType(component.getIndexExpr()) ->getAs()) { indexTypes = tup->getElements(); } else { singleIndexTypeBuf = cs.getType(component.getIndexExpr()); indexTypes = singleIndexTypeBuf; } auto hashable = cs.getASTContext().getProtocol(KnownProtocolKind::Hashable); auto equatable = cs.getASTContext().getProtocol(KnownProtocolKind::Equatable); for (auto indexType : indexTypes) { auto conformance = cs.TC.conformsToProtocol(indexType.getType(), hashable, cs.DC, (ConformanceCheckFlags::Used| ConformanceCheckFlags::InExpression)); if (!conformance) { cs.TC.diagnose(component.getIndexExpr()->getLoc(), diag::expr_keypath_subscript_index_not_hashable, indexType.getType()); allIndexesHashable = false; continue; } hashables.push_back(*conformance); // FIXME: Hashable implies Equatable, but we need to make sure the // Equatable conformance is forced into existence during type checking // so that it's available for SILGen. auto eqConformance = cs.TC.conformsToProtocol(indexType.getType(), equatable, cs.DC, (ConformanceCheckFlags::Used| ConformanceCheckFlags::InExpression)); assert(eqConformance.hasValue()); (void)eqConformance; } if (allIndexesHashable) { component.setSubscriptIndexHashableConformances(hashables); } } // Set the final types on the expression. cs.setExprTypes(result); } /// Diagnose an optional injection that is probably not what the /// user wanted, because it comes from a forced downcast. void diagnoseOptionalInjection(InjectIntoOptionalExpr *injection) { // Check whether we have a forced downcast. auto &tc = cs.getTypeChecker(); auto *cast = findForcedDowncast(tc.Context, injection->getSubExpr()); if (!cast) return; SuspiciousOptionalInjections.push_back(injection); } }; } // end anonymous namespace /// Resolve a locator to the specific declaration it references, if possible. /// /// \param cs The constraint system in which the locator will be resolved. /// /// \param locator The locator to resolve. /// /// \param findOvlChoice A function that searches for the overload choice /// associated with the given locator, or an empty optional if there is no such /// overload. /// /// \returns the decl to which the locator resolved. /// static ConcreteDeclRef resolveLocatorToDecl( ConstraintSystem &cs, ConstraintLocator *locator, llvm::function_ref(ConstraintLocator *)> findOvlChoice, llvm::function_ref getConcreteDeclRef) { assert(locator && "Null locator"); if (!locator->getAnchor()) return ConcreteDeclRef(); auto anchor = locator->getAnchor(); // Unwrap any specializations, constructor calls, implicit conversions, and // '.'s. // FIXME: This is brittle. do { if (auto specialize = dyn_cast(anchor)) { anchor = specialize->getSubExpr(); continue; } if (auto implicit = dyn_cast(anchor)) { anchor = implicit->getSubExpr(); continue; } if (auto identity = dyn_cast(anchor)) { anchor = identity->getSubExpr(); continue; } if (auto tryExpr = dyn_cast(anchor)) { if (isa(tryExpr)) break; anchor = tryExpr->getSubExpr(); continue; } if (auto selfApply = dyn_cast(anchor)) { anchor = selfApply->getFn(); continue; } if (auto dotSyntax = dyn_cast(anchor)) { anchor = dotSyntax->getRHS(); continue; } if (auto *OEE = dyn_cast(anchor)) { anchor = OEE->getSubExpr(); continue; } break; } while (true); // Simple case: direct reference to a declaration. if (auto dre = dyn_cast(anchor)) return dre->getDeclRef(); // Simple case: direct reference to a declaration. if (auto mre = dyn_cast(anchor)) return mre->getMember(); if (auto ctorRef = dyn_cast(anchor)) return ctorRef->getDeclRef(); if (isa(anchor) || isa(anchor)) { // Overloaded and unresolved cases: find the resolved overload. auto anchorLocator = cs.getConstraintLocator(anchor); if (auto selected = findOvlChoice(anchorLocator)) { if (selected->choice.isDecl()) return getConcreteDeclRef(selected->choice.getDecl(), selected->openedType, anchorLocator); } } if (isa(anchor)) { // Unresolved member: find the resolved overload. auto anchorLocator = cs.getConstraintLocator(anchor, ConstraintLocator::UnresolvedMember); if (auto selected = findOvlChoice(anchorLocator)) { if (selected->choice.isDecl()) return getConcreteDeclRef(selected->choice.getDecl(), selected->openedType, anchorLocator); } } if (isa(anchor)) { // Unresolved member: find the resolved overload. auto anchorLocator = cs.getConstraintLocator(anchor, ConstraintLocator::Member); if (auto selected = findOvlChoice(anchorLocator)) { if (selected->choice.isDecl()) return getConcreteDeclRef(selected->choice.getDecl(), selected->openedType, anchorLocator); } } if (auto subscript = dyn_cast(anchor)) { // Subscript expressions may have a declaration. If so, use it. if (subscript->hasDecl()) return subscript->getDecl(); // Otherwise, find the resolved overload. auto anchorLocator = cs.getConstraintLocator(anchor, ConstraintLocator::SubscriptMember); if (auto selected = findOvlChoice(anchorLocator)) { if (selected->choice.isDecl()) return getConcreteDeclRef(selected->choice.getDecl(), selected->openedType, anchorLocator); } } if (auto subscript = dyn_cast(anchor)) { // Dynamic subscripts are always resolved. return subscript->getMember(); } return ConcreteDeclRef(); } ConcreteDeclRef Solution::resolveLocatorToDecl( ConstraintLocator *locator) const { auto &cs = getConstraintSystem(); // Simplify the locator. SourceRange range; locator = simplifyLocator(cs, locator, range); // If we didn't map down to a specific expression, we can't handle a default // argument. if (!locator->getAnchor() || !locator->getPath().empty()) return nullptr; if (auto resolved = ::resolveLocatorToDecl(cs, locator, [&](ConstraintLocator *locator) -> Optional { auto known = overloadChoices.find(locator); if (known == overloadChoices.end()) { return None; } return known->second; }, [&](ValueDecl *decl, Type openedType, ConstraintLocator *locator) -> ConcreteDeclRef { SubstitutionMap subs = computeSubstitutions( decl->getInnermostDeclContext() ->getGenericSignatureOfContext(), locator); return ConcreteDeclRef(decl, subs); })) { return resolved; } return ConcreteDeclRef(); } /// \brief Given a constraint locator, find the declaration reference /// to the callee, it is a call to a declaration. static ConcreteDeclRef findCalleeDeclRef(ConstraintSystem &cs, const Solution &solution, ConstraintLocator *locator) { if (locator->getPath().empty() || !locator->getAnchor()) return nullptr; // If the locator points to a function application, find the function itself. if (locator->getPath().back().getKind() == ConstraintLocator::ApplyArgument) { assert(locator->getPath().back().getNewSummaryFlags() == 0 && "ApplyArgument adds no flags"); SmallVector newPath; newPath.append(locator->getPath().begin(), locator->getPath().end()-1); unsigned newFlags = locator->getSummaryFlags(); newPath.push_back(ConstraintLocator::ApplyFunction); assert(newPath.back().getNewSummaryFlags() == 0 && "added element that changes the flags?"); locator = cs.getConstraintLocator(locator->getAnchor(), newPath, newFlags); } return solution.resolveLocatorToDecl(locator); } static bool shouldApplyAddingLabelFixit(TuplePattern *tuplePattern, TupleType *fromTuple, TupleType *toTuple, std::vector> &locInsertPairs) { std::vector patternParts; std::vector fromParts; std::vector toParts; patternParts.push_back(tuplePattern); fromParts.push_back(fromTuple); toParts.push_back(toTuple); while (!patternParts.empty()) { TuplePattern *curPattern = patternParts.back(); TupleType *curFrom = fromParts.back(); TupleType *curTo = toParts.back(); patternParts.pop_back(); fromParts.pop_back(); toParts.pop_back(); unsigned n = curPattern->getElements().size(); if (curFrom->getElements().size() != n || curTo->getElements().size() != n) return false; for (unsigned i = 0; i < n; i++) { Pattern* subPat = curPattern->getElement(i).getPattern(); const TupleTypeElt &subFrom = curFrom->getElement(i); const TupleTypeElt &subTo = curTo->getElement(i); if ((subFrom.getType()->getKind() == TypeKind::Tuple) ^ (subTo.getType()->getKind() == TypeKind::Tuple)) return false; auto addLabelFunc = [&]() { if (subFrom.getName().empty() && !subTo.getName().empty()) { llvm::SmallString<8> Name; Name.append(subTo.getName().str()); Name.append(": "); locInsertPairs.push_back({subPat->getStartLoc(), Name.str()}); } }; if (auto subFromTuple = subFrom.getType()->getAs()) { fromParts.push_back(subFromTuple); toParts.push_back(subTo.getType()->getAs()); patternParts.push_back(static_cast(subPat)); addLabelFunc(); } else if (subFrom.getType()->isEqual(subTo.getType())) { addLabelFunc(); } else return false; } } return true; } /// Produce the caller-side default argument for this default argument, or /// null if the default argument will be provided by the callee. static std::pair getCallerDefaultArg(ConstraintSystem &cs, DeclContext *dc, SourceLoc loc, ConcreteDeclRef &owner, unsigned index) { auto &tc = cs.getTypeChecker(); auto defArg = getDefaultArgumentInfo(cast(owner.getDecl()), index); Expr *init = nullptr; switch (defArg.first) { case DefaultArgumentKind::None: llvm_unreachable("No default argument here?"); case DefaultArgumentKind::Normal: return {nullptr, defArg.first}; case DefaultArgumentKind::Inherited: // Update the owner to reflect inheritance here. owner = owner.getOverriddenDecl(); return getCallerDefaultArg(cs, dc, loc, owner, index); case DefaultArgumentKind::Column: init = new (tc.Context) MagicIdentifierLiteralExpr( MagicIdentifierLiteralExpr::Column, loc, /*implicit=*/true); break; case DefaultArgumentKind::File: init = new (tc.Context) MagicIdentifierLiteralExpr( MagicIdentifierLiteralExpr::File, loc, /*implicit=*/true); break; case DefaultArgumentKind::Line: init = new (tc.Context) MagicIdentifierLiteralExpr( MagicIdentifierLiteralExpr::Line, loc, /*implicit=*/true); break; case DefaultArgumentKind::Function: init = new (tc.Context) MagicIdentifierLiteralExpr( MagicIdentifierLiteralExpr::Function, loc, /*implicit=*/true); break; case DefaultArgumentKind::DSOHandle: init = new (tc.Context) MagicIdentifierLiteralExpr( MagicIdentifierLiteralExpr::DSOHandle, loc, /*implicit=*/true); break; case DefaultArgumentKind::NilLiteral: init = new (tc.Context) NilLiteralExpr(loc, /*Implicit=*/true); break; case DefaultArgumentKind::EmptyArray: init = ArrayExpr::create(tc.Context, loc, {}, {}, loc); init->setImplicit(); break; case DefaultArgumentKind::EmptyDictionary: init = DictionaryExpr::create(tc.Context, loc, {}, {}, loc); init->setImplicit(); break; } // Convert the literal to the appropriate type. auto defArgType = owner.getDecl()->getDeclContext() ->mapTypeIntoContext(defArg.second); auto resultTy = tc.typeCheckExpression( init, dc, TypeLoc::withoutLoc(defArgType), CTP_CannotFail); assert(resultTy && "Conversion cannot fail"); (void)resultTy; cs.cacheExprTypes(init); return {init, defArg.first}; } static Expr *lookThroughIdentityExprs(Expr *expr) { while (true) { if (auto ident = dyn_cast(expr)) { expr = ident->getSubExpr(); } else if (auto anyTry = dyn_cast(expr)) { if (isa(anyTry)) return expr; expr = anyTry->getSubExpr(); } else { return expr; } } } /// Rebuild the ParenTypes for the given expression, whose underlying expression /// should be set to the given type. This has to apply to exactly the same /// levels of sugar that were stripped off by lookThroughIdentityExprs. static Type rebuildIdentityExprs(ConstraintSystem &cs, Expr *expr, Type type) { ASTContext &ctx = cs.getASTContext(); if (auto paren = dyn_cast(expr)) { type = rebuildIdentityExprs(cs, paren->getSubExpr(), type); cs.setType(paren, ParenType::get(ctx, type->getInOutObjectType(), ParameterTypeFlags().withInOut(type->is()))); return cs.getType(paren); } if (auto ident = dyn_cast(expr)) { type = rebuildIdentityExprs(cs, ident->getSubExpr(), type); cs.setType(ident, type); return cs.getType(ident); } if (auto ident = dyn_cast(expr)) { if (isa(ident)) return type; type = rebuildIdentityExprs(cs, ident->getSubExpr(), type); cs.setType(ident, type); return cs.getType(ident); } return type; } Expr *ExprRewriter::coerceTupleToTuple(Expr *expr, TupleType *fromTuple, TupleType *toTuple, ConstraintLocatorBuilder locator, SmallVectorImpl &sources, SmallVectorImpl &variadicArgs, Optional typeFromPattern){ auto &tc = cs.getTypeChecker(); // Capture the tuple expression, if there is one. Expr *innerExpr = lookThroughIdentityExprs(expr); auto *fromTupleExpr = dyn_cast(innerExpr); /// Check each of the tuple elements in the destination. bool anythingShuffled = false; SmallVector toSugarFields; SmallVector fromTupleExprFields( fromTuple->getElements().size()); for (unsigned i = 0, n = toTuple->getNumElements(); i != n; ++i) { assert(sources[i] != TupleShuffleExpr::DefaultInitialize && sources[i] != TupleShuffleExpr::Variadic); const auto &toElt = toTuple->getElement(i); auto toEltType = toElt.getType(); // If the source and destination index are different, we'll be shuffling. if ((unsigned)sources[i] != i) { anythingShuffled = true; } // We're matching one element to another. If the types already // match, there's nothing to do. const auto &fromElt = fromTuple->getElement(sources[i]); auto fromEltType = fromElt.getType(); if (fromEltType->isEqual(toEltType)) { // Get the sugared type directly from the tuple expression, if there // is one. if (fromTupleExpr) fromEltType = cs.getType(fromTupleExpr->getElement(sources[i])); toSugarFields.push_back(toElt.getWithType(fromEltType)); fromTupleExprFields[sources[i]] = fromElt; continue; } // We need to convert the source element to the destination type. if (!fromTupleExpr) { // FIXME: Lame! We can't express this in the AST. auto anchorExpr = locator.getBaseLocator()->getAnchor(); InFlightDiagnostic diag = tc.diagnose(anchorExpr->getLoc(), diag::tuple_conversion_not_expressible, fromTuple, toTuple); if (typeFromPattern) { std::vector> locInsertPairs; auto *tupleP = dyn_cast(typeFromPattern.getValue()); if (tupleP && shouldApplyAddingLabelFixit(tupleP, toTuple, fromTuple, locInsertPairs)) { for (auto &Pair : locInsertPairs) { diag.fixItInsert(Pair.first, Pair.second); } } } return nullptr; } // Actually convert the source element. auto convertedElt = coerceToType(fromTupleExpr->getElement(sources[i]), toEltType, locator.withPathElement( LocatorPathElt::getTupleElement(sources[i]))); if (!convertedElt) return nullptr; fromTupleExpr->setElement(sources[i], convertedElt); // Record the sugared field name. toSugarFields.push_back(toElt.getWithType(cs.getType(convertedElt))); fromTupleExprFields[sources[i]] = fromElt.getWithType(cs.getType(convertedElt)); } // Compute the updated 'from' tuple type, since we may have // performed some conversions in place. Type fromTupleType = TupleType::get(fromTupleExprFields, tc.Context); if (fromTupleExpr) { cs.setType(fromTupleExpr, fromTupleType); // Update the types of parentheses around the tuple expression. rebuildIdentityExprs(cs, expr, fromTupleType); } // Compute the re-sugared tuple type. Type toSugarType = TupleType::get(toSugarFields, tc.Context); // If we don't have to shuffle anything, we're done. if (!anythingShuffled && fromTupleExpr) { cs.setType(fromTupleExpr, toSugarType); // Update the types of parentheses around the tuple expression. rebuildIdentityExprs(cs, expr, toSugarType); return expr; } // Create the tuple shuffle. return cs.cacheType(TupleShuffleExpr::create(tc.Context, expr, sources, TupleShuffleExpr::TupleToTuple, ConcreteDeclRef(), {}, Type(), {}, toSugarType)); } static Type getMetatypeSuperclass(Type t, TypeChecker &tc) { if (auto *metaTy = t->getAs()) return MetatypeType::get(getMetatypeSuperclass( metaTy->getInstanceType(), tc)); if (auto *metaTy = t->getAs()) return ExistentialMetatypeType::get(getMetatypeSuperclass( metaTy->getInstanceType(), tc)); return t->getSuperclass(); } Expr *ExprRewriter::coerceSuperclass(Expr *expr, Type toType, ConstraintLocatorBuilder locator) { auto &tc = cs.getTypeChecker(); auto fromType = cs.getType(expr); auto fromInstanceType = fromType; auto toInstanceType = toType; while (fromInstanceType->is() && toInstanceType->is()) { fromInstanceType = fromInstanceType->castTo() ->getInstanceType(); toInstanceType = toInstanceType->castTo() ->getInstanceType(); } if (fromInstanceType->is()) { // Coercion from archetype to its (concrete) superclass. auto superclass = getMetatypeSuperclass(fromType, tc); expr = cs.cacheType( new (tc.Context) ArchetypeToSuperExpr(expr, superclass)); if (!superclass->isEqual(toType)) return coerceSuperclass(expr, toType, locator); return expr; } if (fromInstanceType->isExistentialType()) { // Coercion from superclass-constrained existential to its // concrete superclass. auto fromArchetype = ArchetypeType::getAnyOpened(fromType); auto *archetypeVal = cs.cacheType( new (tc.Context) OpaqueValueExpr(expr->getLoc(), fromArchetype)); auto *result = coerceSuperclass(archetypeVal, toType, locator); return cs.cacheType( new (tc.Context) OpenExistentialExpr(expr, archetypeVal, result, toType)); } // Coercion from subclass to superclass. if (toType->is()) { return cs.cacheType( new (tc.Context) MetatypeConversionExpr(expr, toType)); } return cs.cacheType( new (tc.Context) DerivedToBaseExpr(expr, toType)); } /// Collect the conformances for all the protocols of an existential type. /// If the source type is also existential, we don't want to check conformance /// because most protocols do not conform to themselves -- however we still /// allow the conversion here, except the ErasureExpr ends up with trivial /// conformances. static ArrayRef collectExistentialConformances(TypeChecker &tc, Type fromType, Type toType, DeclContext *DC) { auto layout = toType->getExistentialLayout(); SmallVector conformances; for (auto proto : layout.getProtocols()) { conformances.push_back( *tc.containsProtocol(fromType, proto->getDecl(), DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::Used))); } return tc.Context.AllocateCopy(conformances); } Expr *ExprRewriter::coerceExistential(Expr *expr, Type toType, ConstraintLocatorBuilder locator) { auto &tc = solution.getConstraintSystem().getTypeChecker(); Type fromType = cs.getType(expr); Type fromInstanceType = fromType; Type toInstanceType = toType; // Look through metatypes while ((fromInstanceType->is() || fromInstanceType->is()) && toInstanceType->is()) { if (!fromInstanceType->is()) fromInstanceType = fromInstanceType->castTo()->getInstanceType(); toInstanceType = toInstanceType->castTo()->getInstanceType(); } ASTContext &ctx = tc.Context; auto conformances = collectExistentialConformances(tc, fromInstanceType, toInstanceType, cs.DC); // For existential-to-existential coercions, open the source existential. if (fromType->isAnyExistentialType()) { fromType = ArchetypeType::getAnyOpened(fromType); auto *archetypeVal = cs.cacheType( new (ctx) OpaqueValueExpr(expr->getLoc(), fromType)); auto *result = cs.cacheType(ErasureExpr::create(ctx, archetypeVal, toType, conformances)); return cs.cacheType( new (ctx) OpenExistentialExpr(expr, archetypeVal, result, cs.getType(result))); } // Load tuples with lvalue elements. if (auto tupleType = fromType->getAs()) { if (tupleType->hasLValueType()) { auto toTuple = tupleType->getRValueType()->castTo(); SmallVector sources; SmallVector variadicArgs; bool failed = computeTupleShuffle(tupleType, toTuple, sources, variadicArgs); assert(!failed && "Couldn't convert tuple to tuple?"); (void)failed; coerceTupleToTuple(expr, tupleType, toTuple, locator, sources, variadicArgs); } } return cs.cacheType(ErasureExpr::create(ctx, expr, toType, conformances)); } /// Given that the given expression is an implicit conversion added /// to the target by coerceToType, find out how many OptionalEvaluationExprs /// it includes and the target. static unsigned getOptionalEvaluationDepth(Expr *expr, Expr *target) { unsigned depth = 0; while (true) { // Look through sugar expressions. expr = expr->getSemanticsProvidingExpr(); // If we find the target expression, we're done. if (expr == target) return depth; // If we see an optional evaluation, the depth goes up. if (auto optEval = dyn_cast(expr)) { depth++; expr = optEval->getSubExpr(); // We have to handle any other expressions that can be introduced by // coerceToType. } else if (auto bind = dyn_cast(expr)) { expr = bind->getSubExpr(); } else if (auto force = dyn_cast(expr)) { expr = force->getSubExpr(); } else if (auto open = dyn_cast(expr)) { depth += getOptionalEvaluationDepth(open->getSubExpr(), open->getOpaqueValue()); expr = open->getExistentialValue(); // Otherwise, look through implicit conversions. } else { expr = cast(expr)->getSubExpr(); } } } Expr *ExprRewriter::coerceOptionalToOptional(Expr *expr, Type toType, ConstraintLocatorBuilder locator, Optional typeFromPattern) { auto &tc = cs.getTypeChecker(); Type fromType = cs.getType(expr); tc.requireOptionalIntrinsics(expr->getLoc()); SmallVector fromOptionals; (void)fromType->lookThroughAllOptionalTypes(fromOptionals); SmallVector toOptionals; (void)toType->lookThroughAllOptionalTypes(toOptionals); assert(!toOptionals.empty()); assert(!fromOptionals.empty()); // If we are adding optionals but the types are equivalent up to the common // depth, peephole the optional-to-optional conversion into a series of nested // injections. auto toDepth = toOptionals.size(); auto fromDepth = fromOptionals.size(); if (toDepth > fromDepth && toOptionals[toOptionals.size() - fromDepth]->isEqual(fromType)) { auto diff = toDepth - fromDepth; while (diff--) { Type type = toOptionals[diff]; expr = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(expr, type)); diagnoseOptionalInjection(cast(expr)); } return expr; } Type fromValueType = fromType->getOptionalObjectType(); Type toValueType = toType->getOptionalObjectType(); // The depth we use here will get patched after we apply the coercion. auto bindOptional = new (tc.Context) BindOptionalExpr(expr, expr->getSourceRange().End, /*depth*/ 0, fromValueType); expr = cs.cacheType(bindOptional); expr->setImplicit(true); expr = coerceToType(expr, toValueType, locator, typeFromPattern); if (!expr) return nullptr; unsigned depth = getOptionalEvaluationDepth(expr, bindOptional); bindOptional->setDepth(depth); expr = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(expr, toType)); expr = cs.cacheType(new (tc.Context) OptionalEvaluationExpr(expr, toType)); expr->setImplicit(true); return expr; } Expr *ExprRewriter::coerceImplicitlyUnwrappedOptionalToValue(Expr *expr, Type objTy) { auto optTy = cs.getType(expr); // Coerce to an r-value. if (optTy->is()) objTy = LValueType::get(objTy); expr = new (cs.getTypeChecker().Context) ForceValueExpr(expr, expr->getEndLoc(), /* forcedIUO=*/ true); cs.setType(expr, objTy); expr->setImplicit(); return expr; } /// Determine whether the given expression is a reference to an /// unbound instance member of a type. static bool isReferenceToMetatypeMember(ConstraintSystem &cs, Expr *expr) { expr = expr->getSemanticsProvidingExpr(); if (auto dotIgnored = dyn_cast(expr)) return cs.getType(dotIgnored->getLHS())->is(); if (auto dotSyntax = dyn_cast(expr)) return cs.getType(dotSyntax->getBase())->is(); return false; } static unsigned computeCallLevel(ConstraintSystem &cs, ConcreteDeclRef callee, ApplyExpr *apply) { // If we do not have a callee, return a level of 0. if (!callee) { return 0; } // Only calls to members of types can have level > 0. auto calleeDecl = callee.getDecl(); if (!calleeDecl->getDeclContext()->isTypeContext()) { return 0; } // Level 1 if we're not applying "self". if (auto *call = dyn_cast(apply)) { if (!calleeDecl->isInstanceMember() || !isReferenceToMetatypeMember(cs, call->getDirectCallee())) { return 1; } return 0; } // Level 1 if we have an operator. if (isa(apply) || isa(apply) || isa(apply)) { return 1; } // Otherwise, we have a normal application. return 0; } Expr *ExprRewriter::coerceCallArguments( Expr *arg, AnyFunctionType *funcType, ApplyExpr *apply, ArrayRef argLabels, bool hasTrailingClosure, ConstraintLocatorBuilder locator) { auto &tc = getConstraintSystem().getTypeChecker(); auto params = funcType->getParams(); // Local function to produce a locator to refer to the given parameter. auto getArgLocator = [&](unsigned argIdx, unsigned paramIdx) -> ConstraintLocatorBuilder { return locator.withPathElement( LocatorPathElt::getApplyArgToParam(argIdx, paramIdx)); }; bool matchCanFail = llvm::any_of(params, [](const AnyFunctionType::Param ¶m) { return param.getPlainType()->hasUnresolvedType(); }); // Find the callee declaration. ConcreteDeclRef callee = findCalleeDeclRef(cs, solution, cs.getConstraintLocator(locator)); // Determine the level, unsigned level = apply ? computeCallLevel(cs, callee, apply) : 0; // Determine the parameter bindings. llvm::SmallBitVector defaultMap = computeDefaultMap(params, callee.getDecl(), level); SmallVector args; AnyFunctionType::decomposeInput(cs.getType(arg), args); // Quickly test if any further fix-ups for the argument types are necessary. if (AnyFunctionType::equalParams(args, params)) return arg; // Apply labels to arguments. AnyFunctionType::relabelParams(args, argLabels); MatchCallArgumentListener listener; SmallVector parameterBindings; bool failed = constraints::matchCallArguments(args, params, defaultMap, hasTrailingClosure, /*allowFixes=*/false, listener, parameterBindings); assert((matchCanFail || !failed) && "Call arguments did not match up?"); (void)failed; (void)matchCanFail; // We should either have parentheses or a tuple. auto *argTuple = dyn_cast(arg); auto *argParen = dyn_cast(arg); // FIXME: Eventually, we want to enforce that we have either argTuple or // argParen here. // Local function to extract the ith argument expression, which papers // over some of the weirdness with tuples vs. parentheses. auto getArg = [&](unsigned i) -> Expr * { if (argTuple) return argTuple->getElement(i); assert(i == 0 && "Scalar only has a single argument"); if (argParen) return argParen->getSubExpr(); return arg; }; // Local function to extract the ith argument label, which papers over some // of the weirdness with tuples vs. parentheses. auto getArgLabel = [&](unsigned i) -> Identifier { if (argTuple) return argTuple->getElementName(i); assert(i == 0 && "Scalar only has a single argument"); return Identifier(); }; SmallVector toSugarFields; SmallVector fromTupleExprFields( argTuple? argTuple->getNumElements() : 1); SmallVector fromTupleExpr(argTuple? argTuple->getNumElements() : 1); SmallVector variadicArgs; SmallVector callerDefaultArgs; Type sliceType = nullptr; SmallVector sources; for (unsigned paramIdx = 0, numParams = parameterBindings.size(); paramIdx != numParams; ++paramIdx) { // Extract the parameter. const auto ¶m = params[paramIdx]; // Handle variadic parameters. if (param.isVariadic()) { // Find the appropriate injection function. if (tc.requireArrayLiteralIntrinsics(arg->getStartLoc())) return nullptr; // Record this parameter. auto paramBaseType = param.getType(); assert(sliceType.isNull() && "Multiple variadic parameters?"); sliceType = tc.getArraySliceType(arg->getLoc(), paramBaseType); toSugarFields.push_back( TupleTypeElt(sliceType, param.getLabel(), param.getParameterFlags())); sources.push_back(TupleShuffleExpr::Variadic); // Convert the arguments. for (auto argIdx : parameterBindings[paramIdx]) { auto arg = getArg(argIdx); auto argType = cs.getType(arg); variadicArgs.push_back(argIdx); // If the argument type exactly matches, this just works. if (argType->isEqual(paramBaseType)) { fromTupleExprFields[argIdx] = TupleTypeElt(argType, getArgLabel(argIdx)); fromTupleExpr[argIdx] = arg; continue; } // Convert the argument. auto convertedArg = coerceToType(arg, paramBaseType, getArgLocator(argIdx, paramIdx)); if (!convertedArg) return nullptr; // Add the converted argument. fromTupleExpr[argIdx] = convertedArg; fromTupleExprFields[argIdx] = TupleTypeElt(cs.getType(convertedArg), getArgLabel(argIdx)); } continue; } // If we are using a default argument, handle it now. if (parameterBindings[paramIdx].empty()) { // Create a caller-side default argument, if we need one. Expr *defArg; DefaultArgumentKind defArgKind; std::tie(defArg, defArgKind) = getCallerDefaultArg(cs, dc, arg->getLoc(), callee, paramIdx); // Note that we'll be doing a shuffle involving default arguments. toSugarFields.push_back(TupleTypeElt( param.isVariadic() ? tc.getArraySliceType(arg->getLoc(), param.getType()) : param.getType(), param.getLabel(), param.getParameterFlags())); if (defArg) { callerDefaultArgs.push_back(defArg); sources.push_back(TupleShuffleExpr::CallerDefaultInitialize); } else { sources.push_back(TupleShuffleExpr::DefaultInitialize); } continue; } // Extract the argument used to initialize this parameter. assert(parameterBindings[paramIdx].size() == 1); unsigned argIdx = parameterBindings[paramIdx].front(); auto arg = getArg(argIdx); auto argType = cs.getType(arg); // If the argument and parameter indices differ, or if the names differ, // this is a shuffle. sources.push_back(argIdx); // If the types exactly match, this is easy. auto paramType = param.getType(); if (argType->isEqual(paramType)) { toSugarFields.push_back( TupleTypeElt(param.getPlainType(), getArgLabel(argIdx), param.getParameterFlags())); fromTupleExprFields[argIdx] = TupleTypeElt(param.getPlainType(), getArgLabel(argIdx), param.getParameterFlags()); fromTupleExpr[argIdx] = arg; continue; } // Convert the argument. auto convertedArg = coerceToType(arg, paramType, getArgLocator(argIdx, paramIdx)); if (!convertedArg) return nullptr; // Add the converted argument. fromTupleExpr[argIdx] = convertedArg; fromTupleExprFields[argIdx] = TupleTypeElt( cs.getType(convertedArg)->getInOutObjectType(), getArgLabel(argIdx), param.getParameterFlags()); toSugarFields.push_back( TupleTypeElt(argType->getInOutObjectType(), param.getLabel(), param.getParameterFlags())); } Type argTupleType = TupleType::get(fromTupleExprFields, tc.Context); // Compute a new 'arg', from the bits we have. We have three cases: the // scalar case, the paren case, and the tuple literal case. if (!argTuple && !argParen) { assert(fromTupleExpr.size() == 1 && fromTupleExpr[0]); arg = fromTupleExpr[0]; } else if (argParen) { // If the element changed, rebuild a new ParenExpr. assert(fromTupleExpr.size() == 1 && fromTupleExpr[0]); if (fromTupleExpr[0] != argParen->getSubExpr()) { bool argParenImplicit = argParen->isImplicit(); argParen = cs.cacheType(new (tc.Context) ParenExpr(argParen->getLParenLoc(), fromTupleExpr[0], argParen->getRParenLoc(), argParen->hasTrailingClosure(), argTupleType)); if (argParenImplicit) { argParen->setImplicit(); } arg = argParen; } else { // coerceToType may have updated the element type of the ParenExpr in // place. If so, propagate the type out to the ParenExpr as well. cs.setType(argParen, argTupleType); } } else { assert(argTuple); bool anyChanged = false; for (unsigned i = 0, e = argTuple->getNumElements(); i != e; ++i) if (fromTupleExpr[i] != argTuple->getElement(i)) { anyChanged = true; break; } // If anything about the TupleExpr changed, rebuild a new one. Type argTupleType = TupleType::get(fromTupleExprFields, tc.Context); assert(isa(argTupleType.getPointer())); if (anyChanged || !cs.getType(argTuple)->isEqual(argTupleType)) { auto EltNames = argTuple->getElementNames(); auto EltNameLocs = argTuple->getElementNameLocs(); argTuple = cs.cacheType(TupleExpr::create(tc.Context, argTuple->getLParenLoc(), fromTupleExpr, EltNames, EltNameLocs, argTuple->getRParenLoc(), argTuple->hasTrailingClosure(), argTuple->isImplicit(), argTupleType)); arg = argTuple; } } // If we don't have to shuffle anything, we're done. args.clear(); AnyFunctionType::decomposeInput(cs.getType(arg), args); if (AnyFunctionType::equalParams(args, params)) return arg; auto paramType = AnyFunctionType::composeInput(tc.Context, params, /*canonicalVararg=*/false); // If we came from a scalar, create a scalar-to-tuple conversion. TupleShuffleExpr::TypeImpact typeImpact; if (argTuple == nullptr) { typeImpact = TupleShuffleExpr::ScalarToTuple; assert(isa(paramType.getPointer())); } else if (isa(paramType.getPointer())) { typeImpact = TupleShuffleExpr::TupleToTuple; } else { typeImpact = TupleShuffleExpr::TupleToScalar; assert(isa(paramType.getPointer())); } // Create the tuple shuffle. return cs.cacheType(TupleShuffleExpr::create(tc.Context, arg, sources, typeImpact, callee, variadicArgs, sliceType, callerDefaultArgs, paramType)); } static ClosureExpr *getClosureLiteralExpr(Expr *expr) { expr = expr->getSemanticsProvidingExpr(); if (auto *captureList = dyn_cast(expr)) return captureList->getClosureBody(); if (auto *closure = dyn_cast(expr)) return closure; return nullptr; } /// If the expression is an explicit closure expression (potentially wrapped in /// IdentityExprs), change the type of the closure and identities to the /// specified type and return true. Otherwise, return false with no effect. static bool applyTypeToClosureExpr(ConstraintSystem &cs, Expr *expr, Type toType) { // Look through identity expressions, like parens. if (auto IE = dyn_cast(expr)) { if (!applyTypeToClosureExpr(cs, IE->getSubExpr(), toType)) return false; cs.setType(IE, toType); return true; } // Look through capture lists. if (auto CLE = dyn_cast(expr)) { if (!applyTypeToClosureExpr(cs, CLE->getClosureBody(), toType)) return false; cs.setType(CLE, toType); return true; } // If we found an explicit ClosureExpr, update its type. if (auto CE = dyn_cast(expr)) { cs.setType(CE, toType); // If this is not a single-expression closure, write the type into the // ClosureExpr directly here, since the visitor won't. if (!CE->hasSingleExpressionBody()) CE->setType(toType); return true; } // Otherwise fail. return false; } ClosureExpr *ExprRewriter::coerceClosureExprToVoid(ClosureExpr *closureExpr) { auto &tc = cs.getTypeChecker(); // Re-write the single-expression closure to return '()' assert(closureExpr->hasSingleExpressionBody()); // A single-expression body contains a single return statement // prior to this transformation. auto member = closureExpr->getBody()->getElement(0); if (member.is()) { auto returnStmt = cast(member.get()); auto singleExpr = returnStmt->getResult(); auto voidExpr = cs.cacheType( TupleExpr::createEmpty(tc.Context, singleExpr->getStartLoc(), singleExpr->getEndLoc(), /*implicit*/true)); returnStmt->setResult(voidExpr); // For l-value types, reset to the object type. This might not be strictly // necessary any more, but it's probably still a good idea. if (cs.getType(singleExpr)->is()) cs.setType(singleExpr, cs.getType(singleExpr)->getWithoutSpecifierType()); cs.setExprTypes(singleExpr); tc.checkIgnoredExpr(singleExpr); SmallVector elements; elements.push_back(singleExpr); elements.push_back(returnStmt); auto braceStmt = BraceStmt::create(tc.Context, closureExpr->getStartLoc(), elements, closureExpr->getEndLoc(), /*implicit*/true); closureExpr->setImplicit(); closureExpr->setBody(braceStmt, /*isSingleExpression*/true); } // Finally, compute the proper type for the closure. auto fnType = cs.getType(closureExpr)->getAs(); auto newClosureType = FunctionType::get( fnType->getParams(), tc.Context.TheEmptyTupleType, fnType->getExtInfo()); cs.setType(closureExpr, newClosureType); return closureExpr; } ClosureExpr *ExprRewriter::coerceClosureExprFromNever(ClosureExpr *closureExpr) { auto &tc = cs.getTypeChecker(); // Re-write the single-expression closure to drop the 'return'. assert(closureExpr->hasSingleExpressionBody()); // A single-expression body contains a single return statement // prior to this transformation. auto member = closureExpr->getBody()->getElement(0); if (member.is()) { auto returnStmt = cast(member.get()); auto singleExpr = returnStmt->getResult(); cs.setExprTypes(singleExpr); tc.checkIgnoredExpr(singleExpr); SmallVector elements; elements.push_back(singleExpr); auto braceStmt = BraceStmt::create(tc.Context, closureExpr->getStartLoc(), elements, closureExpr->getEndLoc(), /*implicit*/true); closureExpr->setImplicit(); closureExpr->setBody(braceStmt, /*isSingleExpression*/true); } return closureExpr; } // Look through sugar and DotSyntaxBaseIgnoredExprs. static Expr * getSemanticExprForDeclOrMemberRef(Expr *expr) { auto semanticExpr = expr->getSemanticsProvidingExpr(); while (auto ignoredBase = dyn_cast(semanticExpr)){ semanticExpr = ignoredBase->getRHS()->getSemanticsProvidingExpr(); } return semanticExpr; } static void maybeDiagnoseUnsupportedFunctionConversion(ConstraintSystem &cs, Expr *expr, AnyFunctionType *toType) { auto &tc = cs.getTypeChecker(); Type fromType = cs.getType(expr); auto fromFnType = fromType->getAs(); // Conversions to C function pointer type are limited. Since a C function // pointer captures no context, we can only do the necessary thunking or // codegen if the original function is a direct reference to a global function // or context-free closure or local function. if (toType->getRepresentation() == AnyFunctionType::Representation::CFunctionPointer) { // Can convert from an ABI-compatible C function pointer. if (fromFnType && fromFnType->getRepresentation() == AnyFunctionType::Representation::CFunctionPointer) return; // Can convert a decl ref to a global or local function that doesn't // capture context. Look through ignored bases too. // TODO: Look through static method applications to the type. auto semanticExpr = getSemanticExprForDeclOrMemberRef(expr); auto maybeDiagnoseFunctionRef = [&](FuncDecl *fn) { // TODO: We could allow static (or class final) functions too by // "capturing" the metatype in a thunk. if (fn->getDeclContext()->isTypeContext()) { tc.diagnose(expr->getLoc(), diag::c_function_pointer_from_method); } else if (fn->getGenericParams()) { tc.diagnose(expr->getLoc(), diag::c_function_pointer_from_generic_function); } else { tc.maybeDiagnoseCaptures(expr, fn); } }; if (auto declRef = dyn_cast(semanticExpr)) { if (auto fn = dyn_cast(declRef->getDecl())) { return maybeDiagnoseFunctionRef(fn); } } if (auto memberRef = dyn_cast(semanticExpr)) { if (auto fn = dyn_cast(memberRef->getMember().getDecl())) { return maybeDiagnoseFunctionRef(fn); } } // Unwrap closures with explicit capture lists. if (auto capture = dyn_cast(semanticExpr)) semanticExpr = capture->getClosureBody(); // Can convert a literal closure that doesn't capture context. if (auto closure = dyn_cast(semanticExpr)) { tc.maybeDiagnoseCaptures(expr, closure); return; } tc.diagnose(expr->getLoc(), diag::invalid_c_function_pointer_conversion_expr); } } /// Build the conversion of an element in a collection upcast. static Expr *buildElementConversion(ExprRewriter &rewriter, SourceLoc srcLoc, Type srcType, Type destType, bool bridged, ConstraintLocatorBuilder locator, Expr *element) { auto &cs = rewriter.getConstraintSystem(); auto &tc = rewriter.getConstraintSystem().getTypeChecker(); if (bridged && tc.typeCheckCheckedCast(srcType, destType, CheckedCastContextKind::None, cs.DC, SourceLoc(), nullptr, SourceRange()) != CheckedCastKind::Coercion) { if (auto conversion = rewriter.buildObjCBridgeExpr(element, destType, locator)) return conversion; } return rewriter.coerceToType(element, destType, locator); } static CollectionUpcastConversionExpr::ConversionPair buildOpaqueElementConversion(ExprRewriter &rewriter, SourceLoc srcLoc, Type srcCollectionType, Type destCollectionType, bool bridged, ConstraintLocatorBuilder locator, unsigned typeArgIndex) { // We don't need this stuff unless we've got generalized casts. Type srcType = srcCollectionType->castTo() ->getGenericArgs()[typeArgIndex]; Type destType = destCollectionType->castTo() ->getGenericArgs()[typeArgIndex]; // Build the conversion. auto &cs = rewriter.getConstraintSystem(); ASTContext &ctx = cs.getASTContext(); auto opaque = rewriter.cs.cacheType(new (ctx) OpaqueValueExpr(srcLoc, srcType)); Expr *conversion = buildElementConversion(rewriter, srcLoc, srcType, destType, bridged, locator.withPathElement( ConstraintLocator::PathElement::getGenericArgument( typeArgIndex)), opaque); return { opaque, conversion }; } void ExprRewriter::peepholeArrayUpcast(ArrayExpr *expr, Type toType, bool bridged, Type elementType, ConstraintLocatorBuilder locator) { // Update the type of the array literal. cs.setType(expr, toType); // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming // the semantic expression for the dictionary literal, which will undo the // type we set here if this dictionary literal is nested unless we update // the expr type as well. expr->setType(toType); // Convert the elements. ConstraintLocatorBuilder innerLocator = locator.withPathElement( ConstraintLocator::PathElement::getGenericArgument(0)); for (auto &element : expr->getElements()) { if (auto newElement = buildElementConversion(*this, expr->getLoc(), cs.getType(element), elementType, bridged, innerLocator, element)) { element = newElement; } } (void)finishArrayExpr(expr); } void ExprRewriter::peepholeDictionaryUpcast(DictionaryExpr *expr, Type toType, bool bridged, Type keyType, Type valueType, ConstraintLocatorBuilder locator) { // Update the type of the dictionary literal. cs.setType(expr, toType); // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming // the semantic expression for the dictionary literal, which will undo the // type we set here if this dictionary literal is nested unless we update // the expr type as well. expr->setType(toType); ConstraintLocatorBuilder valueLocator = locator.withPathElement( ConstraintLocator::PathElement::getGenericArgument(1)); // Convert the elements. TupleTypeElt tupleTypeElts[2] = { keyType, valueType }; auto tupleType = TupleType::get(tupleTypeElts, cs.getASTContext()); for (auto element : expr->getElements()) { if (auto tuple = dyn_cast(element)) { auto key = tuple->getElement(0); if (auto newKey = buildElementConversion(*this, expr->getLoc(), cs.getType(key), keyType, bridged, valueLocator, key)) tuple->setElement(0, newKey); auto value = tuple->getElement(1); if (auto newValue = buildElementConversion(*this, expr->getLoc(), cs.getType(value), valueType, bridged, valueLocator, value)) { tuple->setElement(1, newValue); } cs.setType(tuple, tupleType); // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming // the semantic expression for the dictionary literal, which will undo the // type we set here if this dictionary literal is nested unless we update // the expr type as well. tuple->setType(tupleType); } } (void)finishDictionaryExpr(expr); } bool ExprRewriter::peepholeCollectionUpcast(Expr *expr, Type toType, bool bridged, ConstraintLocatorBuilder locator) { // Recur into parenthesized expressions. if (auto paren = dyn_cast(expr)) { // If we can't peephole the subexpression, we're done. if (!peepholeCollectionUpcast(paren->getSubExpr(), toType, bridged, locator)) return false; // Update the type of this expression. auto parenTy = ParenType::get(cs.getASTContext(), cs.getType(paren->getSubExpr())); cs.setType(paren, parenTy); // FIXME: finish{Array,Dictionary}Expr invoke cacheExprTypes after forming // the semantic expression for the dictionary literal, which will undo the // type we set here if this dictionary literal is nested unless we update // the expr type as well. paren->setType(parenTy); return true; } // Array literals. if (auto arrayLiteral = dyn_cast(expr)) { if (Optional elementType = ConstraintSystem::isArrayType(toType)) { peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator); return true; } if (Optional elementType = ConstraintSystem::isSetType(toType)) { peepholeArrayUpcast(arrayLiteral, toType, bridged, *elementType, locator); return true; } return false; } // Dictionary literals. if (auto dictLiteral = dyn_cast(expr)) { if (auto elementType = ConstraintSystem::isDictionaryType(toType)) { peepholeDictionaryUpcast(dictLiteral, toType, bridged, elementType->first, elementType->second, locator); return true; } return false; } return false; } Expr *ExprRewriter::buildCollectionUpcastExpr( Expr *expr, Type toType, bool bridged, ConstraintLocatorBuilder locator) { if (peepholeCollectionUpcast(expr, toType, bridged, locator)) return expr; ASTContext &ctx = cs.getASTContext(); // Build the first value conversion. auto conv = buildOpaqueElementConversion(*this, expr->getLoc(), cs.getType(expr), toType, bridged, locator, 0); // For single-parameter collections, form the upcast. if (ConstraintSystem::isArrayType(toType) || ConstraintSystem::isSetType(toType)) { return cs.cacheType( new (ctx) CollectionUpcastConversionExpr(expr, toType, {}, conv)); } assert(ConstraintSystem::isDictionaryType(toType) && "Unhandled collection upcast"); // Build the second value conversion. auto conv2 = buildOpaqueElementConversion(*this, expr->getLoc(), cs.getType(expr), toType, bridged, locator, 1); return cs.cacheType( new (ctx) CollectionUpcastConversionExpr(expr, toType, conv, conv2)); } Expr *ExprRewriter::buildObjCBridgeExpr(Expr *expr, Type toType, ConstraintLocatorBuilder locator) { auto &tc = cs.getTypeChecker(); Type fromType = cs.getType(expr); // Bridged collection casts always succeed, so we treat them as // collection "upcasts". if ((ConstraintSystem::isArrayType(fromType) && ConstraintSystem::isArrayType(toType)) || (ConstraintSystem::isDictionaryType(fromType) && ConstraintSystem::isDictionaryType(toType)) || (ConstraintSystem::isSetType(fromType) && ConstraintSystem::isSetType(toType))) { return buildCollectionUpcastExpr(expr, toType, /*bridged=*/true, locator); } // Bridging from a Swift type to an Objective-C class type. if (toType->isAnyObject() || (fromType->getRValueType()->isPotentiallyBridgedValueType() && (toType->isBridgeableObjectType() || toType->isExistentialType()))) { // Bridging to Objective-C. Expr *objcExpr = bridgeToObjectiveC(expr, toType); if (!objcExpr) return nullptr; // We might have a coercion of a Swift type to a CF type toll-free // bridged to Objective-C. // // FIXME: Ideally we would instead have already recorded a restriction // when solving the constraint, and we wouldn't need to duplicate this // part of coerceToType() here. if (auto foreignClass = toType->getClassOrBoundGenericClass()) { if (foreignClass->getForeignClassKind() == ClassDecl::ForeignKind::CFType) { return cs.cacheType( new (tc.Context) ForeignObjectConversionExpr(objcExpr, toType)); } } return coerceToType(objcExpr, toType, locator); } // Bridging from an Objective-C class type to a Swift type. return forceBridgeFromObjectiveC(expr, toType); } static Expr *addImplicitLoadExpr(ConstraintSystem &cs, Expr *expr) { auto &tc = cs.getTypeChecker(); return tc.addImplicitLoadExpr( expr, [&cs](Expr *expr) { return cs.getType(expr); }, [&cs](Expr *expr, Type type) { cs.setType(expr, type); }); } Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, ConstraintLocatorBuilder locator, Optional typeFromPattern) { auto &tc = cs.getTypeChecker(); // The type we're converting from. Type fromType = cs.getType(expr); // If the types are already equivalent, we don't have to do anything. if (fromType->isEqual(toType)) return expr; // If the solver recorded what we should do here, just do it immediately. auto knownRestriction = solution.ConstraintRestrictions.find( { fromType->getCanonicalType(), toType->getCanonicalType() }); if (knownRestriction != solution.ConstraintRestrictions.end()) { switch (knownRestriction->second) { case ConversionRestrictionKind::TupleToTuple: case ConversionRestrictionKind::LValueToRValue: // Restrictions that don't need to be recorded. // Should match recordRestriction() in CSSimplify break; case ConversionRestrictionKind::DeepEquality: { if (toType->hasUnresolvedType()) break; // HACK: Fix problem related to Swift 4 mode (with assertions), // since Swift 4 mode allows passing arguments with extra parens // to parameters which don't expect them, it should be supported // by "deep equality" type - Optional e.g. // ```swift // func foo(_: (() -> Void)?) {} // func bar() -> ((()) -> Void)? { return nil } // foo(bar) // This expression should compile in Swift 3 mode // ``` // // See also: https://bugs.swift.org/browse/SR-6796 if (cs.getASTContext().isSwiftVersionAtLeast(4) && !cs.getASTContext().isSwiftVersionAtLeast(5)) { auto obj1 = fromType->getOptionalObjectType(); auto obj2 = toType->getOptionalObjectType(); if (obj1 && obj2) { auto *fn1 = obj1->getAs(); auto *fn2 = obj2->getAs(); if (fn1 && fn2) { auto params1 = fn1->getParams(); auto params2 = fn2->getParams(); // This handles situations like argument: (()), parameter: (). if (params1.size() == 1 && params2.empty()) { auto tupleTy = params1.front().getType()->getAs(); if (tupleTy && tupleTy->getNumElements() == 0) break; } } } } llvm_unreachable("Should be handled above"); } case ConversionRestrictionKind::Superclass: case ConversionRestrictionKind::ExistentialMetatypeToMetatype: return coerceSuperclass(expr, toType, locator); case ConversionRestrictionKind::Existential: case ConversionRestrictionKind::MetatypeToExistentialMetatype: return coerceExistential(expr, toType, locator); case ConversionRestrictionKind::ClassMetatypeToAnyObject: { assert(tc.getLangOpts().EnableObjCInterop && "metatypes can only be cast to objects w/ objc runtime!"); return cs.cacheType( new (tc.Context) ClassMetatypeToObjectExpr(expr, toType)); } case ConversionRestrictionKind::ExistentialMetatypeToAnyObject: { assert(tc.getLangOpts().EnableObjCInterop && "metatypes can only be cast to objects w/ objc runtime!"); return cs.cacheType( new (tc.Context) ExistentialMetatypeToObjectExpr(expr, toType)); } case ConversionRestrictionKind::ProtocolMetatypeToProtocolClass: { return cs.cacheType( new (tc.Context) ProtocolMetatypeToObjectExpr(expr, toType)); } case ConversionRestrictionKind::ValueToOptional: { auto toGenericType = toType->castTo(); assert(toGenericType->getDecl()->isOptionalDecl()); tc.requireOptionalIntrinsics(expr->getLoc()); Type valueType = toGenericType->getGenericArgs()[0]; expr = coerceToType(expr, valueType, locator); if (!expr) return nullptr; auto *result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(expr, toType)); diagnoseOptionalInjection(result); return result; } case ConversionRestrictionKind::OptionalToOptional: return coerceOptionalToOptional(expr, toType, locator, typeFromPattern); case ConversionRestrictionKind::ArrayUpcast: { // Build the value conversion. return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false, locator); } case ConversionRestrictionKind::HashableToAnyHashable: { // We want to check conformance on the rvalue, as that's what has // the Hashable conformance expr = cs.coerceToRValue(expr); // Find the conformance of the source type to Hashable. auto hashable = tc.Context.getProtocol(KnownProtocolKind::Hashable); auto conformance = tc.conformsToProtocol( cs.getType(expr), hashable, cs.DC, (ConformanceCheckFlags::InExpression | ConformanceCheckFlags::Used)); assert(conformance && "must conform to Hashable"); return cs.cacheType( new (tc.Context) AnyHashableErasureExpr(expr, toType, *conformance)); } case ConversionRestrictionKind::DictionaryUpcast: { // Build the value conversion. return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false, locator); } case ConversionRestrictionKind::SetUpcast: { // Build the value conversion. return buildCollectionUpcastExpr(expr, toType, /*bridged=*/false, locator); } case ConversionRestrictionKind::InoutToPointer: { bool isOptional = false; Type unwrappedTy = toType; if (Type unwrapped = toType->getOptionalObjectType()) { isOptional = true; unwrappedTy = unwrapped; } PointerTypeKind pointerKind; auto toEltType = unwrappedTy->getAnyPointerElementType(pointerKind); assert(toEltType && "not a pointer type?"); (void) toEltType; tc.requirePointerArgumentIntrinsics(expr->getLoc()); Expr *result = cs.cacheType(new (tc.Context) InOutToPointerExpr(expr, unwrappedTy)); if (isOptional) result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(result, toType)); return result; } case ConversionRestrictionKind::ArrayToPointer: { bool isOptional = false; Type unwrappedTy = toType; if (Type unwrapped = toType->getOptionalObjectType()) { isOptional = true; unwrappedTy = unwrapped; } tc.requirePointerArgumentIntrinsics(expr->getLoc()); Expr *result = cs.cacheType(new (tc.Context) ArrayToPointerExpr(expr, unwrappedTy)); if (isOptional) result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(result, toType)); return result; } case ConversionRestrictionKind::StringToPointer: { bool isOptional = false; Type unwrappedTy = toType; if (Type unwrapped = toType->getOptionalObjectType()) { isOptional = true; unwrappedTy = unwrapped; } tc.requirePointerArgumentIntrinsics(expr->getLoc()); Expr *result = cs.cacheType(new (tc.Context) StringToPointerExpr(expr, unwrappedTy)); if (isOptional) result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(result, toType)); return result; } case ConversionRestrictionKind::PointerToPointer: { tc.requirePointerArgumentIntrinsics(expr->getLoc()); Type unwrappedToTy = toType->getOptionalObjectType(); // Optional to optional. if (Type unwrappedFromTy = cs.getType(expr)->getOptionalObjectType()) { assert(unwrappedToTy && "converting optional to non-optional"); Expr *boundOptional = cs.cacheType( new (tc.Context) BindOptionalExpr(expr, SourceLoc(), /*depth*/ 0, unwrappedFromTy)); Expr *converted = cs.cacheType(new (tc.Context) PointerToPointerExpr( boundOptional, unwrappedToTy)); Expr *rewrapped = cs.cacheType( new (tc.Context) InjectIntoOptionalExpr(converted, toType)); return cs.cacheType(new (tc.Context) OptionalEvaluationExpr(rewrapped, toType)); } // Non-optional to optional. if (unwrappedToTy) { Expr *converted = cs.cacheType( new (tc.Context) PointerToPointerExpr(expr, unwrappedToTy)); return cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(converted, toType)); } // Non-optional to non-optional. return cs.cacheType(new (tc.Context) PointerToPointerExpr(expr, toType)); } case ConversionRestrictionKind::CFTollFreeBridgeToObjC: { auto foreignClass = fromType->getClassOrBoundGenericClass(); auto objcType = foreignClass->getAttrs().getAttribute() ->getObjCClass()->getDeclaredInterfaceType(); auto asObjCClass = cs.cacheType( new (tc.Context) ForeignObjectConversionExpr(expr, objcType)); return coerceToType(asObjCClass, toType, locator); } case ConversionRestrictionKind::ObjCTollFreeBridgeToCF: { auto foreignClass = toType->getClassOrBoundGenericClass(); auto objcType = foreignClass->getAttrs().getAttribute() ->getObjCClass()->getDeclaredInterfaceType(); Expr *result = coerceToType(expr, objcType, locator); if (!result) return nullptr; return cs.cacheType(new (tc.Context) ForeignObjectConversionExpr(result, toType)); } } } // Coercions from an lvalue: load or perform implicit address-of. We perform // these coercions first because they are often the first step in a multi-step // coercion. if (auto fromLValue = fromType->getAs()) { if (auto *toIO = toType->getAs()) { // In an 'inout' operator like "i += 1", the operand is converted from // an implicit lvalue to an inout argument. assert(toIO->getObjectType()->isEqual(fromLValue->getObjectType())); return cs.cacheType(new (tc.Context) InOutExpr(expr->getStartLoc(), expr, toIO->getObjectType(), /*isImplicit*/ true)); } return coerceToType(addImplicitLoadExpr(cs, expr), toType, locator); } // Coercions to tuple type. if (auto toTuple = toType->getAs()) { // Coerce from a tuple to a tuple. if (auto fromTuple = fromType->getAs()) { SmallVector sources; SmallVector variadicArgs; if (!computeTupleShuffle(fromTuple, toTuple, sources, variadicArgs)) { return coerceTupleToTuple(expr, fromTuple, toTuple, locator, sources, variadicArgs); } } } // Coercion from a subclass to a superclass. // // FIXME: Can we rig things up so that we always have a Superclass // conversion restriction in this case? if (fromType->mayHaveSuperclass() && toType->getClassOrBoundGenericClass()) { for (auto fromSuperClass = fromType->getSuperclass(); fromSuperClass; fromSuperClass = fromSuperClass->getSuperclass()) { if (fromSuperClass->isEqual(toType)) { return coerceSuperclass(expr, toType, locator); } } } // Coercions to function type. if (auto toFunc = toType->getAs()) { // Default argument generator must return escaping functions. Therefore, we // leave an explicit escape to noescape cast here such that SILGen can skip // the cast and emit a code for the escaping function. bool isInDefaultArgumentContext = false; if (auto initalizerCtx = dyn_cast(cs.DC)) isInDefaultArgumentContext = (initalizerCtx->getInitializerKind() == InitializerKind::DefaultArgument); auto toEI = toFunc->getExtInfo(); auto fromFunc = fromType->getAs(); // Coercion to an autoclosure type produces an implicit closure. // The constraint solver only performs this conversion when the source // type is not an autoclosure function type. That's a weird rule in // some rules, but it's easy to follow here. Really we just shouldn't // represent autoclosures as a bit on function types. // FIXME: The type checker is more lenient, and allows @autoclosures to // be subtypes of non-@autoclosures, which is bogus. if (toFunc->isAutoClosure() && (!fromFunc || !fromFunc->isAutoClosure())) { // The function type without @noescape if we are in the default argument // context. auto newToFuncType = toFunc; // Remove the noescape attribute so that we can apply a separate function // conversion instruction if we are in a default argument context. if (isInDefaultArgumentContext && toEI.isNoEscape()) newToFuncType = toFunc->withExtInfo(toEI.withNoEscape(false)) ->castTo(); // Convert the value to the expected result type of the function. expr = coerceToType( expr, toFunc->getResult(), locator.withPathElement(ConstraintLocator::AutoclosureResult)); // We'll set discriminator values on all the autoclosures in a // later pass. auto discriminator = AutoClosureExpr::InvalidDiscriminator; auto closure = cs.cacheType(new (tc.Context) AutoClosureExpr( expr, newToFuncType, discriminator, dc)); closure->setParameterList(ParameterList::createEmpty(tc.Context)); // Compute the capture list, now that we have analyzed the expression. tc.ClosuresWithUncomputedCaptures.push_back(closure); // Apply the noescape conversion. if (!newToFuncType->isEqual(toFunc)) { assert(isInDefaultArgumentContext); assert(newToFuncType ->withExtInfo(newToFuncType->getExtInfo().withNoEscape(true)) ->isEqual(toFunc)); return cs.cacheType(new (tc.Context) FunctionConversionExpr(closure, toFunc)); } return closure; } // Coercion from one function type to another, this produces a // FunctionConversionExpr in its full generality. if (fromFunc) { // If we have a ClosureExpr, then we can safely propagate the 'no escape' // bit to the closure without invalidating prior analysis. auto fromEI = fromFunc->getExtInfo(); if (toEI.isNoEscape() && !fromEI.isNoEscape()) { auto newFromFuncType = fromFunc->withExtInfo(fromEI.withNoEscape()); if (!isInDefaultArgumentContext && applyTypeToClosureExpr(cs, expr, newFromFuncType)) { fromFunc = newFromFuncType->castTo(); // Propagating the 'no escape' bit might have satisfied the entire // conversion. If so, we're done, otherwise keep converting. if (fromFunc->isEqual(toType)) return expr; } else if (isInDefaultArgumentContext) { // First apply the conversion *without* noescape attribute. if (!newFromFuncType->isEqual(toType)) { auto escapingToFuncTy = toFunc->withExtInfo(toEI.withNoEscape(false)); maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc); expr = cs.cacheType(new (tc.Context) FunctionConversionExpr( expr, escapingToFuncTy)); } // Apply an explict function conversion *only* for the escape to // noescape conversion. This conversion will be stripped by the // default argument generator. (We can't return a @noescape function) auto newExpr = cs.cacheType(new (tc.Context) FunctionConversionExpr(expr, toFunc)); return newExpr; } } maybeDiagnoseUnsupportedFunctionConversion(cs, expr, toFunc); return cs.cacheType(new (tc.Context) FunctionConversionExpr(expr, toType)); } } // Coercions from metadata to objects. if (auto fromMeta = fromType->getAs()) { if (toType->isAnyObject()) { assert(cs.getASTContext().LangOpts.EnableObjCInterop && "metatype-to-object conversion requires objc interop"); if (fromMeta->is()) { assert(fromMeta->getInstanceType()->mayHaveSuperclass() && "metatype-to-object input should be a class metatype"); return cs.cacheType( new (tc.Context) ClassMetatypeToObjectExpr(expr, toType)); } if (fromMeta->is()) { assert(fromMeta->getInstanceType()->getCanonicalType() ->getExistentialLayout().requiresClass() && "metatype-to-object input should be a class metatype"); return cs.cacheType( new (tc.Context) ExistentialMetatypeToObjectExpr(expr, toType)); } llvm_unreachable("unhandled metatype kind"); } if (auto toClass = toType->getClassOrBoundGenericClass()) { if (toClass->getName() == cs.getASTContext().Id_Protocol && toClass->getModuleContext()->getName() == cs.getASTContext().Id_ObjectiveC) { assert(cs.getASTContext().LangOpts.EnableObjCInterop && "metatype-to-object conversion requires objc interop"); assert(fromMeta->is() && fromMeta->getInstanceType()->is() && "protocol-metatype-to-Protocol only works for single " "protocols"); return cs.cacheType( new (tc.Context) ProtocolMetatypeToObjectExpr(expr, toType)); } } } // Coercions from a type to an existential type. if (toType->isAnyExistentialType()) { return coerceExistential(expr, toType, locator); } if (toType->getOptionalObjectType() && cs.getType(expr)->getOptionalObjectType()) { return coerceOptionalToOptional(expr, toType, locator, typeFromPattern); } // Coercion to Optional. if (auto toGenericType = toType->getAs()) { if (toGenericType->getDecl()->isOptionalDecl()) { tc.requireOptionalIntrinsics(expr->getLoc()); Type valueType = toGenericType->getGenericArgs()[0]; expr = coerceToType(expr, valueType, locator); if (!expr) return nullptr; auto *result = cs.cacheType(new (tc.Context) InjectIntoOptionalExpr(expr, toType)); diagnoseOptionalInjection(result); return result; } } // Coercion from one metatype to another. if (fromType->is() && toType->is()) { auto toMeta = toType->castTo(); return cs.cacheType(new (tc.Context) MetatypeConversionExpr(expr, toMeta)); } // Unresolved types come up in diagnostics for lvalue and inout types. if (fromType->hasUnresolvedType() || toType->hasUnresolvedType()) return cs.cacheType(new (tc.Context) UnresolvedTypeConversionExpr(expr, toType)); llvm_unreachable("Unhandled coercion"); } /// Adjust the given type to become the self type when referring to /// the given member. static Type adjustSelfTypeForMember(Type baseTy, ValueDecl *member, AccessSemantics semantics, DeclContext *UseDC) { auto baseObjectTy = baseTy->getWithoutSpecifierType(); if (isa(member)) return baseObjectTy; if (auto func = dyn_cast(member)) { // If 'self' is an inout type, turn the base type into an lvalue // type with the same qualifiers. if (func->isMutating()) return InOutType::get(baseObjectTy); // Otherwise, return the rvalue type. return baseObjectTy; } // If the base of the access is mutable, then we may be invoking a getter or // setter that requires the base to be mutable. auto *SD = cast(member); bool isSettableFromHere = SD->isSettable(UseDC) && (!UseDC->getASTContext().LangOpts.EnableAccessControl || SD->isSetterAccessibleFrom(UseDC)); // If neither the property's getter nor its setter are mutating, the base // can be an rvalue. if (!SD->isGetterMutating() && (!isSettableFromHere || !SD->isSetterMutating())) return baseObjectTy; // If we're calling an accessor, keep the base as an inout type, because the // getter may be mutating. auto strategy = SD->getAccessStrategy(semantics, isSettableFromHere ? AccessKind::ReadWrite : AccessKind::Read, UseDC); if (baseTy->is() && strategy.getKind() != AccessStrategy::Storage) return InOutType::get(baseObjectTy); // Accesses to non-function members in value types are done through an @lvalue // type. if (baseTy->is()) return LValueType::get(baseObjectTy); // Accesses to members in values of reference type (classes, metatypes) are // always done through a the reference to self. Accesses to value types with // a non-mutable self are also done through the base type. return baseTy; } Expr * ExprRewriter::coerceObjectArgumentToType(Expr *expr, Type baseTy, ValueDecl *member, AccessSemantics semantics, ConstraintLocatorBuilder locator) { Type toType = adjustSelfTypeForMember(baseTy, member, semantics, dc); // If our expression already has the right type, we're done. Type fromType = cs.getType(expr); if (fromType->isEqual(toType)) return expr; // If we're coercing to an rvalue type, just do it. auto toInOutTy = toType->getAs(); if (!toInOutTy) return coerceToType(expr, toType, locator); assert(fromType->is() && "Can only convert lvalues to inout"); auto &ctx = cs.getTypeChecker().Context; // Use InOutExpr to convert it to an explicit inout argument for the // receiver. return cs.cacheType(new (ctx) InOutExpr(expr->getStartLoc(), expr, toInOutTy->getInOutObjectType(), /*isImplicit*/ true)); } Expr *ExprRewriter::convertLiteral(Expr *literal, Type type, Type openedType, ProtocolDecl *protocol, TypeOrName literalType, DeclName literalFuncName, ProtocolDecl *builtinProtocol, TypeOrName builtinLiteralType, DeclName builtinLiteralFuncName, bool (*isBuiltinArgType)(Type), Diag<> brokenProtocolDiag, Diag<> brokenBuiltinProtocolDiag) { auto &tc = cs.getTypeChecker(); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; auto setType = [&](Expr *E, Type Ty) { cs.setType(E, Ty); }; // If coercing a literal to an unresolved type, we don't try to look up the // witness members, just do it. if (type->is()) { // Instead of updating the literal expr in place, allocate a new node. This // avoids issues where Builtin types end up on expr nodes and pollute // diagnostics. literal = cast(literal)->shallowClone(tc.Context, setType, getType); // The literal expression has this type. cs.setType(literal, type); return literal; } // Check whether this literal type conforms to the builtin protocol. Optional builtinConformance; if (builtinProtocol && (builtinConformance = tc.conformsToProtocol( type, builtinProtocol, cs.DC, (ConformanceCheckFlags::InExpression)))) { // Find the builtin argument type we'll use. Type argType; if (builtinLiteralType.is()) argType = builtinLiteralType.get(); else argType = tc.getWitnessType(type, builtinProtocol, *builtinConformance, builtinLiteralType.get(), brokenBuiltinProtocolDiag); if (!argType) return nullptr; // Make sure it's of an appropriate builtin type. if (isBuiltinArgType && !isBuiltinArgType(argType)) { tc.diagnose(builtinProtocol->getLoc(), brokenBuiltinProtocolDiag); return nullptr; } // Instead of updating the literal expr in place, allocate a new node. This // avoids issues where Builtin types end up on expr nodes and pollute // diagnostics. literal = cast(literal)->shallowClone(tc.Context, setType, getType); // The literal expression has this type. cs.setType(literal, argType); // Call the builtin conversion operation. // FIXME: Bogus location info. Expr *base = TypeExpr::createImplicitHack(literal->getLoc(), type, tc.Context); cs.cacheExprTypes(base); cs.setExprTypes(base); cs.setExprTypes(literal); SmallVector arguments = { literal }; Expr *result = tc.callWitness(base, dc, builtinProtocol, *builtinConformance, builtinLiteralFuncName, arguments, brokenBuiltinProtocolDiag); if (result) cs.cacheExprTypes(result); return result; } // This literal type must conform to the (non-builtin) protocol. assert(protocol && "requirements should have stopped recursion"); auto conformance = tc.conformsToProtocol(type, protocol, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "must conform to literal protocol"); // Figure out the (non-builtin) argument type if there is one. Type argType; if (literalType.is() && literalType.get().empty()) { // If there is no argument to the constructor function, then just pass in // the empty tuple. literal = cs.cacheType( TupleExpr::createEmpty(tc.Context, literal->getLoc(), literal->getLoc(), /*implicit*/!literal->getLoc().isValid())); } else { // Otherwise, figure out the type of the constructor function and coerce to // it. if (literalType.is()) argType = literalType.get(); else argType = tc.getWitnessType(type, protocol, *conformance, literalType.get(), brokenProtocolDiag); if (!argType) return nullptr; // Convert the literal to the non-builtin argument type via the // builtin protocol, first. // FIXME: Do we need an opened type here? literal = convertLiteral(literal, argType, argType, nullptr, Identifier(), Identifier(), builtinProtocol, builtinLiteralType, builtinLiteralFuncName, isBuiltinArgType, brokenProtocolDiag, brokenBuiltinProtocolDiag); if (!literal) return nullptr; } // Convert the resulting expression to the final literal type. // FIXME: Bogus location info. Expr *base = TypeExpr::createImplicitHack(literal->getLoc(), type, tc.Context); cs.cacheExprTypes(base); cs.setExprTypes(base); cs.setExprTypes(literal); literal = tc.callWitness(base, dc, protocol, *conformance, literalFuncName, literal, brokenProtocolDiag); if (literal) cs.cacheExprTypes(literal); return literal; } Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, Type type, ProtocolDecl *protocol, Identifier literalType, DeclName literalFuncName, ProtocolDecl *builtinProtocol, DeclName builtinLiteralFuncName, Diag<> brokenProtocolDiag, Diag<> brokenBuiltinProtocolDiag) { auto &tc = cs.getTypeChecker(); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; auto setType = [&](Expr *E, Type Ty) { cs.setType(E, Ty); }; // If coercing a literal to an unresolved type, we don't try to look up the // witness members, just do it. if (type->is()) { // Instead of updating the literal expr in place, allocate a new node. This // avoids issues where Builtin types end up on expr nodes and pollute // diagnostics. literal = cast(literal)->shallowClone(tc.Context, setType, getType); // The literal expression has this type. cs.setType(literal, type); return literal; } // Check whether this literal type conforms to the builtin protocol. If so, // initialize via the builtin protocol. Optional builtinConformance; if (builtinProtocol && (builtinConformance = tc.conformsToProtocol(type, builtinProtocol, cs.DC, ConformanceCheckFlags::InExpression))) { // Find the witness that we'll use to initialize the type via a builtin // literal. auto witness = findNamedWitnessImpl( tc, dc, type->getRValueType(), builtinProtocol, builtinLiteralFuncName, brokenBuiltinProtocolDiag, *builtinConformance); if (!witness || !isa(witness.getDecl())) return nullptr; // Form a reference to the builtin conversion function. // Set the builtin initializer. if (auto stringLiteral = dyn_cast(literal)) stringLiteral->setBuiltinInitializer(witness); else { cast(literal) ->setBuiltinInitializer(witness); } // The literal expression has this type. cs.setType(literal, type); return literal; } // This literal type must conform to the (non-builtin) protocol. assert(protocol && "requirements should have stopped recursion"); auto conformance = tc.conformsToProtocol(type, protocol, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "must conform to literal protocol"); // Dig out the literal type and perform a builtin literal conversion to it. if (!literalType.empty()) { // Extract the literal type. Type builtinLiteralType = tc.getWitnessType(type, protocol, *conformance, literalType, brokenProtocolDiag); if (!builtinLiteralType) return nullptr; // Perform the builtin conversion. if (!convertLiteralInPlace(literal, builtinLiteralType, nullptr, Identifier(), DeclName(), builtinProtocol, builtinLiteralFuncName, brokenProtocolDiag, brokenBuiltinProtocolDiag)) return nullptr; } // Find the witness that we'll use to initialize the literal value. auto witness = findNamedWitnessImpl( tc, dc, type->getRValueType(), protocol, literalFuncName, brokenProtocolDiag, conformance); if (!witness || !isa(witness.getDecl())) return nullptr; // Set the initializer. if (auto stringLiteral = dyn_cast(literal)) stringLiteral->setInitializer(witness); else cast(literal)->setInitializer(witness); // The literal expression has this type. cs.setType(literal, type); return literal; } Expr *ExprRewriter::finishApply(ApplyExpr *apply, Type openedType, ConstraintLocatorBuilder locator) { TypeChecker &tc = cs.getTypeChecker(); auto fn = apply->getFn(); bool hasTrailingClosure = isa(apply) && cast(apply)->hasTrailingClosure(); auto finishApplyOfDeclWithSpecialTypeCheckingSemantics = [&](ApplyExpr *apply, ValueDecl *decl, Type openedType) -> Expr* { switch (cs.TC.getDeclTypeCheckingSemantics(decl)) { case DeclTypeCheckingSemantics::TypeOf: { // Resolve into a DynamicTypeExpr. auto arg = apply->getArg(); SmallVector argLabelsScratch; auto fnType = cs.getType(fn)->getAs(); arg = coerceCallArguments(arg, fnType, apply, apply->getArgumentLabels(argLabelsScratch), hasTrailingClosure, locator.withPathElement( ConstraintLocator::ApplyArgument)); if (!arg) { return nullptr; } if (auto shuffle = dyn_cast(arg)) arg = shuffle->getSubExpr(); if (auto tuple = dyn_cast(arg)) arg = tuple->getElements()[0]; auto replacement = new (tc.Context) DynamicTypeExpr(apply->getFn()->getLoc(), apply->getArg()->getStartLoc(), arg, apply->getArg()->getEndLoc(), Type()); cs.setType(replacement, simplifyType(openedType)); return replacement; } case DeclTypeCheckingSemantics::WithoutActuallyEscaping: { // Resolve into a MakeTemporarilyEscapableExpr. auto arg = cast(apply->getArg()); assert(arg->getNumElements() == 2 && "should have two arguments"); auto nonescaping = arg->getElements()[0]; auto body = arg->getElements()[1]; auto bodyTy = cs.getType(body)->getWithoutSpecifierType(); auto bodyFnTy = bodyTy->castTo(); auto escapableParams = bodyFnTy->getParams(); auto resultType = bodyFnTy->getResult(); // The body is immediately called, so is obviously noescape. bodyFnTy = cast( bodyFnTy->withExtInfo(bodyFnTy->getExtInfo().withNoEscape())); body = coerceToType(body, bodyFnTy, locator); assert(body && "can't make nonescaping?!"); auto escapable = new (tc.Context) OpaqueValueExpr(apply->getFn()->getLoc(), Type()); cs.setType(escapable, escapableParams[0].getType()); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; auto callSubExpr = CallExpr::createImplicit(tc.Context, body, {escapable}, {}, getType); cs.cacheSubExprTypes(callSubExpr); cs.setType(callSubExpr->getArg(), AnyFunctionType::composeInput(tc.Context, escapableParams, false)); cs.setType(callSubExpr, resultType); auto replacement = new (tc.Context) MakeTemporarilyEscapableExpr(apply->getFn()->getLoc(), apply->getArg()->getStartLoc(), nonescaping, callSubExpr, apply->getArg()->getEndLoc(), escapable, apply); cs.setType(replacement, resultType); return replacement; } case DeclTypeCheckingSemantics::OpenExistential: { // Resolve into an OpenExistentialExpr. auto arg = cast(apply->getArg()); assert(arg->getNumElements() == 2 && "should have two arguments"); auto existential = cs.coerceToRValue(arg->getElements()[0]); auto body = cs.coerceToRValue(arg->getElements()[1]); auto bodyFnTy = cs.getType(body)->castTo(); auto openedTy = getBaseType(bodyFnTy, /*wantsRValue*/ false); auto resultTy = bodyFnTy->getResult(); // The body is immediately called, so is obviously noescape. bodyFnTy = cast( bodyFnTy->withExtInfo(bodyFnTy->getExtInfo().withNoEscape())); body = coerceToType(body, bodyFnTy, locator); assert(body && "can't make nonescaping?!"); auto openedInstanceTy = openedTy; auto existentialInstanceTy = cs.getType(existential); if (auto metaTy = openedTy->getAs()) { openedInstanceTy = metaTy->getInstanceType(); existentialInstanceTy = existentialInstanceTy ->castTo() ->getInstanceType(); } assert(openedInstanceTy->castTo() ->getOpenedExistentialType() ->isEqual(existentialInstanceTy)); auto opaqueValue = new (tc.Context) OpaqueValueExpr(apply->getLoc(), openedTy); cs.setType(opaqueValue, openedTy); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; auto callSubExpr = CallExpr::createImplicit(tc.Context, body, {opaqueValue}, {}, getType); cs.cacheSubExprTypes(callSubExpr); cs.setType(callSubExpr, resultTy); auto replacement = new (tc.Context) OpenExistentialExpr(existential, opaqueValue, callSubExpr, resultTy); cs.setType(replacement, resultTy); return replacement; } case DeclTypeCheckingSemantics::Normal: return nullptr; } llvm_unreachable("Unhandled DeclTypeCheckingSemantics in switch."); }; // The function is always an rvalue. fn = cs.coerceToRValue(fn); // Resolve applications of decls with special semantics. if (auto declRef = dyn_cast(getSemanticExprForDeclOrMemberRef(fn))) { if (auto special = finishApplyOfDeclWithSpecialTypeCheckingSemantics(apply, declRef->getDecl(), openedType)) { return special; } } bool unwrapResult = false; if (auto *IUOFnTy = dyn_cast(fn)) { unwrapResult = true; fn = IUOFnTy->getSubExpr(); } // If we're applying a function that resulted from a covariant // function conversion, strip off that conversion. // FIXME: It would be nicer if we could build the ASTs properly in the // first shot. Type covariantResultType; if (auto covariant = dyn_cast(fn)) { // Strip off one layer of application from the covariant result. covariantResultType = cs.getType(covariant)->castTo()->getResult(); // Use the subexpression as the function. fn = covariant->getSubExpr(); } // An immediate application of a closure literal is always noescape. if (getClosureLiteralExpr(fn)) { if (auto fnTy = cs.getType(fn)->getAs()) { fnTy = cast( fnTy->withExtInfo(fnTy->getExtInfo().withNoEscape())); fn = coerceToType(fn, fnTy, locator); } } apply->setFn(fn); // Check whether the argument is 'super'. bool isSuper = apply->getArg()->isSuperExpr(); // For function application, convert the argument to the input type of // the function. SmallVector argLabelsScratch; if (auto fnType = cs.getType(fn)->getAs()) { auto origArg = apply->getArg(); Expr *arg = coerceCallArguments(origArg, fnType, apply, apply->getArgumentLabels(argLabelsScratch), hasTrailingClosure, locator.withPathElement( ConstraintLocator::ApplyArgument)); if (!arg) { return nullptr; } apply->setArg(arg); cs.setType(apply, fnType->getResult()); apply->setIsSuper(isSuper); // We need the layout of nominal types returned from a function call. if (auto nominalResult = fnType->getResult()->getAnyNominal()) { tc.requestNominalLayout(nominalResult); } cs.setExprTypes(apply); Expr *result = tc.substituteInputSugarTypeForResult(apply); cs.cacheExprTypes(result); // If we have a covariant result type, perform the conversion now. if (covariantResultType) { if (covariantResultType->is()) result = cs.cacheType(new (tc.Context) CovariantFunctionConversionExpr( result, covariantResultType)); else result = cs.cacheType(new (tc.Context) CovariantReturnConversionExpr( result, covariantResultType)); } // Try closing the existential, if there is one. closeExistential(result, locator); // Extract all arguments. auto *CEA = arg; if (auto *TSE = dyn_cast(CEA)) CEA = TSE->getSubExpr(); // The argument is either a ParenExpr or TupleExpr. ArrayRef arguments; SmallVector Scratch; if (auto *TE = dyn_cast(CEA)) arguments = TE->getElements(); else if (auto *PE = dyn_cast(CEA)) { Scratch.push_back(PE->getSubExpr()); arguments = makeArrayRef(Scratch); } else { Scratch.push_back(apply->getArg()); arguments = makeArrayRef(Scratch); } for (auto arg: arguments) { bool isNoEscape = false; while (1) { if (auto AFT = cs.getType(arg)->getAs()) { isNoEscape = isNoEscape || AFT->isNoEscape(); } if (auto conv = dyn_cast(arg)) arg = conv->getSubExpr(); else if (auto *PE = dyn_cast(arg)) arg = PE->getSubExpr(); else break; } if (!isNoEscape) { if (auto DRE = dyn_cast(arg)) if (auto FD = dyn_cast(DRE->getDecl())) { tc.addEscapingFunctionAsArgument(FD, apply); } } } if (unwrapResult) return forceUnwrapResult(result); return result; } // FIXME: handle unwrapping everywhere else assert(!unwrapResult); // If this is an UnresolvedType in the system, preserve it. if (cs.getType(fn)->is()) { cs.setType(apply, cs.getType(fn)); return apply; } // We have a type constructor. auto metaTy = cs.getType(fn)->castTo(); auto ty = metaTy->getInstanceType(); if (!cs.isTypeReference(fn)) { bool isExistentialType = false; // If this is an attempt to initialize existential type. if (auto metaType = cs.getType(fn)->getAs()) { auto instanceType = metaType->getInstanceType(); isExistentialType = instanceType->isExistentialType(); } if (!isExistentialType) { // If the metatype value isn't a type expression, // the user should reference '.init' explicitly, for clarity. cs.TC .diagnose(apply->getArg()->getStartLoc(), diag::missing_init_on_metatype_initialization) .fixItInsert(apply->getArg()->getStartLoc(), ".init"); } } // If we're "constructing" a tuple type, it's simply a conversion. if (auto tupleTy = ty->getAs()) { // FIXME: Need an AST to represent this properly. return coerceToType(apply->getArg(), tupleTy, locator); } // We're constructing a value of nominal type. Look for the constructor or // enum element to use. auto ctorLocator = cs.getConstraintLocator( locator.withPathElement(ConstraintLocator::ApplyFunction) .withPathElement(ConstraintLocator::ConstructorMember)); auto selected = solution.getOverloadChoiceIfAvailable(ctorLocator); if (!selected) { assert(ty->hasError() || ty->hasUnresolvedType()); cs.setType(apply, ty); return apply; } assert(ty->getNominalOrBoundGenericNominal() || ty->is() || ty->isExistentialType() || ty->is()); // We have the constructor. auto choice = selected->choice; // Consider the constructor decl reference expr 'implicit', but the // constructor call expr itself has the apply's 'implicitness'. bool isDynamic = choice.getKind() == OverloadChoiceKind::DeclViaDynamic; Expr *declRef = buildMemberRef(fn, selected->openedFullType, /*dotLoc=*/SourceLoc(), choice, DeclNameLoc(fn->getEndLoc()), selected->openedType, locator, ctorLocator, /*Implicit=*/true, choice.getFunctionRefKind(), AccessSemantics::Ordinary, isDynamic); if (!declRef) return nullptr; declRef->setImplicit(apply->isImplicit()); apply->setFn(declRef); // Tail-recur to actually call the constructor. return finishApply(apply, openedType, locator); } // Return the precedence-yielding parent of 'expr', along with the index of // 'expr' as the child of that parent. The precedence-yielding parent is the // nearest ancestor of 'expr' which imposes a minimum precedence on 'expr'. // Right now that just means skipping over TupleExpr instances that only exist // to hold arguments to binary operators. static std::pair getPrecedenceParentAndIndex(Expr *expr, Expr *rootExpr) { auto parentMap = rootExpr->getParentMap(); auto it = parentMap.find(expr); if (it == parentMap.end()) { return { nullptr, 0 }; } Expr *parent = it->second; // Handle all cases where the answer isn't just going to be { parent, 0 }. if (auto tuple = dyn_cast(parent)) { // Get index of expression in tuple. auto tupleElems = tuple->getElements(); auto elemIt = std::find(tupleElems.begin(), tupleElems.end(), expr); assert(elemIt != tupleElems.end() && "expr not found in parent TupleExpr"); unsigned index = elemIt - tupleElems.begin(); it = parentMap.find(parent); if (it != parentMap.end()) { Expr *gparent = it->second; // Was this tuple just constructed for a binop? if (isa(gparent)) { return { gparent, index }; } } // Must be a tuple literal, function arg list, collection, etc. return { parent, index }; } else if (auto ifExpr = dyn_cast(parent)) { unsigned index; if (expr == ifExpr->getCondExpr()) { index = 0; } else if (expr == ifExpr->getThenExpr()) { index = 1; } else if (expr == ifExpr->getElseExpr()) { index = 2; } else { llvm_unreachable("expr not found in parent IfExpr"); } return { ifExpr, index }; } else if (auto assignExpr = dyn_cast(parent)) { unsigned index; if (expr == assignExpr->getSrc()) { index = 0; } else if (expr == assignExpr->getDest()) { index = 1; } else { llvm_unreachable("expr not found in parent AssignExpr"); } return { assignExpr, index }; } return { parent, 0 }; } /// Return true if, when replacing "" with " op ", /// parentheses must be added around "" to allow the new operator /// to bind correctly. bool swift::exprNeedsParensInsideFollowingOperator( TypeChecker &TC, DeclContext *DC, Expr *expr, PrecedenceGroupDecl *followingPG) { if (expr->isInfixOperator()) { auto exprPG = TC.lookupPrecedenceGroupForInfixOperator(DC, expr); if (!exprPG) return true; return TC.Context.associateInfixOperators(exprPG, followingPG) != Associativity::Left; } // We want to parenthesize a 'try?' on the LHS, but we don't care about // capturing the new operator inside a 'try' or 'try!'. if (isa(expr)) return true; return false; } /// Return true if, when replacing "" with " op " /// within the given root expression, parentheses must be added around /// the new operator to prevent it from binding incorrectly in the /// surrounding context. bool swift::exprNeedsParensOutsideFollowingOperator( TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr, PrecedenceGroupDecl *followingPG) { Expr *parent; unsigned index; std::tie(parent, index) = getPrecedenceParentAndIndex(expr, rootExpr); if (!parent || isa(parent) || isa(parent)) { return false; } if (parent->isInfixOperator()) { auto parentPG = TC.lookupPrecedenceGroupForInfixOperator(DC, parent); if (!parentPG) return true; // If the index is 0, this is on the LHS of the parent. if (index == 0) { return TC.Context.associateInfixOperators(followingPG, parentPG) != Associativity::Left; } else { return TC.Context.associateInfixOperators(parentPG, followingPG) != Associativity::Right; } } return true; } bool swift::exprNeedsParensBeforeAddingNilCoalescing(TypeChecker &TC, DeclContext *DC, Expr *expr) { auto asPG = TC.lookupPrecedenceGroup(DC, DC->getASTContext().Id_NilCoalescingPrecedence, SourceLoc()); if (!asPG) return true; return exprNeedsParensInsideFollowingOperator(TC, DC, expr, asPG); } bool swift::exprNeedsParensAfterAddingNilCoalescing(TypeChecker &TC, DeclContext *DC, Expr *expr, Expr *rootExpr) { auto asPG = TC.lookupPrecedenceGroup(DC, DC->getASTContext().Id_NilCoalescingPrecedence, SourceLoc()); if (!asPG) return true; return exprNeedsParensOutsideFollowingOperator(TC, DC, expr, rootExpr, asPG); } namespace { class ExprWalker : public ASTWalker { ExprRewriter &Rewriter; SmallVector ClosuresToTypeCheck; public: ExprWalker(ExprRewriter &Rewriter) : Rewriter(Rewriter) { } const SmallVectorImpl &getClosuresToTypeCheck() const { return ClosuresToTypeCheck; } std::pair walkToExprPre(Expr *expr) override { // For closures, update the parameter types and check the body. if (auto closure = dyn_cast(expr)) { Rewriter.simplifyExprType(expr); auto &cs = Rewriter.getConstraintSystem(); auto &tc = cs.getTypeChecker(); // Coerce the pattern, in case we resolved something. auto fnType = cs.getType(closure)->castTo(); auto *params = closure->getParameters(); if (tc.coerceParameterListToType(params, closure, fnType)) return { false, nullptr }; // Require layout of dependent types that could be used to materialize // metadata types/conformances during IRGen. tc.requestRequiredNominalTypeLayoutForParameters(params); // If this is a single-expression closure, convert the expression // in the body to the result type of the closure. if (closure->hasSingleExpressionBody()) { // Enter the context of the closure when type-checking the body. llvm::SaveAndRestore savedDC(Rewriter.dc, closure); Expr *body = closure->getSingleExpressionBody()->walk(*this); if (!body) return { false, nullptr }; if (body != closure->getSingleExpressionBody()) closure->setSingleExpressionBody(body); if (body) { // A single-expression closure with a non-Void expression type // coerces to a Void-returning function type. if (fnType->getResult()->isVoid() && !cs.getType(body)->isVoid()) { closure = Rewriter.coerceClosureExprToVoid(closure); // A single-expression closure with a Never expression type // coerces to any other function type. } else if (cs.getType(body)->isUninhabited()) { closure = Rewriter.coerceClosureExprFromNever(closure); } else { body = Rewriter.coerceToType(body, fnType->getResult(), cs.getConstraintLocator( closure, ConstraintLocator::ClosureResult)); if (!body) return { false, nullptr }; closure->setSingleExpressionBody(body); } } } else { // For other closures, type-check the body once we've finished with // the expression. cs.setExprTypes(closure); ClosuresToTypeCheck.push_back(closure); } tc.ClosuresWithUncomputedCaptures.push_back(closure); return { false, closure }; } Rewriter.walkToExprPre(expr); return { true, expr }; } Expr *walkToExprPost(Expr *expr) override { Expr *result = Rewriter.walkToExprPost(expr); auto &cs = Rewriter.getConstraintSystem(); if (result && cs.hasType(result)) Rewriter.checkForImportedUsedConformances(cs.getType(result)); return result; } /// \brief Ignore statements. std::pair walkToStmtPre(Stmt *stmt) override { return { false, stmt }; } /// \brief Ignore declarations. bool walkToDeclPre(Decl *decl) override { return false; } }; } // end anonymous namespace Expr *ConstraintSystem::coerceToRValue(Expr *expr) { auto &tc = getTypeChecker(); return tc.coerceToRValue(expr, [&](Expr *expr) { return getType(expr); }, [&](Expr *expr, Type type) { setType(expr, type); }); } /// Emit the fixes computed as part of the solution, returning true if we were /// able to emit an error message, or false if none of the fixits worked out. bool ConstraintSystem::applySolutionFixes(Expr *E, const Solution &solution) { llvm::SmallDenseMap> fixesPerExpr; applySolution(solution); for (auto *fix : solution.Fixes) fixesPerExpr[fix->getAnchor()].push_back(fix); auto diagnoseExprFailures = [&](Expr *expr) -> bool { auto fixes = fixesPerExpr.find(expr); if (fixes == fixesPerExpr.end()) return false; bool diagnosed = false; for (const auto *fix : fixes->second) diagnosed |= fix->diagnose(E); return diagnosed; }; bool diagnosed = false; E->forEachChildExpr([&](Expr *subExpr) -> Expr * { // Diagnose root expression at the end to // preserve ordering. if (subExpr != E) diagnosed |= diagnoseExprFailures(subExpr); return subExpr; }); diagnosed |= diagnoseExprFailures(E); return diagnosed; } /// \brief Apply a given solution to the expression, producing a fully /// type-checked expression. Expr *ConstraintSystem::applySolution(Solution &solution, Expr *expr, Type convertType, bool discardedExpr, bool skipClosures) { // If any fixes needed to be applied to arrive at this solution, resolve // them to specific expressions. if (!solution.Fixes.empty()) { if (shouldSuppressDiagnostics()) return nullptr; // If we can diagnose the problem with the fixits that we've pre-assumed, // do so now. if (applySolutionFixes(expr, solution)) return nullptr; // If we didn't manage to diagnose anything well, so fall back to // diagnosing mining the system to construct a reasonable error message. diagnoseFailureForExpr(expr); return nullptr; } // Mark any normal conformances used in this solution as "used". for (auto &e : solution.Conformances) TC.markConformanceUsed(e.second, DC); ExprRewriter rewriter(*this, solution, shouldSuppressDiagnostics()); ExprWalker walker(rewriter); // Apply the solution to the expression. auto result = expr->walk(walker); if (!result) return nullptr; // If we're re-typechecking an expression for diagnostics, don't // visit closures that have non-single expression bodies. if (!skipClosures) { auto &tc = getTypeChecker(); bool hadError = false; for (auto *closure : walker.getClosuresToTypeCheck()) hadError |= tc.typeCheckClosureBody(closure); // If any of the closures failed to type check, bail. if (hadError) return nullptr; } // If we're supposed to convert the expression to some particular type, // do so now. if (convertType) { result = rewriter.coerceToType(result, convertType, getConstraintLocator(expr)); if (!result) return nullptr; } else if (getType(result)->hasLValueType() && !discardedExpr) { // We referenced an lvalue. Load it. result = rewriter.coerceToType(result, getType(result)->getRValueType(), getConstraintLocator(expr)); } if (result) rewriter.finalize(result); return result; } Expr *ConstraintSystem::applySolutionShallow(const Solution &solution, Expr *expr, bool suppressDiagnostics) { ExprRewriter rewriter(*this, solution, suppressDiagnostics); rewriter.walkToExprPre(expr); Expr *result = rewriter.walkToExprPost(expr); if (result) rewriter.finalize(result); return result; } Expr *Solution::coerceToType(Expr *expr, Type toType, ConstraintLocator *locator, bool ignoreTopLevelInjection, Optional typeFromPattern) const { auto &cs = getConstraintSystem(); ExprRewriter rewriter(cs, *this, /*suppressDiagnostics=*/false); Expr *result = rewriter.coerceToType(expr, toType, locator, typeFromPattern); if (!result) return nullptr; // If we were asked to ignore top-level optional injections, mark // the top-level injection (if any) as "diagnosed". if (ignoreTopLevelInjection) { if (auto injection = dyn_cast( result->getSemanticsProvidingExpr())) { rewriter.DiagnosedOptionalInjections.insert(injection); } } rewriter.finalize(result); return result; } // Determine whether this is a variadic witness. static bool isVariadicWitness(AbstractFunctionDecl *afd) { for (auto param : *afd->getParameters()) if (param->isVariadic()) return true; return false; } static bool argumentNamesMatch(Type argTy, ArrayRef names) { auto tupleType = argTy->getAs(); if (!tupleType) return names.size() == 1 && names[0].empty(); if (tupleType->getNumElements() != names.size()) return false; for (unsigned i = 0, n = tupleType->getNumElements(); i != n; ++i) { if (tupleType->getElement(i).getName() != names[i]) return false; } return true; } Expr *TypeChecker::callWitness(Expr *base, DeclContext *dc, ProtocolDecl *protocol, ProtocolConformanceRef conformance, DeclName name, MutableArrayRef arguments, Diag<> brokenProtocolDiag) { // Construct an empty constraint system and solution. ConstraintSystem cs(*this, dc, ConstraintSystemOptions()); for (auto *arg : arguments) cs.cacheType(arg); // Find the witness we need to use. auto type = base->getType(); assert(!type->hasTypeVariable() && "Building call to witness with unresolved base type!"); if (auto metaType = type->getAs()) type = metaType->getInstanceType(); auto witness = findNamedWitnessImpl( *this, dc, type->getRValueType(), protocol, name, brokenProtocolDiag); if (!witness || !isa(witness.getDecl())) return nullptr; auto *witnessFn = cast(witness.getDecl()); // Form a syntactic expression that describes the reference to the // witness. // FIXME: Egregious hack. auto unresolvedDot = new (Context) UnresolvedDotExpr( base, SourceLoc(), witness.getDecl()->getFullName(), DeclNameLoc(base->getEndLoc()), /*Implicit=*/true); unresolvedDot->setFunctionRefKind(FunctionRefKind::SingleApply); auto dotLocator = cs.getConstraintLocator(unresolvedDot); // Form a reference to the witness itself. Type openedFullType, openedType; std::tie(openedFullType, openedType) = cs.getTypeOfMemberReference(base->getType(), witness.getDecl(), dc, /*isDynamicResult=*/false, FunctionRefKind::DoubleApply, dotLocator); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; // Form the call argument. // FIXME: Standardize all callers to always provide all argument names, // rather than hack around this. CallExpr *call; auto argLabels = witness.getDecl()->getFullName().getArgumentNames(); if (arguments.size() == 1 && (isVariadicWitness(witnessFn) || argumentNamesMatch(cs.getType(arguments[0]), argLabels))) { call = CallExpr::create(Context, unresolvedDot, arguments[0], {}, {}, /*hasTrailingClosure=*/false, /*implicit=*/true, Type(), getType); } else { // The tuple should have the source range enclosing its arguments unless // they are invalid or there are no arguments. SourceLoc TupleStartLoc = base->getStartLoc(); SourceLoc TupleEndLoc = base->getEndLoc(); if (!arguments.empty()) { SourceLoc AltStartLoc = arguments.front()->getStartLoc(); SourceLoc AltEndLoc = arguments.back()->getEndLoc(); if (AltStartLoc.isValid() && AltEndLoc.isValid()) { TupleStartLoc = AltStartLoc; TupleEndLoc = AltEndLoc; } } call = CallExpr::create(Context, unresolvedDot, TupleStartLoc, arguments, argLabels, {}, TupleEndLoc, /*trailingClosure=*/nullptr, /*implicit=*/true, getType); } cs.cacheSubExprTypes(call); // Extract the arguments. SmallVector args; AnyFunctionType::decomposeInput(cs.getType(call->getArg()), args); // Add the conversion from the argument to the function parameter type. auto openedFuncType = openedType->castTo(); ::matchCallArguments( cs, /*isOperator=*/false, args, openedFuncType->getParams(), cs.getConstraintLocator(call, ConstraintLocator::ApplyArgument)); // Solve the system. SmallVector solutions; cs.cacheExprTypes(call); // If the system failed to produce a solution, post any available diagnostics. if (cs.solve(call, solutions) || solutions.size() != 1) { cs.salvage(solutions, base); return nullptr; } Solution &solution = solutions.front(); ExprRewriter rewriter(cs, solution, /*suppressDiagnostics=*/false); auto choice = OverloadChoice(openedFullType, witnessFn, FunctionRefKind::SingleApply); auto memberRef = rewriter.buildMemberRef( base, openedFullType, base->getStartLoc(), choice, DeclNameLoc(base->getEndLoc()), openedType, dotLocator, dotLocator, /*Implicit=*/true, FunctionRefKind::SingleApply, AccessSemantics::Ordinary, /*isDynamic=*/false); call->setFn(memberRef); // Call the witness. Expr *result = rewriter.finishApply(call, openedType, cs.getConstraintLocator(call)); if (!result) return nullptr; rewriter.finalize(result); return result; } Expr * Solution::convertBooleanTypeToBuiltinI1(Expr *expr, ConstraintLocator *locator) const { auto &cs = getConstraintSystem(); // Load lvalues here. expr = cs.coerceToRValue(expr); auto &tc = cs.getTypeChecker(); auto &ctx = tc.Context; auto type = cs.getType(expr); // We allow UnresolvedType is()) return expr; // Look for the builtin name. If we don't have it, we need to call the // general name via the witness table. NameLookupOptions lookupOptions = defaultMemberLookupOptions; if (isa(cs.DC)) lookupOptions |= NameLookupFlags::KnownPrivate; auto members = tc.lookupMember(cs.DC, type, tc.Context.Id_getBuiltinLogicValue, lookupOptions); // Find the builtin method. if (members.size() != 1) { tc.diagnose(expr->getLoc(), diag::broken_bool); return expr; } auto *builtinMethod = dyn_cast(members[0].getValueDecl()); if (!builtinMethod) { tc.diagnose(expr->getLoc(), diag::broken_bool); return expr; } // The method is not generic, so there are no substitutions. tc.validateDeclForNameLookup(builtinMethod); auto builtinMethodType = builtinMethod->getInterfaceType() ->castTo(); // Form an unbound reference to the builtin method. auto *declRef = new (ctx) DeclRefExpr(builtinMethod, DeclNameLoc(expr->getLoc()), /*Implicit=*/true); declRef->setFunctionRefKind(FunctionRefKind::DoubleApply); cs.setType(declRef, builtinMethodType); auto getType = [&](const Expr *E) -> Type { return cs.getType(E); }; // Apply 'self' to get the method value. auto *methodRef = new (ctx) DotSyntaxCallExpr(declRef, SourceLoc(), expr); cs.setType(methodRef, builtinMethodType->getResult()); // Apply the empty argument list to get the final result. auto *result = CallExpr::createImplicit(ctx, methodRef, { }, { }, getType); cs.setType(result, builtinMethodType->getResult() ->castTo()->getResult()); cs.setType(result->getArg(), ctx.TheEmptyTupleType); if (!cs.getType(result)->isBuiltinIntegerType(1)) { tc.diagnose(expr->getLoc(), diag::broken_bool); return result; } return result; } Expr *Solution::convertOptionalToBool(Expr *expr, ConstraintLocator *locator) const { auto &cs = getConstraintSystem(); auto &tc = cs.getTypeChecker(); tc.requireOptionalIntrinsics(expr->getLoc()); // Match the optional value against its `Some` case. auto &ctx = tc.Context; auto isSomeExpr = new (ctx) EnumIsCaseExpr(expr, ctx.getOptionalSomeDecl()); cs.setType(isSomeExpr, tc.lookupBoolType(cs.DC)); return isSomeExpr; }