Skip to content

Commit 0b03721

Browse files
committed
Convert DictionaryExpr to not use tc.callWitness() or generate a SemanticExpr.
For reference, everything else except string interpolation has been migrated to this new form.
1 parent 735a884 commit 0b03721

File tree

10 files changed

+73
-98
lines changed

10 files changed

+73
-98
lines changed

include/swift/AST/Expr.h

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2128,8 +2128,6 @@ class CollectionExpr : public Expr {
21282128
SourceLoc RBracketLoc;
21292129
ConcreteDeclRef Initializer;
21302130

2131-
Expr *SemanticExpr = nullptr;
2132-
21332131
/// Retrieve the intrusive pointer storage from the subtype
21342132
Expr *const *getTrailingObjectsPointer() const;
21352133
Expr **getTrailingObjectsPointer() {
@@ -2194,9 +2192,6 @@ class CollectionExpr : public Expr {
21942192
SourceRange getSourceRange() const {
21952193
return SourceRange(LBracketLoc, RBracketLoc);
21962194
}
2197-
2198-
Expr *getSemanticExpr() const { return SemanticExpr; }
2199-
void setSemanticExpr(Expr *e) { SemanticExpr = e; }
22002195

22012196
static bool classof(const Expr *e) {
22022197
return e->getKind() >= ExprKind::First_CollectionExpr &&
@@ -2274,6 +2269,8 @@ class DictionaryExpr final : public CollectionExpr,
22742269
static bool classof(const Expr *e) {
22752270
return e->getKind() == ExprKind::Dictionary;
22762271
}
2272+
2273+
Type getElementType();
22772274
};
22782275

22792276
/// Subscripting expressions like a[i] that refer to an element within a

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2127,16 +2127,16 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
21272127
OS << '\n';
21282128
printRec(elt);
21292129
}
2130-
printSemanticExpr(E->getSemanticExpr());
21312130
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21322131
}
21332132
void visitDictionaryExpr(DictionaryExpr *E) {
21342133
printCommon(E, "dictionary_expr");
2134+
PrintWithColorRAII(OS, LiteralValueColor) << " initializer=";
2135+
E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS());
21352136
for (auto elt : E->getElements()) {
21362137
OS << '\n';
21372138
printRec(elt);
21382139
}
2139-
printSemanticExpr(E->getSemanticExpr());
21402140
PrintWithColorRAII(OS, ParenthesisColor) << ')';
21412141
}
21422142
void visitSubscriptExpr(SubscriptExpr *E) {

lib/AST/ASTWalker.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -525,8 +525,6 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
525525
}
526526

527527
Expr *visitCollectionExpr(CollectionExpr *E) {
528-
HANDLE_SEMANTIC_EXPR(E);
529-
530528
for (auto &elt : E->getElements())
531529
if (Expr *Sub = doIt(elt))
532530
elt = Sub;

lib/AST/Expr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1485,6 +1485,19 @@ Type ArrayExpr::getElementType() {
14851485
.subst(init.getSubstitutions());
14861486
}
14871487

1488+
Type DictionaryExpr::getElementType() {
1489+
auto init = getInitializer();
1490+
if (!init)
1491+
return Type();
1492+
1493+
auto *decl = cast<ConstructorDecl>(init.getDecl());
1494+
return decl->getMethodInterfaceType()
1495+
->getAs<AnyFunctionType>()
1496+
->getParams()[0]
1497+
.getPlainType()
1498+
.subst(init.getSubstitutions());
1499+
}
1500+
14881501
DictionaryExpr *DictionaryExpr::create(ASTContext &C, SourceLoc LBracketLoc,
14891502
ArrayRef<Expr*> Elements,
14901503
ArrayRef<SourceLoc> CommaLocs,

lib/SILGen/SILGenExpr.cpp

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,7 @@ namespace {
462462
RValue visitKeyPathExpr(KeyPathExpr *E, SGFContext C);
463463
RValue visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E,
464464
SGFContext C);
465-
RValue visitArrayExpr(ArrayExpr *E, SGFContext C);
466-
RValue visitDictionaryExpr(DictionaryExpr *E, SGFContext C);
465+
RValue visitCollectionExpr(CollectionExpr *E, SGFContext C);
467466
RValue visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E,
468467
SGFContext C);
469468
RValue visitInjectIntoOptionalExpr(InjectIntoOptionalExpr *E, SGFContext C);
@@ -3671,15 +3670,20 @@ visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) {
36713670
llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
36723671
}
36733672

3674-
RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) {
3673+
RValue RValueEmitter::visitCollectionExpr(CollectionExpr *E, SGFContext C) {
36753674
auto loc = SILLocation(E);
36763675
ArgumentScope scope(SGF, loc);
36773676

36783677
// CSApply builds ArrayExprs without an initializer for the trivial case
36793678
// of emitting varargs.
36803679
CanType arrayType, elementType;
36813680
if (E->getInitializer()) {
3682-
elementType = E->getElementType()->getCanonicalType();
3681+
if (auto *arrayExpr = dyn_cast<ArrayExpr>(E)) {
3682+
elementType = arrayExpr->getElementType()->getCanonicalType();
3683+
} else {
3684+
auto *dictionaryExpr = cast<DictionaryExpr>(E);
3685+
elementType = dictionaryExpr->getElementType()->getCanonicalType();
3686+
}
36833687
arrayType = ArraySliceType::get(elementType)->getCanonicalType();
36843688
} else {
36853689
arrayType = E->getType()->getCanonicalType();
@@ -3742,10 +3746,6 @@ RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) {
37423746
loc, E->getInitializer(), std::move(args), E->getType(), C);
37433747
}
37443748

3745-
RValue RValueEmitter::visitDictionaryExpr(DictionaryExpr *E, SGFContext C) {
3746-
return visit(E->getSemanticExpr(), C);
3747-
}
3748-
37493749
/// Flattens one level of optional from a nested optional value.
37503750
static ManagedValue flattenOptional(SILGenFunction &SGF, SILLocation loc,
37513751
ManagedValue optVal) {

lib/Sema/CSApply.cpp

Lines changed: 9 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -2929,65 +2929,20 @@ namespace {
29292929
if (!conformance)
29302930
return nullptr;
29312931

2932-
// Call the witness that builds the dictionary literal.
2933-
// FIXME: callWitness() may end up re-doing some work we already did
2934-
// to convert the dictionary literal elements to the (key, value) tuple.
2935-
// It would be nicer to re-use them.
2936-
// FIXME: Cache the name.
2937-
// FIXME: This location info is bogus.
2938-
Expr *typeRef = TypeExpr::createImplicitHack(expr->getLoc(), dictionaryTy,
2939-
tc.Context);
2940-
cs.cacheExprTypes(typeRef);
2941-
29422932
DeclName name(tc.Context, DeclBaseName::createConstructor(),
29432933
{ tc.Context.Id_dictionaryLiteral });
2944-
2945-
// Restructure the argument to provide the appropriate labels in the
2946-
// tuple.
2947-
SmallVector<TupleTypeElt, 4> typeElements;
2948-
SmallVector<Identifier, 4> names;
2949-
bool first = true;
2950-
for (auto elt : expr->getElements()) {
2951-
if (first) {
2952-
typeElements.push_back(TupleTypeElt(cs.getType(elt),
2953-
tc.Context.Id_dictionaryLiteral));
2954-
names.push_back(tc.Context.Id_dictionaryLiteral);
2955-
2956-
first = false;
2957-
continue;
2958-
}
2959-
2960-
typeElements.push_back(cs.getType(elt));
2961-
names.push_back(Identifier());
2962-
}
2963-
2964-
Type argType = TupleType::get(typeElements, tc.Context);
2965-
assert(isa<TupleType>(argType.getPointer()));
2966-
2967-
Expr *arg =
2968-
TupleExpr::create(tc.Context, expr->getLBracketLoc(),
2969-
expr->getElements(),
2970-
names,
2971-
{ },
2972-
expr->getRBracketLoc(),
2973-
/*HasTrailingClosure=*/false,
2974-
/*Implicit=*/true,
2975-
argType);
2976-
2977-
cs.cacheExprTypes(arg);
2978-
2979-
cs.setExprTypes(typeRef);
2980-
cs.setExprTypes(arg);
2981-
2982-
Expr *result = tc.callWitness(typeRef, dc, dictionaryProto,
2983-
*conformance, name, arg,
2984-
diag::dictionary_protocol_broken);
2985-
if (!result)
2934+
ConcreteDeclRef witness =
2935+
conformance->getWitnessByName(dictionaryTy->getRValueType(), name);
2936+
if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
29862937
return nullptr;
2938+
expr->setInitializer(witness);
29872939

2988-
cs.cacheExprTypes(result);
2940+
auto elementType = expr->getElementType();
2941+
for (auto &element : expr->getElements()) {
2942+
element = coerceToType(element, elementType,
2943+
cs.getConstraintLocator(element));
2944+
}
29892945

2990-
expr->setSemanticExpr(result);
29912946
return expr;
29922947
}
29932948

lib/Sema/CSDiag.cpp

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1280,7 +1280,6 @@ namespace {
12801280
llvm::DenseMap<Pattern*, Type> PatternTypes;
12811281
llvm::DenseMap<ParamDecl*, Type> ParamDeclTypes;
12821282
llvm::DenseMap<ParamDecl*, Type> ParamDeclInterfaceTypes;
1283-
llvm::DenseMap<CollectionExpr*, Expr*> CollectionSemanticExprs;
12841283
llvm::DenseSet<ValueDecl*> PossiblyInvalidDecls;
12851284
ExprTypeSaverAndEraser(const ExprTypeSaverAndEraser&) = delete;
12861285
void operator=(const ExprTypeSaverAndEraser&) = delete;
@@ -1340,15 +1339,6 @@ namespace {
13401339
P->setInvalid(false);
13411340
}
13421341

1343-
// If we have a CollectionExpr with a type checked SemanticExpr,
1344-
// remove it so we can recalculate a new semantic form.
1345-
if (auto *CE = dyn_cast<CollectionExpr>(expr)) {
1346-
if (auto SE = CE->getSemanticExpr()) {
1347-
TS->CollectionSemanticExprs[CE] = SE;
1348-
CE->setSemanticExpr(nullptr);
1349-
}
1350-
}
1351-
13521342
expr->setType(nullptr);
13531343

13541344
return { true, expr };
@@ -1403,9 +1393,6 @@ namespace {
14031393
paramDeclIfaceElt.first->setInterfaceType(paramDeclIfaceElt.second->getInOutObjectType());
14041394
}
14051395

1406-
for (auto CSE : CollectionSemanticExprs)
1407-
CSE.first->setSemanticExpr(CSE.second);
1408-
14091396
if (!PossiblyInvalidDecls.empty())
14101397
for (auto D : PossiblyInvalidDecls)
14111398
if (D->hasInterfaceType())
@@ -1426,10 +1413,6 @@ namespace {
14261413
// we go digging through failed constraints, and expect their locators to
14271414
// still be meaningful.
14281415
~ExprTypeSaverAndEraser() {
1429-
for (auto CSE : CollectionSemanticExprs)
1430-
if (!CSE.first->getType())
1431-
CSE.first->setSemanticExpr(CSE.second);
1432-
14331416
for (auto exprElt : ExprTypes)
14341417
if (!exprElt.first->getType())
14351418
exprElt.first->setType(exprElt.second);

lib/Sema/CSGen.cpp

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3317,9 +3317,7 @@ namespace {
33173317
}
33183318

33193319
// Remove any semantic expression injected by typechecking.
3320-
if (auto CE = dyn_cast<CollectionExpr>(expr)) {
3321-
CE->setSemanticExpr(nullptr);
3322-
} else if (auto ISLE = dyn_cast<InterpolatedStringLiteralExpr>(expr)) {
3320+
if (auto ISLE = dyn_cast<InterpolatedStringLiteralExpr>(expr)) {
33233321
ISLE->setSemanticExpr(nullptr);
33243322
} else if (auto OLE = dyn_cast<ObjectLiteralExpr>(expr)) {
33253323
OLE->setSemanticExpr(nullptr);

test/SILGen/literals.swift

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -256,6 +256,39 @@ func throwingElement<T : FooProtocol>() throws -> [T] {
256256
return try [makeBasic(), makeThrowing()]
257257
}
258258

259+
class TakesDictionaryLiteral<Key, Value> : ExpressibleByDictionaryLiteral {
260+
required init(dictionaryLiteral elements: (Key, Value)...) {}
261+
}
262+
263+
// CHECK-LABEL: sil hidden [ossa] @$s8literals23returnsCustomDictionaryAA05TakesD7LiteralCyS2iGyF : $@convention(thin) () -> @owned TakesDictionaryLiteral<Int, Int> {
264+
// CHECK: [[TMP:%.*]] = apply %2(%0, %1) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int
265+
// CHECK: [[ARRAY_LENGTH:%.*]] = integer_literal $Builtin.Word, 2
266+
// CHECK: // function_ref _allocateUninitializedArray<A>(_:)
267+
// CHECK: [[ALLOCATE_VARARGS:%.*]] = function_ref @$ss27_allocateUninitializedArrayySayxG_BptBwlF : $@convention(thin) <τ_0_0> (Builtin.Word) -> (@owned Array<τ_0_0>, Builtin.RawPointer)
268+
// CHECK: [[ARR_TMP:%.*]] = apply [[ALLOCATE_VARARGS]]<(Int, Int)>([[ARRAY_LENGTH]])
269+
// CHECK: ([[ARR:%.*]], [[ADDRESS:%.*]]) = destructure_tuple [[ARR_TMP]]
270+
// CHECK: [[TUPLE_ADDR:%.*]] = pointer_to_address %9 : $Builtin.RawPointer to [strict] $*(Int, Int)
271+
// CHECK: [[KEY_ADDR:%.*]] = tuple_element_addr [[TUPLE_ADDR]] : $*(Int, Int), 0
272+
// CHECK: [[VALUE_ADDR:%.*]] = tuple_element_addr [[TUPLE_ADDR]] : $*(Int, Int), 1
273+
// CHECK: store [[TMP]] to [trivial] [[KEY_ADDR]] : $*Int
274+
// CHECK: store [[TMP]] to [trivial] [[VALUE_ADDR]] : $*Int
275+
// CHECK: [[IDX1:%.*]] = integer_literal $Builtin.Word, 1
276+
// CHECK: [[TUPLE_ADDR1:%.*]] = index_addr [[TUPLE_ADDR]] : $*(Int, Int), [[IDX1]] : $Builtin.Word
277+
// CHECK: [[KEY_ADDR:%.*]] = tuple_element_addr [[TUPLE_ADDR1]] : $*(Int, Int), 0
278+
// CHECK: [[VALUE_ADDR:%.*]] = tuple_element_addr [[TUPLE_ADDR1]] : $*(Int, Int), 1
279+
// CHECK: store [[TMP]] to [trivial] [[KEY_ADDR]] : $*Int
280+
// CHECK: store [[TMP]] to [trivial] [[VALUE_ADDR]] : $*Int
281+
// CHECK: [[METATYPE:%.*]] = metatype $@thick TakesDictionaryLiteral<Int, Int>.Type
282+
// CHECK: [[CTOR:%.*]] = class_method [[METATYPE]] : $@thick TakesDictionaryLiteral<Int, Int>.Type, #TakesDictionaryLiteral.init!allocator.1 : <Key, Value> (TakesDictionaryLiteral<Key, Value>.Type) -> ((Key, Value)...) -> TakesDictionaryLiteral<Key, Value>, $@convention(method) <τ_0_0, τ_0_1> (@owned Array<(τ_0_0, τ_0_1)>, @thick TakesDictionaryLiteral<τ_0_0, τ_0_1>.Type) -> @owned TakesDictionaryLiteral<τ_0_0, τ_0_1>
283+
// CHECK: [[RESULT:%.*]] = apply [[CTOR]]<Int, Int>(%8, %21)
284+
// CHECK: return [[RESULT]]
285+
286+
func returnsCustomDictionary() -> TakesDictionaryLiteral<Int, Int> {
287+
// Use temporary to simplify generated_sil
288+
let tmp = 77
289+
return [tmp: tmp, tmp : tmp]
290+
}
291+
259292
struct Color: _ExpressibleByColorLiteral {
260293
init(_colorLiteralRed red: Float, green: Float, blue: Float, alpha: Float) {}
261294
}

test/SILGen/sil_locations.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -259,17 +259,15 @@ func tuple_element(_ x: (Int, Float)) {
259259
}
260260

261261
func containers() -> ([Int], Dictionary<String, Int>) {
262-
return ([1, 2, 3], ["Ankeny": 1, "Burnside": 2, "Couch": 3])
262+
return ([1, 2, 3], ["Ankeny": 101, "Burnside": 102, "Couch": 103])
263263
// CHECK-LABEL: sil hidden [ossa] @$s13sil_locations10containers{{[_0-9a-zA-Z]*}}F
264-
// CHECK: apply {{%.*}}<(String, Int)>({{%.*}}), loc "{{.*}}":[[@LINE-2]]:23
265264

266-
// CHECK: string_literal utf8 "Ankeny", loc "{{.*}}":[[@LINE-4]]:23
265+
// CHECK: string_literal utf8 "Ankeny", loc "{{.*}}":[[@LINE-3]]:23
267266

268-
// CHECK: integer_literal $Builtin.IntLiteral, 1, loc "{{.*}}":[[@LINE-6]]:33
269-
// CHECK: integer_literal $Builtin.IntLiteral, 2, loc "{{.*}}":[[@LINE-7]]:48
267+
// CHECK: integer_literal $Builtin.IntLiteral, 101, loc "{{.*}}":[[@LINE-5]]:33
268+
// CHECK: integer_literal $Builtin.IntLiteral, 102, loc "{{.*}}":[[@LINE-6]]:50
270269

271-
272-
270+
// CHECK: apply {{%.*}}<String, Int>({{%.*}}, {{%.*}}) : {{.*}}, loc "{{.*}}":[[@LINE-8]]:22
273271
}
274272

275273

0 commit comments

Comments
 (0)