Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions include/swift/AST/Expr.h
Original file line number Diff line number Diff line change
Expand Up @@ -1135,6 +1135,7 @@ class ObjectLiteralExpr final
Expr *Arg;
Expr *SemanticExpr;
SourceLoc PoundLoc;
ConcreteDeclRef Initializer;

ObjectLiteralExpr(SourceLoc PoundLoc, LiteralKind LitKind,
Expr *Arg,
Expand Down Expand Up @@ -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;
}
Expand Down
2 changes: 2 additions & 0 deletions lib/AST/ASTDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1967,6 +1967,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
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());
Expand Down
9 changes: 8 additions & 1 deletion lib/SILGen/SILGenExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<ConstructorDecl>(init.getDecl());
AnyFunctionType *fnTy = decl->getMethodInterfaceType()
.subst(init.getSubstitutions())
->getAs<AnyFunctionType>();
PreparedArguments args(fnTy->getParams(), E->getArg());
return SGF.emitApplyAllocatingInitializer(SILLocation(E), init,
std::move(args), E->getType(), C);
}

RValue RValueEmitter::
Expand Down
29 changes: 6 additions & 23 deletions lib/Sema/CSApply.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand All @@ -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<Expr *, 4> args;
if (!isa<TupleExpr>(expr->getArg()))
return nullptr;
auto tupleArg = cast<TupleExpr>(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<AbstractFunctionDecl>(witness.getDecl()))
return nullptr;
expr->setInitializer(witness);
return expr;
}

Expand Down
4 changes: 4 additions & 0 deletions lib/Sema/MiscDiagnostics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,10 @@ static void diagSyntacticUseRestrictions(TypeChecker &TC, const Expr *E,
if (isa<TypeExpr>(Base))
checkUseOfMetaTypeName(Base);

if (auto *OLE = dyn_cast<ObjectLiteralExpr>(E)) {
CallArgs.insert(OLE->getArg());
}

if (auto *SE = dyn_cast<SubscriptExpr>(E))
CallArgs.insert(SE->getIndex());

Expand Down
65 changes: 65 additions & 0 deletions test/SILGen/literals.swift
Original file line number Diff line number Diff line change
Expand Up @@ -255,3 +255,68 @@ func makeBasic<T : FooProtocol>() -> T { return T() }
func throwingElement<T : FooProtocol>() 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())
}