From 4db510057f222e5db5d4614a53a924b23b0dc512 Mon Sep 17 00:00:00 2001 From: Parker Schuh Date: Thu, 28 Mar 2019 11:14:18 -0700 Subject: [PATCH] Convert ObjectLiteralExpr to not use tc.callWitness() or generate a SemanticExpr. For reference, all other literal types except dictionaries and string interpolation have been converted over to this form. --- include/swift/AST/Expr.h | 10 ++++++ lib/AST/ASTDumper.cpp | 2 ++ lib/SILGen/SILGenExpr.cpp | 9 ++++- lib/Sema/CSApply.cpp | 29 ++++------------ lib/Sema/MiscDiagnostics.cpp | 4 +++ test/SILGen/literals.swift | 65 ++++++++++++++++++++++++++++++++++++ 6 files changed, 95 insertions(+), 24 deletions(-) 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/SILGen/SILGenExpr.cpp b/lib/SILGen/SILGenExpr.cpp index c490e36484928..3e3924fdfc84a 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..9edc4ba8e77fa 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -2213,7 +2213,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. @@ -2238,30 +2237,14 @@ namespace { 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; } 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/test/SILGen/literals.swift b/test/SILGen/literals.swift index 47471cdde1d9d..722e70ff5aa14 100644 --- a/test/SILGen/literals.swift +++ b/test/SILGen/literals.swift @@ -255,3 +255,68 @@ 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()) +}