diff --git a/include/swift/AST/Expr.h b/include/swift/AST/Expr.h index e6af2df8196bf..7af6c2080b537 100644 --- a/include/swift/AST/Expr.h +++ b/include/swift/AST/Expr.h @@ -1135,6 +1135,7 @@ class ObjectLiteralExpr final Expr *Arg; Expr *SemanticExpr; SourceLoc PoundLoc; + ConcreteDeclRef Initializer; ObjectLiteralExpr(SourceLoc PoundLoc, LiteralKind LitKind, Expr *Arg, @@ -1195,6 +1196,15 @@ class ObjectLiteralExpr final StringRef getLiteralKindPlainName() const; + /// Retrieve the initializer that will be used to construct the 'object' + /// literal from the result of the initializer. + ConcreteDeclRef getInitializer() const { return Initializer; } + + /// Set the initializer that will be used to construct the 'object' literal. + void setInitializer(ConcreteDeclRef initializer) { + Initializer = initializer; + } + static bool classof(const Expr *E) { return E->getKind() == ExprKind::ObjectLiteral; } diff --git a/lib/AST/ASTDumper.cpp b/lib/AST/ASTDumper.cpp index 2a205bcd84592..e6844632658fe 100644 --- a/lib/AST/ASTDumper.cpp +++ b/lib/AST/ASTDumper.cpp @@ -1967,6 +1967,8 @@ class PrintExpr : public ExprVisitor { void visitObjectLiteralExpr(ObjectLiteralExpr *E) { printCommon(E, "object_literal") << " kind='" << E->getLiteralKindPlainName() << "'"; + PrintWithColorRAII(OS, LiteralValueColor) << " initializer="; + E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS()); printArgumentLabels(E->getArgumentLabels()); OS << "\n"; printRec(E->getArg()); diff --git a/lib/AST/ProtocolConformance.cpp b/lib/AST/ProtocolConformance.cpp index 13dd5944ec3c1..d17a89fb5355f 100644 --- a/lib/AST/ProtocolConformance.cpp +++ b/lib/AST/ProtocolConformance.cpp @@ -966,8 +966,23 @@ Witness SelfProtocolConformance::getWitness(ValueDecl *requirement, ConcreteDeclRef RootProtocolConformance::getWitnessDeclRef(ValueDecl *requirement, LazyResolver *resolver) const { - if (auto witness = getWitness(requirement, resolver)) - return witness.getDeclRef(); + if (auto witness = getWitness(requirement, resolver)) { + auto *witnessDecl = witness.getDecl(); + + // If the witness is generic, you have to call getWitness() and build + // your own substitutions in terms of the synthetic environment. + if (auto *witnessDC = dyn_cast(witnessDecl)) + assert(!witnessDC->isInnermostContextGeneric()); + + // If the witness is not generic, use type substitutions from the + // witness's parent. Don't use witness.getSubstitutions(), which + // are written in terms of the synthetic environment. + auto subs = + getType()->getContextSubstitutionMap(getDeclContext()->getParentModule(), + witnessDecl->getDeclContext()); + return ConcreteDeclRef(witness.getDecl(), subs); + } + return ConcreteDeclRef(); } @@ -1120,11 +1135,6 @@ SpecializedProtocolConformance::getWitnessDeclRef( auto witnessMap = baseWitness.getSubstitutions(); auto combinedMap = witnessMap.subst(specializationMap); - - // Fast path if the substitutions didn't change. - if (combinedMap == baseWitness.getSubstitutions()) - return baseWitness; - return ConcreteDeclRef(witnessDecl, combinedMap); } diff --git a/lib/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index e1d02a526018d..7a57c88145ffa 100644 --- a/lib/SILGen/SILGenExpr.cpp +++ b/lib/SILGen/SILGenExpr.cpp @@ -2346,7 +2346,14 @@ visitInterpolatedStringLiteralExpr(InterpolatedStringLiteralExpr *E, RValue RValueEmitter:: visitObjectLiteralExpr(ObjectLiteralExpr *E, SGFContext C) { - return visit(E->getSemanticExpr(), C); + ConcreteDeclRef init = E->getInitializer(); + auto *decl = cast(init.getDecl()); + AnyFunctionType *fnTy = decl->getMethodInterfaceType() + .subst(init.getSubstitutions()) + ->getAs(); + PreparedArguments args(fnTy->getParams(), E->getArg()); + return SGF.emitApplyAllocatingInitializer(SILLocation(E), init, + std::move(args), E->getType(), C); } RValue RValueEmitter:: diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 6e9da3712d9d8..6ff140658bd53 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -77,8 +77,6 @@ SubstitutionMap Solution::computeSubstitutions( 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 { @@ -88,9 +86,9 @@ SubstitutionMap Solution::computeSubstitutions( return ProtocolConformanceRef(protoType); } - return tc.conformsToProtocol(replacement, protoType, - getConstraintSystem().DC, - ConformanceCheckFlags::InExpression); + return TypeChecker::conformsToProtocol(replacement, protoType, + getConstraintSystem().DC, + ConformanceCheckFlags::InExpression); }; return SubstitutionMap::get(sig, @@ -425,7 +423,7 @@ namespace { if (!baseTy->is() && !baseTy->isAnyExistentialType()) { auto &tc = cs.getTypeChecker(); auto conformance = - tc.conformsToProtocol( + TypeChecker::conformsToProtocol( baseTy, proto, cs.DC, ConformanceCheckFlags::InExpression); if (conformance && conformance->isConcrete()) { @@ -1694,10 +1692,10 @@ namespace { // Try to find the conformance of the value type to _BridgedToObjectiveC. auto bridgedToObjectiveCConformance - = tc.conformsToProtocol(valueType, - bridgedProto, - cs.DC, - ConformanceCheckFlags::InExpression); + = TypeChecker::conformsToProtocol(valueType, + bridgedProto, + cs.DC, + ConformanceCheckFlags::InExpression); FuncDecl *fn = nullptr; @@ -1973,8 +1971,8 @@ namespace { ProtocolDecl *protocol = tc.getProtocol( expr->getLoc(), KnownProtocolKind::ExpressibleByStringLiteral); - if (!tc.conformsToProtocol(type, protocol, cs.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC, + ConformanceCheckFlags::InExpression)) { // If the type does not conform to ExpressibleByStringLiteral, it should // be ExpressibleByExtendedGraphemeClusterLiteral. protocol = tc.getProtocol( @@ -1983,8 +1981,8 @@ namespace { isStringLiteral = false; isGraphemeClusterLiteral = true; } - if (!tc.conformsToProtocol(type, protocol, cs.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol(type, protocol, cs.DC, + ConformanceCheckFlags::InExpression)) { // ... or it should be ExpressibleByUnicodeScalarLiteral. protocol = tc.getProtocol( expr->getLoc(), @@ -2105,8 +2103,8 @@ namespace { assert(proto && "Missing string interpolation protocol?"); auto conformance = - tc.conformsToProtocol(type, proto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(type, proto, cs.DC, + ConformanceCheckFlags::InExpression); assert(conformance && "string interpolation type conforms to protocol"); DeclName constrName(tc.Context, DeclBaseName::createConstructor(), argLabels); @@ -2213,7 +2211,6 @@ namespace { 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. @@ -2234,34 +2231,18 @@ namespace { auto proto = tc.getLiteralProtocol(expr); assert(proto && "Missing object literal protocol?"); auto conformance = - tc.conformsToProtocol(conformingType, proto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::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); + ConcreteDeclRef witness = + conformance->getWitnessByName(conformingType->getRValueType(), + constrName); + if (!witness || !isa(witness.getDecl())) + return nullptr; + expr->setInitializer(witness); return expr; } @@ -2898,8 +2879,8 @@ namespace { assert(arrayProto && "type-checked array literal w/o protocol?!"); auto conformance = - tc.conformsToProtocol(arrayTy, arrayProto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(arrayTy, arrayProto, cs.DC, + ConformanceCheckFlags::InExpression); assert(conformance && "Type does not conform to protocol?"); DeclName name(tc.Context, DeclBaseName::createConstructor(), @@ -2943,8 +2924,8 @@ namespace { KnownProtocolKind::ExpressibleByDictionaryLiteral); auto conformance = - tc.conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(dictionaryTy, dictionaryProto, cs.DC, + ConformanceCheckFlags::InExpression); if (!conformance) return nullptr; @@ -4572,7 +4553,6 @@ namespace { auto hashable = cs.getASTContext().getProtocol(KnownProtocolKind::Hashable); - auto &TC = cs.getTypeChecker(); auto fnType = overload.openedType->castTo(); for (const auto ¶m : fnType->getParams()) { auto indexType = simplifyType(param.getPlainType()); @@ -4580,8 +4560,8 @@ namespace { // verified by the solver, we just need to get it again // with all of the generic parameters resolved. auto hashableConformance = - TC.conformsToProtocol(indexType, hashable, cs.DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(indexType, hashable, cs.DC, + ConformanceCheckFlags::InExpression); assert(hashableConformance.hasValue()); conformances.push_back(*hashableConformance); @@ -6242,7 +6222,7 @@ Expr *ExprRewriter::coerceToType(Expr *expr, Type toType, // Find the conformance of the source type to Hashable. auto hashable = tc.Context.getProtocol(KnownProtocolKind::Hashable); auto conformance = - tc.conformsToProtocol( + TypeChecker::conformsToProtocol( cs.getType(expr), hashable, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "must conform to Hashable"); @@ -6748,8 +6728,8 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *literal, Optional builtinConformance; if (builtinProtocol && (builtinConformance = - tc.conformsToProtocol(type, builtinProtocol, cs.DC, - ConformanceCheckFlags::InExpression))) { + TypeChecker::conformsToProtocol(type, builtinProtocol, cs.DC, + ConformanceCheckFlags::InExpression))) { // Find the witness that we'll use to initialize the type via a builtin // literal. @@ -6780,7 +6760,7 @@ Expr *ExprRewriter::convertLiteralInPlace(Expr *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, + auto conformance = TypeChecker::conformsToProtocol(type, protocol, cs.DC, ConformanceCheckFlags::InExpression); assert(conformance && "must conform to literal protocol"); diff --git a/lib/Sema/CSBindings.cpp b/lib/Sema/CSBindings.cpp index 6258a705a552f..be679cebf0458 100644 --- a/lib/Sema/CSBindings.cpp +++ b/lib/Sema/CSBindings.cpp @@ -676,7 +676,7 @@ ConstraintSystem::getPotentialBindings(TypeVariableType *typeVar) { do { // If the type conforms to this protocol, we're covered. - if (tc.conformsToProtocol( + if (TypeChecker::conformsToProtocol( testType, protocol, DC, (ConformanceCheckFlags::InExpression | ConformanceCheckFlags::SkipConditionalRequirements))) { diff --git a/lib/Sema/CSDiag.cpp b/lib/Sema/CSDiag.cpp index 55648f3829a91..ebe79ebcf8a0e 100644 --- a/lib/Sema/CSDiag.cpp +++ b/lib/Sema/CSDiag.cpp @@ -1212,7 +1212,7 @@ bool FailureDiagnosis::diagnoseGeneralConversionFailure(Constraint *constraint){ } // Emit a conformance error through conformsToProtocol. - if (auto conformance = CS.TC.conformsToProtocol( + if (auto conformance = TypeChecker::conformsToProtocol( fromType, PT->getDecl(), CS.DC, ConformanceCheckFlags::InExpression, expr->getLoc())) { if (conformance->isAbstract() || @@ -1724,8 +1724,8 @@ static bool conformsToKnownProtocol(Type fromType, KnownProtocolKind kind, if (!proto) return false; - if (CS.TC.conformsToProtocol(fromType, proto, CS.DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol(fromType, proto, CS.DC, + ConformanceCheckFlags::InExpression)) { return true; } @@ -1745,7 +1745,7 @@ static Type isRawRepresentable(Type fromType, const ConstraintSystem &CS) { if (!rawReprType) return Type(); - auto conformance = CS.TC.conformsToProtocol( + auto conformance = TypeChecker::conformsToProtocol( fromType, rawReprType, CS.DC, ConformanceCheckFlags::InExpression); if (!conformance) return Type(); @@ -2122,8 +2122,8 @@ bool FailureDiagnosis::diagnoseContextualConversionError( if (auto errorCodeProtocol = TC.Context.getProtocol(KnownProtocolKind::ErrorCodeProtocol)) { if (auto conformance = - TC.conformsToProtocol(CS.getType(expr), errorCodeProtocol, CS.DC, - ConformanceCheckFlags::InExpression)) { + TypeChecker::conformsToProtocol(CS.getType(expr), errorCodeProtocol, CS.DC, + ConformanceCheckFlags::InExpression)) { Type errorCodeType = CS.getType(expr); Type errorType = conformance->getTypeWitnessByName(errorCodeType, @@ -6261,8 +6261,8 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) { // Check to see if the contextual type conforms. if (auto Conformance - = CS.TC.conformsToProtocol(contextualType, ALC, CS.DC, - ConformanceCheckFlags::InExpression)) { + = TypeChecker::conformsToProtocol(contextualType, ALC, CS.DC, + ConformanceCheckFlags::InExpression)) { Type contextualElementType = Conformance->getTypeWitnessByName( contextualType, CS.getASTContext().Id_ArrayLiteralElement) @@ -6286,8 +6286,8 @@ bool FailureDiagnosis::visitArrayExpr(ArrayExpr *E) { if (!DLC) return visitExpr(E); - if (CS.TC.conformsToProtocol(contextualType, DLC, CS.DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol(contextualType, DLC, CS.DC, + ConformanceCheckFlags::InExpression)) { // If the contextual type conforms to ExpressibleByDictionaryLiteral and // this is an empty array, then they meant "[:]". auto numElements = E->getNumElements(); @@ -6344,7 +6344,7 @@ bool FailureDiagnosis::visitDictionaryExpr(DictionaryExpr *E) { // Validate the contextual type conforms to ExpressibleByDictionaryLiteral // and figure out what the contextual Key/Value types are in place. - auto Conformance = CS.TC.conformsToProtocol( + auto Conformance = TypeChecker::conformsToProtocol( contextualType, DLC, CS.DC, ConformanceCheckFlags::InExpression); if (!Conformance) { diagnose(E->getStartLoc(), diag::type_is_not_dictionary, contextualType) diff --git a/lib/Sema/CSGen.cpp b/lib/Sema/CSGen.cpp index 1403197f0237b..32b15bfa4afab 100644 --- a/lib/Sema/CSGen.cpp +++ b/lib/Sema/CSGen.cpp @@ -577,8 +577,8 @@ namespace { // the literal. if (otherArgTy && otherArgTy->getAnyNominal()) { if (otherArgTy->isEqual(paramTy) && - tc.conformsToProtocol(otherArgTy, literalProto, CS.DC, - ConformanceCheckFlags::InExpression)) + TypeChecker::conformsToProtocol(otherArgTy, literalProto, CS.DC, + ConformanceCheckFlags::InExpression)) return true; } else if (Type defaultType = tc.getDefaultType(literalProto, CS.DC)) { // If there is a default type for the literal protocol, check whether diff --git a/lib/Sema/CSRanking.cpp b/lib/Sema/CSRanking.cpp index d0e57049170d3..9ebd37f0ba150 100644 --- a/lib/Sema/CSRanking.cpp +++ b/lib/Sema/CSRanking.cpp @@ -249,7 +249,7 @@ computeSelfTypeRelationship(TypeChecker &tc, DeclContext *dc, ValueDecl *decl1, // If the model type does not conform to the protocol, the bases are // unrelated. - auto conformance = tc.conformsToProtocol( + auto conformance = TypeChecker::conformsToProtocol( modelTy, proto, dc, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::SkipConditionalRequirements)); diff --git a/lib/Sema/CSSimplify.cpp b/lib/Sema/CSSimplify.cpp index ee62373280539..c1d18a3a30c9b 100644 --- a/lib/Sema/CSSimplify.cpp +++ b/lib/Sema/CSSimplify.cpp @@ -3329,7 +3329,7 @@ ConstraintSystem::SolutionKind ConstraintSystem::simplifyConformsToConstraint( case ConstraintKind::LiteralConformsTo: { // Check whether this type conforms to the protocol. if (auto conformance = - TC.conformsToProtocol( + TypeChecker::conformsToProtocol( type, protocol, DC, (ConformanceCheckFlags::InExpression| ConformanceCheckFlags::SkipConditionalRequirements))) { diff --git a/lib/Sema/CSSolver.cpp b/lib/Sema/CSSolver.cpp index e0553b48401b8..9ff2b5f94edfd 100644 --- a/lib/Sema/CSSolver.cpp +++ b/lib/Sema/CSSolver.cpp @@ -1671,11 +1671,11 @@ void ConstraintSystem::ArgumentInfoCollector::minimizeLiteralProtocols() { const auto &candidate = candidates[i]; auto first = - CS.TC.conformsToProtocol(candidate.second, candidates[result].first, - CS.DC, ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(candidate.second, candidates[result].first, + CS.DC, ConformanceCheckFlags::InExpression); auto second = - CS.TC.conformsToProtocol(candidates[result].second, candidate.first, - CS.DC, ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(candidates[result].second, candidate.first, + CS.DC, ConformanceCheckFlags::InExpression); if ((first && second) || (!first && !second)) return; @@ -1878,8 +1878,8 @@ void ConstraintSystem::sortDesignatedTypes( ++nextType; break; } else if (auto *protoDecl = dyn_cast(nominalTypes[i])) { - if (TC.conformsToProtocol(argType, protoDecl, DC, - ConformanceCheckFlags::InExpression)) { + if (TypeChecker::conformsToProtocol(argType, protoDecl, DC, + ConformanceCheckFlags::InExpression)) { std::swap(nominalTypes[nextType], nominalTypes[i]); ++nextType; break; diff --git a/lib/Sema/CalleeCandidateInfo.cpp b/lib/Sema/CalleeCandidateInfo.cpp index 6628314c00b96..b74beb9366fab 100644 --- a/lib/Sema/CalleeCandidateInfo.cpp +++ b/lib/Sema/CalleeCandidateInfo.cpp @@ -1059,8 +1059,8 @@ bool CalleeCandidateInfo::diagnoseGenericParameterErrors(Expr *badArgExpr) { // FIXME: Add specific error for not subclass, if the archetype has a superclass? for (auto proto : paramArchetype->getConformsTo()) { - if (!CS.TC.conformsToProtocol(substitution, proto, CS.DC, - ConformanceCheckFlags::InExpression)) { + if (!TypeChecker::conformsToProtocol(substitution, proto, CS.DC, + ConformanceCheckFlags::InExpression)) { if (substitution->isEqual(argType)) { CS.TC.diagnose(badArgExpr->getLoc(), diag::cannot_convert_argument_value_protocol, diff --git a/lib/Sema/DerivedConformanceCodable.cpp b/lib/Sema/DerivedConformanceCodable.cpp index 438cbcceb8844..43402828d9512 100644 --- a/lib/Sema/DerivedConformanceCodable.cpp +++ b/lib/Sema/DerivedConformanceCodable.cpp @@ -72,25 +72,23 @@ enum CodableConformanceType { /// Returns whether the given type conforms to the given {En,De}codable /// protocol. /// -/// \param tc The typechecker to use in validating {En,De}codable conformance. -/// /// \param context The \c DeclContext the var declarations belong to. /// /// \param target The \c Type to validate. /// /// \param proto The \c ProtocolDecl to check conformance to. -static CodableConformanceType typeConformsToCodable(TypeChecker &tc, - DeclContext *context, +static CodableConformanceType typeConformsToCodable(DeclContext *context, Type target, bool isIUO, ProtocolDecl *proto) { target = context->mapTypeIntoContext(target); if (isIUO) - return typeConformsToCodable(tc, context, target->getOptionalObjectType(), + return typeConformsToCodable(context, target->getOptionalObjectType(), false, proto); - return tc.conformsToProtocol(target, proto, context, None) ? Conforms - : DoesNotConform; + return (TypeChecker::conformsToProtocol(target, proto, context, None) + ? Conforms + : DoesNotConform); } /// Returns whether the given variable conforms to the given {En,De}codable @@ -131,7 +129,7 @@ static CodableConformanceType varConformsToCodable(TypeChecker &tc, bool isIUO = varDecl->getAttrs().hasAttribute(); - return typeConformsToCodable(tc, context, varDecl->getValueInterfaceType(), + return typeConformsToCodable(context, varDecl->getValueInterfaceType(), isIUO, proto); } @@ -287,9 +285,9 @@ static CodingKeysValidity hasValidCodingKeysEnum(DerivedConformance &derived) { // Ensure that the type we found conforms to the CodingKey protocol. auto *codingKeyProto = C.getProtocol(KnownProtocolKind::CodingKey); - if (!tc.conformsToProtocol(codingKeysType, codingKeyProto, - derived.getConformanceContext(), - None)) { + if (!TypeChecker::conformsToProtocol(codingKeysType, codingKeyProto, + derived.getConformanceContext(), + None)) { // If CodingKeys is a typealias which doesn't point to a valid nominal type, // codingKeysTypeDecl will be nullptr here. In that case, we need to warn on // the location of the usage, since there isn't an underlying type to @@ -1082,7 +1080,8 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) { if (auto *superclassDecl = classDecl->getSuperclassDecl()) { DeclName memberName; auto superType = superclassDecl->getDeclaredInterfaceType(); - if (tc.conformsToProtocol(superType, proto, superclassDecl, None)) { + if (TypeChecker::conformsToProtocol(superType, proto, superclassDecl, + None)) { // super.init(from:) must be accessible. memberName = cast(requirement)->getFullName(); } else { @@ -1097,8 +1096,8 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) { if (result.empty()) { // No super initializer for us to call. - tc.diagnose(superclassDecl, diag::decodable_no_super_init_here, - requirement->getFullName(), memberName); + superclassDecl->diagnose(diag::decodable_no_super_init_here, + requirement->getFullName(), memberName); return false; } else if (result.size() > 1) { // There are multiple results for this lookup. We'll end up producing a @@ -1111,22 +1110,21 @@ static bool canSynthesize(DerivedConformance &derived, ValueDecl *requirement) { auto conformanceDC = derived.getConformanceContext(); if (!initializer->isDesignatedInit()) { // We must call a superclass's designated initializer. - tc.diagnose(initializer, - diag::decodable_super_init_not_designated_here, - requirement->getFullName(), memberName); + initializer->diagnose(diag::decodable_super_init_not_designated_here, + requirement->getFullName(), memberName); return false; } else if (!initializer->isAccessibleFrom(conformanceDC)) { // Cannot call an inaccessible method. auto accessScope = initializer->getFormalAccessScope(conformanceDC); - tc.diagnose(initializer, diag::decodable_inaccessible_super_init_here, - requirement->getFullName(), memberName, - accessScope.accessLevelForDiagnostics()); + initializer->diagnose(diag::decodable_inaccessible_super_init_here, + requirement->getFullName(), memberName, + accessScope.accessLevelForDiagnostics()); return false; } else if (initializer->getFailability() != OTK_None) { // We can't call super.init() if it's failable, since init(from:) // isn't failable. - tc.diagnose(initializer, diag::decodable_super_init_is_failable_here, - requirement->getFullName(), memberName); + initializer->diagnose(diag::decodable_super_init_is_failable_here, + requirement->getFullName(), memberName); return false; } } diff --git a/lib/Sema/DerivedConformanceEquatableHashable.cpp b/lib/Sema/DerivedConformanceEquatableHashable.cpp index 56aa16303a8ca..bffa7948a359e 100644 --- a/lib/Sema/DerivedConformanceEquatableHashable.cpp +++ b/lib/Sema/DerivedConformanceEquatableHashable.cpp @@ -1082,18 +1082,19 @@ static ValueDecl *deriveHashable_hashValue(DerivedConformance &derived) { // We can't form a Hashable conformance if Int isn't Hashable or // ExpressibleByIntegerLiteral. - if (!tc.conformsToProtocol(intType, - C.getProtocol(KnownProtocolKind::Hashable), - parentDC, None)) { - tc.diagnose(derived.ConformanceDecl, diag::broken_int_hashable_conformance); + if (!TypeChecker::conformsToProtocol(intType, + C.getProtocol(KnownProtocolKind::Hashable), + parentDC, None)) { + derived.ConformanceDecl->diagnose(diag::broken_int_hashable_conformance); return nullptr; } ProtocolDecl *intLiteralProto = C.getProtocol(KnownProtocolKind::ExpressibleByIntegerLiteral); - if (!tc.conformsToProtocol(intType, intLiteralProto, parentDC, None)) { - tc.diagnose(derived.ConformanceDecl, - diag::broken_int_integer_literal_convertible_conformance); + if (!TypeChecker::conformsToProtocol(intType, intLiteralProto, + parentDC, None)) { + derived.ConformanceDecl->diagnose( + diag::broken_int_integer_literal_convertible_conformance); return nullptr; } diff --git a/lib/Sema/DerivedConformanceRawRepresentable.cpp b/lib/Sema/DerivedConformanceRawRepresentable.cpp index a97d95918002e..25f205b5df0f4 100644 --- a/lib/Sema/DerivedConformanceRawRepresentable.cpp +++ b/lib/Sema/DerivedConformanceRawRepresentable.cpp @@ -421,7 +421,8 @@ deriveRawRepresentable_init(DerivedConformance &derived) { auto equatableProto = tc.getProtocol(enumDecl->getLoc(), KnownProtocolKind::Equatable); assert(equatableProto); - assert(tc.conformsToProtocol(rawType, equatableProto, enumDecl, None)); + assert(TypeChecker::conformsToProtocol(rawType, equatableProto, + enumDecl, None)); (void)equatableProto; (void)rawType; @@ -489,7 +490,8 @@ static bool canSynthesizeRawRepresentable(DerivedConformance &derived) { if (!equatableProto) return false; - if (!tc.conformsToProtocol(rawType, equatableProto, enumDecl, None)) + if (!TypeChecker::conformsToProtocol(rawType, equatableProto, + enumDecl, None)) return false; // There must be enum elements. diff --git a/lib/Sema/DerivedConformances.cpp b/lib/Sema/DerivedConformances.cpp index 5b66439ee4755..fd470139dca76 100644 --- a/lib/Sema/DerivedConformances.cpp +++ b/lib/Sema/DerivedConformances.cpp @@ -152,7 +152,7 @@ ValueDecl *DerivedConformance::getDerivableRequirement(TypeChecker &tc, auto proto = ctx.getProtocol(kind); if (!proto) return nullptr; - if (auto conformance = tc.conformsToProtocol( + if (auto conformance = TypeChecker::conformsToProtocol( nominal->getDeclaredInterfaceType(), proto, nominal, ConformanceCheckFlags::SkipConditionalRequirements)) { auto DC = conformance->getConcrete()->getDeclContext(); diff --git a/lib/Sema/MiscDiagnostics.cpp b/lib/Sema/MiscDiagnostics.cpp index 9d6361bcee2cc..95b6bc739e9a7 100644 --- a/lib/Sema/MiscDiagnostics.cpp +++ b/lib/Sema/MiscDiagnostics.cpp @@ -124,6 +124,10 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E, if (isa(Base)) checkUseOfMetaTypeName(Base); + if (auto *OLE = dyn_cast(E)) { + CallArgs.insert(OLE->getArg()); + } + if (auto *SE = dyn_cast(E)) CallArgs.insert(SE->getIndex()); diff --git a/lib/Sema/TypeCheckAttr.cpp b/lib/Sema/TypeCheckAttr.cpp index 1723735d4f8c9..ac6f128c5170b 100644 --- a/lib/Sema/TypeCheckAttr.cpp +++ b/lib/Sema/TypeCheckAttr.cpp @@ -897,8 +897,8 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, if (!hasKeywordArguments) { auto arrayLitProto = TC.Context.getProtocol(KnownProtocolKind::ExpressibleByArrayLiteral); - return TC.conformsToProtocol(argType, arrayLitProto, DC, - ConformanceCheckOptions()).hasValue(); + return TypeChecker::conformsToProtocol(argType, arrayLitProto, DC, + ConformanceCheckOptions()).hasValue(); } // If keyword arguments, check that argument type conforms to // `ExpressibleByDictionaryLiteral` and that the `Key` associated type @@ -907,15 +907,15 @@ bool swift::isValidDynamicCallableMethod(FuncDecl *decl, DeclContext *DC, TC.Context.getProtocol(KnownProtocolKind::ExpressibleByStringLiteral); auto dictLitProto = TC.Context.getProtocol(KnownProtocolKind::ExpressibleByDictionaryLiteral); - auto dictConf = TC.conformsToProtocol(argType, dictLitProto, DC, - ConformanceCheckOptions()); + auto dictConf = TypeChecker::conformsToProtocol(argType, dictLitProto, DC, + ConformanceCheckOptions()); if (!dictConf) return false; auto lookup = dictLitProto->lookupDirect(TC.Context.Id_Key); auto keyAssocType = cast(lookup[0])->getDeclaredInterfaceType(); auto keyType = dictConf.getValue().getAssociatedType(argType, keyAssocType); - return TC.conformsToProtocol(keyType, stringLitProtocol, DC, - ConformanceCheckOptions()).hasValue(); + return TypeChecker::conformsToProtocol(keyType, stringLitProtocol, DC, + ConformanceCheckOptions()).hasValue(); } /// Returns true if the given nominal type has a valid implementation of a @@ -1004,8 +1004,8 @@ bool swift::isValidStringDynamicMemberLookup(SubscriptDecl *decl, TC.Context.getProtocol(KnownProtocolKind::ExpressibleByStringLiteral); // If this is `subscript(dynamicMember: String*)` - return bool(TC.conformsToProtocol(paramType, stringLitProto, DC, - ConformanceCheckOptions())); + return bool(TypeChecker::conformsToProtocol(paramType, stringLitProto, DC, + ConformanceCheckOptions())); } bool swift::isValidKeyPathDynamicMemberLookup(SubscriptDecl *decl, @@ -1490,8 +1490,9 @@ void AttributeChecker::checkApplicationMainAttribute(DeclAttribute *attr, } if (!ApplicationDelegateProto || - !TC.conformsToProtocol(CD->getDeclaredType(), ApplicationDelegateProto, - CD, None)) { + !TypeChecker::conformsToProtocol(CD->getDeclaredType(), + ApplicationDelegateProto, + CD, None)) { TC.diagnose(attr->getLocation(), diag::attr_ApplicationMain_not_ApplicationDelegate, applicationMainKind); diff --git a/lib/Sema/TypeCheckAvailability.cpp b/lib/Sema/TypeCheckAvailability.cpp index fc67ed345b057..85b279332122d 100644 --- a/lib/Sema/TypeCheckAvailability.cpp +++ b/lib/Sema/TypeCheckAvailability.cpp @@ -2627,10 +2627,10 @@ static bool isIntegerOrFloatingPointType(Type ty, DeclContext *DC, if (!integerType || !floatingType) return false; return - TC.conformsToProtocol(ty, integerType, DC, - ConformanceCheckFlags::InExpression) || - TC.conformsToProtocol(ty, floatingType, DC, - ConformanceCheckFlags::InExpression); + TypeChecker::conformsToProtocol(ty, integerType, DC, + ConformanceCheckFlags::InExpression) || + TypeChecker::conformsToProtocol(ty, floatingType, DC, + ConformanceCheckFlags::InExpression); } diff --git a/lib/Sema/TypeCheckConstraints.cpp b/lib/Sema/TypeCheckConstraints.cpp index 07f78f97e0bba..413872023e728 100644 --- a/lib/Sema/TypeCheckConstraints.cpp +++ b/lib/Sema/TypeCheckConstraints.cpp @@ -1993,7 +1993,7 @@ Expr *PreCheckExpression::simplifyTypeConstructionWithLiteralArg(Expr *E) { options |= ConformanceCheckFlags::InExpression; options |= ConformanceCheckFlags::SkipConditionalRequirements; - auto result = TC.conformsToProtocol(type, protocol, DC, options); + auto result = TypeChecker::conformsToProtocol(type, protocol, DC, options); if (!result || !result->isConcrete()) return nullptr; diff --git a/lib/Sema/TypeCheckDecl.cpp b/lib/Sema/TypeCheckDecl.cpp index 35e39b60c2e7f..0cf3c05f11b74 100644 --- a/lib/Sema/TypeCheckDecl.cpp +++ b/lib/Sema/TypeCheckDecl.cpp @@ -1488,7 +1488,8 @@ static void checkEnumRawValues(TypeChecker &TC, EnumDecl *ED) { // primitive literal protocols. auto conformsToProtocol = [&](KnownProtocolKind protoKind) { ProtocolDecl *proto = TC.getProtocol(ED->getLoc(), protoKind); - return TC.conformsToProtocol(rawTy, proto, ED->getDeclContext(), None); + return TypeChecker::conformsToProtocol(rawTy, proto, + ED->getDeclContext(), None); }; static auto otherLiteralProtocolKinds = { @@ -4486,7 +4487,7 @@ static void finalizeType(TypeChecker &TC, NominalTypeDecl *nominal) { TC.requestSuperclassLayout(CD); auto forceConformance = [&](ProtocolDecl *protocol) { - if (auto ref = TC.conformsToProtocol( + if (auto ref = TypeChecker::conformsToProtocol( CD->getDeclaredInterfaceType(), protocol, CD, ConformanceCheckFlags::SkipConditionalRequirements, SourceLoc())) { @@ -4949,10 +4950,10 @@ static void diagnoseClassWithoutInitializers(TypeChecker &tc, ASTContext &C = tc.Context; auto *decodableProto = C.getProtocol(KnownProtocolKind::Decodable); auto superclassType = superclassDecl->getDeclaredInterfaceType(); - if (auto ref = tc.conformsToProtocol(superclassType, decodableProto, - superclassDecl, - ConformanceCheckOptions(), - SourceLoc())) { + if (auto ref = TypeChecker::conformsToProtocol(superclassType, decodableProto, + superclassDecl, + ConformanceCheckOptions(), + SourceLoc())) { // super conforms to Decodable, so we've failed to inherit init(from:). // Let's suggest overriding it here. // diff --git a/lib/Sema/TypeCheckNameLookup.cpp b/lib/Sema/TypeCheckNameLookup.cpp index 9b87eee3c62ca..d849f289d7bde 100644 --- a/lib/Sema/TypeCheckNameLookup.cpp +++ b/lib/Sema/TypeCheckNameLookup.cpp @@ -231,11 +231,9 @@ namespace { // Dig out the protocol conformance. auto *foundProto = cast(foundDC); - auto resolver = DC->getASTContext().getLazyResolver(); - assert(resolver && "Need an active resolver"); - auto &tc = *static_cast(resolver); - auto conformance = tc.conformsToProtocol(conformingType, foundProto, DC, - conformanceOptions); + auto conformance = TypeChecker::conformsToProtocol(conformingType, + foundProto, DC, + conformanceOptions); if (!conformance) { // If there's no conformance, we have an existential // and we found a member from one of the protocols, and diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index c084baeaa9d25..2e7ab575646bd 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -1718,7 +1718,7 @@ checkIndividualConformance(NormalProtocolConformance *conformance, // Check that T conforms to all inherited protocols. for (auto InheritedProto : Proto->getInheritedProtocols()) { auto InheritedConformance = - TC.conformsToProtocol( + TypeChecker::conformsToProtocol( T, InheritedProto, DC, ConformanceCheckFlags::SkipConditionalRequirements, ComplainLoc); @@ -2932,7 +2932,8 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { // a member that could in turn satisfy *this* requirement. auto derivableProto = cast(derivable->getDeclContext()); if (auto conformance = - TC.conformsToProtocol(Adoptee, derivableProto, DC, None)) { + TypeChecker::conformsToProtocol(Adoptee, derivableProto, + DC, None)) { if (conformance->isConcrete()) (void)conformance->getConcrete()->getWitnessDecl(derivable, &TC); } @@ -3313,7 +3314,7 @@ CheckTypeWitnessResult swift::checkTypeWitness(TypeChecker &tc, DeclContext *dc, // Check protocol conformances. for (auto reqProto : genericSig->getConformsTo(depTy)) { - if (!tc.conformsToProtocol( + if (!TypeChecker::conformsToProtocol( contextType, reqProto, dc, ConformanceCheckFlags::SkipConditionalRequirements)) return CheckTypeWitnessResult(reqProto->getDeclaredType()); diff --git a/lib/Sema/TypeCheckProtocolInference.cpp b/lib/Sema/TypeCheckProtocolInference.cpp index 7bf44b6ff2166..8595602fddf88 100644 --- a/lib/Sema/TypeCheckProtocolInference.cpp +++ b/lib/Sema/TypeCheckProtocolInference.cpp @@ -970,7 +970,7 @@ Type AssociatedTypeInference::substCurrentTypeWitnesses(Type type) { // If that failed, check whether it's because of the conformance we're // evaluating. auto localConformance - = tc.conformsToProtocol( + = TypeChecker::conformsToProtocol( baseTy, assocType->getProtocol(), dc, ConformanceCheckFlags::SkipConditionalRequirements); if (!localConformance || localConformance->isAbstract() || diff --git a/lib/Sema/TypeCheckStmt.cpp b/lib/Sema/TypeCheckStmt.cpp index a07157ffa36b9..1cdfc4fc54083 100644 --- a/lib/Sema/TypeCheckStmt.cpp +++ b/lib/Sema/TypeCheckStmt.cpp @@ -739,9 +739,9 @@ class StmtChecker : public StmtVisitor { { Type sequenceType = sequence->getType(); auto conformance = - TC.conformsToProtocol(sequenceType, sequenceProto, DC, - ConformanceCheckFlags::InExpression, - sequence->getLoc()); + TypeChecker::conformsToProtocol(sequenceType, sequenceProto, DC, + ConformanceCheckFlags::InExpression, + sequence->getLoc()); if (!conformance) return nullptr; @@ -789,9 +789,9 @@ class StmtChecker : public StmtVisitor { // FIXME: Would like to customize the diagnostic emitted in // conformsToProtocol(). auto genConformance = - TC.conformsToProtocol(generatorTy, generatorProto, DC, - ConformanceCheckFlags::InExpression, - sequence->getLoc()); + TypeChecker::conformsToProtocol(generatorTy, generatorProto, DC, + ConformanceCheckFlags::InExpression, + sequence->getLoc()); if (!genConformance) return nullptr; diff --git a/test/SILGen/literals.swift b/test/SILGen/literals.swift index 47471cdde1d9d..df38a0e41bb29 100644 --- a/test/SILGen/literals.swift +++ b/test/SILGen/literals.swift @@ -255,3 +255,91 @@ func makeBasic() -> T { return T() } func throwingElement() throws -> [T] { return try [makeBasic(), makeThrowing()] } + +struct Color: _ExpressibleByColorLiteral { + init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) {} +} + +// CHECK-LABEL: sil hidden [ossa] @$s8literals16makeColorLiteralAA0C0VyF : $@convention(thin) () -> Color { +// CHECK: [[COLOR_METATYPE:%.*]] = metatype $@thin Color.Type +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0x3FFFADD2F1A9FBE76C8B +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[R:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0xBFFB978D4FDF3B645A1D +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[G:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0xBFF8C49BA5E353F7CED9 +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[B:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[VALUE:%.*]] = float_literal $Builtin.FPIEEE80, 0x3FFF8000000000000000 +// CHECK: [[METATYPE:%.*]] = metatype $@thin Float.Type +// CHECK: [[FN:%.*]] = function_ref @$sSf20_builtinFloatLiteralSfBf80__tcfC +// CHECK: [[A:%.*]] = apply [[FN]]([[VALUE]], [[METATYPE]]) : $@convention(method) (Builtin.FPIEEE80, @thin Float.Type) -> Float + +// CHECK: [[FN:%.*]] = function_ref @$s8literals5ColorV16_colorLiteralRed5green4blue5alphaACSf_S3ftcfC : $@convention(method) (Float, Float, Float, Float, @thin Color.Type) -> Color +// CHECK: [[LIT:%.*]] = apply [[FN]]([[R]], [[G]], [[B]], [[A]], [[COLOR_METATYPE]]) : $@convention(method) (Float, Float, Float, Float, @thin Color.Type) -> Color +// CHECK: return [[LIT]] : $Color +func makeColorLiteral() -> Color { + return #colorLiteral(red: 1.358, green: -0.074, blue: -0.012, alpha: 1.0) +} + +struct Image: _ExpressibleByImageLiteral { + init(imageLiteralResourceName: String) {} +} + +func makeTmpString() -> String { return "" } + +// CHECK-LABEL: sil hidden [ossa] @$s8literals16makeImageLiteralAA0C0VyF : $@convention(thin) () -> Image +// CHECK: [[METATYPE:%.*]] = metatype $@thin Image.Type +// CHECK: [[FN:%.*]] = function_ref @$s8literals13makeTmpStringSSyF : $@convention(thin) () -> @owned String +// CHECK: [[STR:%.*]] = apply [[FN]]() : $@convention(thin) () -> @owned String +// CHECK: [[FN:%.*]] = function_ref @$s8literals5ImageV24imageLiteralResourceNameACSS_tcfC : $@convention(method) (@owned String, @thin Image.Type) -> Image +// CHECK: [[LIT:%.*]] = apply [[FN]]([[STR]], [[METATYPE]]) : $@convention(method) (@owned String, @thin Image.Type) -> Image +// CHECK: return [[LIT]] : $Image +func makeImageLiteral() -> Image { + return #imageLiteral(resourceName: makeTmpString()) +} + +struct FileReference: _ExpressibleByFileReferenceLiteral { + init(fileReferenceLiteralResourceName: String) {} +} + +// CHECK-LABEL: sil hidden [ossa] @$s8literals24makeFileReferenceLiteralAA0cD0VyF : $@convention(thin) () -> FileReference +// CHECK: [[METATYPE:%.*]] = metatype $@thin FileReference.Type +// CHECK: [[FN:%.*]] = function_ref @$s8literals13makeTmpStringSSyF : $@convention(thin) () -> @owned String +// CHECK: [[STR:%.*]] = apply [[FN]]() : $@convention(thin) () -> @owned String +// CHECK: [[FN:%.*]] = function_ref @$s8literals13FileReferenceV04fileC19LiteralResourceNameACSS_tcfC +// CHECK: [[LIT:%.*]] = apply [[FN]]([[STR]], [[METATYPE]]) : $@convention(method) (@owned String, @thin FileReference.Type) -> FileReference +// CHECK: return [[LIT]] : $FileReference +func makeFileReferenceLiteral() -> FileReference { + return #fileLiteral(resourceName: makeTmpString()) +} + +class ReferenceColor { required init() {} } + +protocol Silly { + init() + init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) +} + +extension Silly { + init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) { + self.init() + } +} + +extension ReferenceColor : Silly, _ExpressibleByColorLiteral {} + +func makeColorLiteral() -> ReferenceColor { + return #colorLiteral(red: 1.358, green: -0.074, blue: -0.012, alpha: 1.0) +} + +// CHECK-LABEL: sil hidden [ossa] @$s8literals16makeColorLiteralAA09ReferenceC0CyxGylF : $@convention(thin) () -> @owned ReferenceColor +// CHECK: [[FN:%.*]] = function_ref @$s8literals5SillyPAAE16_colorLiteralRed5green4blue5alphaxSf_S3ftcfC : $@convention(method) <τ_0_0 where τ_0_0 : Silly> (Float, Float, Float, Float, @thick τ_0_0.Type) -> @out τ_0_0 +// CHECK: apply [[FN]]>(