Skip to content

Commit d0779bd

Browse files
pschuhslavapestov
authored andcommitted
Convert ArrayExpr to not use callWitness() or generate a SemanticExpr.
1 parent 7e88424 commit d0779bd

File tree

10 files changed

+310
-65
lines changed

10 files changed

+310
-65
lines changed

include/swift/AST/Expr.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2207,6 +2207,7 @@ class TupleExpr final : public Expr,
22072207
class CollectionExpr : public Expr {
22082208
SourceLoc LBracketLoc;
22092209
SourceLoc RBracketLoc;
2210+
ConcreteDeclRef Initializer;
22102211

22112212
Expr *SemanticExpr = nullptr;
22122213

@@ -2283,6 +2284,14 @@ class CollectionExpr : public Expr {
22832284
e->getKind() <= ExprKind::Last_CollectionExpr;
22842285
}
22852286

2287+
/// Retrieve the initializer that will be used to construct the 'array'
2288+
/// literal from the result of the initializer.
2289+
ConcreteDeclRef getInitializer() const { return Initializer; }
2290+
2291+
/// Set the initializer that will be used to construct the 'array' literal.
2292+
void setInitializer(ConcreteDeclRef initializer) {
2293+
Initializer = initializer;
2294+
}
22862295
};
22872296

22882297
/// An array literal expression [a, b, c].
@@ -2313,6 +2322,8 @@ class ArrayExpr final : public CollectionExpr,
23132322
static bool classof(const Expr *e) {
23142323
return e->getKind() == ExprKind::Array;
23152324
}
2325+
2326+
Type getElementType();
23162327
};
23172328

23182329
/// A dictionary literal expression [a : x, b : y, c : z].

lib/AST/ASTDumper.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2068,6 +2068,8 @@ class PrintExpr : public ExprVisitor<PrintExpr> {
20682068
}
20692069
void visitArrayExpr(ArrayExpr *E) {
20702070
printCommon(E, "array_expr");
2071+
PrintWithColorRAII(OS, LiteralValueColor) << " initializer=";
2072+
E->getInitializer().dump(PrintWithColorRAII(OS, LiteralValueColor).getOS());
20712073
for (auto elt : E->getElements()) {
20722074
OS << '\n';
20732075
printRec(elt);

lib/AST/Expr.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,6 +1488,19 @@ ArrayExpr *ArrayExpr::create(ASTContext &C, SourceLoc LBracketLoc,
14881488
return new (Mem) ArrayExpr(LBracketLoc, Elements, CommaLocs, RBracketLoc, Ty);
14891489
}
14901490

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

lib/IDE/ExprContextAnalysis.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -588,6 +588,12 @@ class ExprContextAnalyzer {
588588
analyzeApplyExpr(Parent);
589589
break;
590590
}
591+
case ExprKind::Array: {
592+
if (auto type = ParsedExpr->getType()) {
593+
recordPossibleType(type);
594+
}
595+
break;
596+
}
591597
case ExprKind::Assign: {
592598
auto *AE = cast<AssignExpr>(Parent);
593599

@@ -744,6 +750,7 @@ class ExprContextAnalyzer {
744750
case ExprKind::PrefixUnary:
745751
case ExprKind::Assign:
746752
case ExprKind::Subscript:
753+
case ExprKind::Array:
747754
return true;
748755
case ExprKind::Tuple: {
749756
auto ParentE = Parent.getAsExpr();

lib/SILGen/SILGenExpr.cpp

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,7 +462,8 @@ namespace {
462462
RValue visitKeyPathExpr(KeyPathExpr *E, SGFContext C);
463463
RValue visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E,
464464
SGFContext C);
465-
RValue visitCollectionExpr(CollectionExpr *E, SGFContext C);
465+
RValue visitArrayExpr(ArrayExpr *E, SGFContext C);
466+
RValue visitDictionaryExpr(DictionaryExpr *E, SGFContext C);
466467
RValue visitRebindSelfInConstructorExpr(RebindSelfInConstructorExpr *E,
467468
SGFContext C);
468469
RValue visitInjectIntoOptionalExpr(InjectIntoOptionalExpr *E, SGFContext C);
@@ -3652,7 +3653,51 @@ visitMagicIdentifierLiteralExpr(MagicIdentifierLiteralExpr *E, SGFContext C) {
36523653
llvm_unreachable("Unhandled MagicIdentifierLiteralExpr in switch.");
36533654
}
36543655

3655-
RValue RValueEmitter::visitCollectionExpr(CollectionExpr *E, SGFContext C) {
3656+
RValue RValueEmitter::visitArrayExpr(ArrayExpr *E, SGFContext C) {
3657+
auto loc = SILLocation(E);
3658+
ArgumentScope scope(SGF, loc);
3659+
auto init = E->getInitializer();
3660+
auto *decl = dyn_cast<AbstractFunctionDecl>(init.getDecl());
3661+
Type elementType = E->getElementType();
3662+
ArrayRef<Identifier> argLabels = decl->getFullName().getArgumentNames();
3663+
CanType arrayTy = ArraySliceType::get(elementType)->getCanonicalType();
3664+
VarargsInfo varargsInfo =
3665+
emitBeginVarargs(SGF, loc, elementType->getCanonicalType(), arrayTy,
3666+
E->getNumElements(), {});
3667+
3668+
for (unsigned index : range(E->getNumElements())) {
3669+
auto destAddr = varargsInfo.getBaseAddress();
3670+
if (index != 0) {
3671+
SILValue indexValue = SGF.B.createIntegerLiteral(
3672+
loc, SILType::getBuiltinWordType(SGF.getASTContext()), index);
3673+
destAddr = SGF.B.createIndexAddr(loc, destAddr, indexValue);
3674+
}
3675+
auto &destTL = varargsInfo.getBaseTypeLowering();
3676+
// Use an invalid cleanup here because we're relying on the cleanup for
3677+
// the Array constructed inside emitBeginVarargs to destroy these values.
3678+
TemporaryInitialization init(destAddr, CleanupHandle::invalid());
3679+
ArgumentSource(E->getElements()[index])
3680+
.forwardInto(SGF, varargsInfo.getBaseAbstractionPattern(), &init,
3681+
destTL);
3682+
}
3683+
3684+
RValue arg(SGF, loc, arrayTy,
3685+
emitEndVarargs(SGF, loc, std::move(varargsInfo)));
3686+
3687+
// Add an argument label for init(arrayLiteral: T...) as the above tuple is of
3688+
// the form (T...) with no label.
3689+
assert(argLabels.size() == 1 && !argLabels[0].empty() &&
3690+
!isa<TupleType>(arg.getType()));
3691+
Type newType = TupleType::get({TupleTypeElt(arg.getType(), argLabels[0])},
3692+
SGF.getASTContext());
3693+
arg.rewriteType(newType->getCanonicalType());
3694+
3695+
// Call the builtin initializer.
3696+
return scope.popPreservingValue(SGF.emitApplyAllocatingInitializer(
3697+
loc, init, std::move(arg), E->getType(), C));
3698+
}
3699+
3700+
RValue RValueEmitter::visitDictionaryExpr(DictionaryExpr *E, SGFContext C) {
36563701
return visit(E->getSemanticExpr(), C);
36573702
}
36583703

lib/Sema/CSApply.cpp

Lines changed: 10 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -2786,71 +2786,23 @@ namespace {
27862786
ConformanceCheckFlags::InExpression);
27872787
assert(conformance && "Type does not conform to protocol?");
27882788

2789-
// Call the witness that builds the array literal.
2790-
// FIXME: callWitness() may end up re-doing some work we already did
2791-
// to convert the array literal elements to the element type. It would
2792-
// be nicer to re-use them.
2793-
2794-
// FIXME: This location info is bogus.
2795-
Expr *typeRef = TypeExpr::createImplicitHack(expr->getLoc(), arrayTy,
2796-
tc.Context);
2797-
cs.cacheExprTypes(typeRef);
2798-
27992789
DeclName name(tc.Context, DeclBaseName::createConstructor(),
28002790
{ tc.Context.Id_arrayLiteral });
28012791

2802-
// Coerce the array elements to be rvalues, so that other type-checker
2803-
// code that attempts to peephole the AST doesn't have to re-load the
2804-
// elements (and break the invariant that lvalue nodes only get their
2805-
// access kind set once).
2806-
for (auto &element : expr->getElements()) {
2807-
element = cs.coerceToRValue(element);
2808-
}
2809-
2810-
// Restructure the argument to provide the appropriate labels in the
2811-
// tuple.
2812-
SmallVector<TupleTypeElt, 4> typeElements;
2813-
SmallVector<Identifier, 4> names;
2814-
bool first = true;
2815-
for (auto elt : expr->getElements()) {
2816-
if (first) {
2817-
typeElements.push_back(TupleTypeElt(cs.getType(elt),
2818-
tc.Context.Id_arrayLiteral));
2819-
names.push_back(tc.Context.Id_arrayLiteral);
2792+
ConcreteDeclRef witness =
2793+
findNamedWitnessImpl(tc, dc, arrayTy->getRValueType(), arrayProto,
2794+
name, diag::array_protocol_broken, conformance);
2795+
if (!witness || !isa<AbstractFunctionDecl>(witness.getDecl()))
2796+
return nullptr;
2797+
expr->setInitializer(witness);
28202798

2821-
first = false;
2822-
continue;
2823-
}
2799+
auto elementType = expr->getElementType();
28242800

2825-
typeElements.push_back(cs.getType(elt));
2826-
names.push_back(Identifier());
2801+
for (auto &element : expr->getElements()) {
2802+
element = coerceToType(element, elementType,
2803+
cs.getConstraintLocator(element));
28272804
}
28282805

2829-
Type argType = TupleType::get(typeElements, tc.Context);
2830-
assert(isa<TupleType>(argType.getPointer()));
2831-
2832-
Expr *arg =
2833-
TupleExpr::create(tc.Context, SourceLoc(),
2834-
expr->getElements(),
2835-
names,
2836-
{ },
2837-
SourceLoc(), /*HasTrailingClosure=*/false,
2838-
/*Implicit=*/true,
2839-
argType);
2840-
2841-
cs.cacheExprTypes(arg);
2842-
2843-
cs.setExprTypes(typeRef);
2844-
cs.setExprTypes(arg);
2845-
2846-
Expr *result = tc.callWitness(typeRef, dc, arrayProto, *conformance,
2847-
name, arg, diag::array_protocol_broken);
2848-
if (!result)
2849-
return nullptr;
2850-
2851-
cs.cacheExprTypes(result);
2852-
2853-
expr->setSemanticExpr(result);
28542806
return expr;
28552807
}
28562808

test/IDE/complete_unresolved_members.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -368,12 +368,12 @@ func f() -> SomeEnum1 {
368368
return .#^UNRESOLVED_27^#
369369
}
370370

371-
let TopLevelVar1 = OptionSetTaker7([.#^UNRESOLVED_28^#], Op2: [.Option4])
371+
let TopLevelVar1 = OptionSetTaker7([.#^UNRESOLVED_28^#], [.Option4])
372372

373373
let TopLevelVar2 = OptionSetTaker1([.#^UNRESOLVED_29^#])
374374

375-
let TopLevelVar3 = OptionSetTaker7([.Option1], Op2: [.#^UNRESOLVED_30^#])
376-
let TopLevelVar4 = OptionSetTaker7([.Option1], Op2: [.Option4, .#^UNRESOLVED_31^#])
375+
let TopLevelVar3 = OptionSetTaker7([.Option1], [.#^UNRESOLVED_30^#])
376+
let TopLevelVar4 = OptionSetTaker7([.Option1], [.Option4, .#^UNRESOLVED_31^#])
377377

378378
let _: [SomeEnum1] = [.#^UNRESOLVED_32^#]
379379
let _: [SomeEnum1] = [.South, .#^UNRESOLVED_33^#]

0 commit comments

Comments
 (0)