Skip to content

Commit ae82b29

Browse files
committed
Rework emission of EditorPlaceholderExprs
Rather than synthesizing a semantic expression to emit, add a compiler intrinsic to the stdlib that is simple enough to just SILGen the emission.
1 parent 0c9025c commit ae82b29

File tree

9 files changed

+59
-60
lines changed

9 files changed

+59
-60
lines changed

include/swift/AST/DiagnosticsSema.def

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2370,8 +2370,6 @@ NOTE(note_no_in_class_init_3plus,none,
23702370
(Identifier, Identifier, Identifier, bool))
23712371
ERROR(missing_unimplemented_init_runtime,none,
23722372
"standard library error: missing _unimplementedInitializer", ())
2373-
ERROR(missing_undefined_runtime,none,
2374-
"standard library error: missing _undefined", ())
23752373

23762374
ERROR(inherited_default_value_not_in_designated_constructor,none,
23772375
"default value inheritance via 'super' is only valid on the parameters of "

include/swift/AST/Expr.h

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5764,14 +5764,13 @@ class EditorPlaceholderExpr : public Expr {
57645764
SourceLoc Loc;
57655765
TypeRepr *PlaceholderTy;
57665766
TypeRepr *ExpansionTyR;
5767-
Expr *SemanticExpr;
57685767

57695768
public:
57705769
EditorPlaceholderExpr(Identifier Placeholder, SourceLoc Loc,
57715770
TypeRepr *PlaceholderTy, TypeRepr *ExpansionTyR)
57725771
: Expr(ExprKind::EditorPlaceholder, /*Implicit=*/false),
57735772
Placeholder(Placeholder), Loc(Loc), PlaceholderTy(PlaceholderTy),
5774-
ExpansionTyR(ExpansionTyR), SemanticExpr(nullptr) {}
5773+
ExpansionTyR(ExpansionTyR) {}
57755774

57765775
Identifier getPlaceholder() const { return Placeholder; }
57775776
SourceRange getSourceRange() const { return Loc; }
@@ -5783,9 +5782,6 @@ class EditorPlaceholderExpr : public Expr {
57835782
static bool classof(const Expr *E) {
57845783
return E->getKind() == ExprKind::EditorPlaceholder;
57855784
}
5786-
5787-
Expr *getSemanticExpr() const { return SemanticExpr; }
5788-
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
57895785
};
57905786

57915787
/// A LazyInitializerExpr is used to embed an existing typechecked

include/swift/AST/KnownDecls.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,6 @@ FUNC_DECL(ModifyAtReferenceWritableKeyPath, "_modifyAtReferenceWritableKeyPath")
9191
FUNC_DECL(Swap, "swap")
9292

9393
FUNC_DECL(UnimplementedInitializer, "_unimplementedInitializer")
94-
FUNC_DECL(Undefined, "_undefined")
94+
FUNC_DECL(UndefinedEditorPlaceholder, "_undefinedEditorPlaceholder")
9595

9696
#undef FUNC_DECL

lib/AST/ASTDumper.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4413,9 +4413,6 @@ class PrintExpr : public ExprVisitor<PrintExpr, void, Label>,
44134413
if (ExpTyR && ExpTyR != TyR) {
44144414
printRec(ExpTyR, Label::optional("type_repr_for_expansion"));
44154415
}
4416-
if (auto *SE = E->getSemanticExpr()) {
4417-
printRec(SE, Label::always("semantic_expr"));
4418-
}
44194416
printFoot();
44204417
}
44214418
void visitLazyInitializerExpr(LazyInitializerExpr *E, Label label) {

lib/AST/ASTWalker.cpp

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -599,23 +599,6 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
599599
// Exprs
600600
//===--------------------------------------------------------------------===//
601601

602-
// A macro for handling the "semantic expressions" that are common
603-
// on sugared expression nodes like string interpolation. The
604-
// semantic expression is set up by type-checking to include all the
605-
// other children as sub-expressions, so if it exists, we should
606-
// just bypass the rest of the visitation.
607-
#define HANDLE_SEMANTIC_EXPR(NODE) \
608-
do { \
609-
if (Expr *_semanticExpr = NODE->getSemanticExpr()) { \
610-
if ((_semanticExpr = doIt(_semanticExpr))) { \
611-
NODE->setSemanticExpr(_semanticExpr); \
612-
} else { \
613-
return nullptr; \
614-
} \
615-
return NODE; \
616-
} \
617-
} while (false)
618-
619602
Expr *visitErrorExpr(ErrorExpr *E) {
620603
if (auto *origExpr = E->getOriginalExpr()) {
621604
auto *newOrigExpr = doIt(origExpr);
@@ -1267,7 +1250,6 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
12671250
}
12681251

12691252
Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
1270-
HANDLE_SEMANTIC_EXPR(E);
12711253
return E;
12721254
}
12731255

lib/SILGen/SILGenExpr.cpp

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3485,7 +3485,21 @@ visitObjectLiteralExpr(ObjectLiteralExpr *E, SGFContext C) {
34853485

34863486
RValue RValueEmitter::
34873487
visitEditorPlaceholderExpr(EditorPlaceholderExpr *E, SGFContext C) {
3488-
return visit(E->getSemanticExpr(), C);
3488+
if (auto *undefinedFn = SGF.getASTContext().getUndefinedEditorPlaceholder()) {
3489+
auto args = SGF.emitSourceLocationArgs(E->getLoc(), E);
3490+
SGF.emitApplyOfLibraryIntrinsic(E, undefinedFn, SubstitutionMap(),
3491+
{
3492+
args.filenameStartPointer,
3493+
args.filenameLength,
3494+
args.filenameIsAscii,
3495+
args.line,
3496+
},
3497+
SGFContext());
3498+
} else {
3499+
SGF.B.createUnconditionalFail(E, "attempt to evaluate editor placeholder");
3500+
}
3501+
SGF.B.createUnreachable(E);
3502+
return emitUnreachableValue(E, E->getType()->getCanonicalType());
34893503
}
34903504

34913505
RValue RValueEmitter::visitObjCSelectorExpr(ObjCSelectorExpr *e, SGFContext C) {

lib/Sema/CSApply.cpp

Lines changed: 1 addition & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -4782,34 +4782,7 @@ namespace {
47824782
}
47834783

47844784
Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
4785-
simplifyExprType(E);
4786-
auto valueType = cs.getType(E);
4787-
4788-
// Synthesize a call to _undefined() of appropriate type.
4789-
FuncDecl *undefinedDecl = ctx.getUndefined();
4790-
if (!undefinedDecl) {
4791-
ctx.Diags.diagnose(E->getLoc(), diag::missing_undefined_runtime);
4792-
return nullptr;
4793-
}
4794-
DeclRefExpr *fnRef = new (ctx) DeclRefExpr(undefinedDecl, DeclNameLoc(),
4795-
/*Implicit=*/true);
4796-
fnRef->setFunctionRefInfo(FunctionRefInfo::singleBaseNameApply());
4797-
4798-
StringRef msg = "attempt to evaluate editor placeholder";
4799-
Expr *argExpr = new (ctx) StringLiteralExpr(msg, E->getLoc(),
4800-
/*implicit*/true);
4801-
4802-
auto *argList = ArgumentList::forImplicitUnlabeled(ctx, {argExpr});
4803-
Expr *callExpr = CallExpr::createImplicit(ctx, fnRef, argList);
4804-
4805-
auto resultTy = TypeChecker::typeCheckExpression(
4806-
callExpr, dc, /*contextualInfo=*/{valueType, CTP_CannotFail});
4807-
assert(resultTy && "Conversion cannot fail!");
4808-
(void)resultTy;
4809-
4810-
cs.cacheExprTypes(callExpr);
4811-
E->setSemanticExpr(callExpr);
4812-
return E;
4785+
return simplifyExprType(E);
48134786
}
48144787

48154788
Expr *visitObjCSelectorExpr(ObjCSelectorExpr *E) {

stdlib/public/core/AssertCommon.swift

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,7 @@ func _unimplementedInitializer(className: StaticString,
292292

293293
#if !$Embedded
294294

295-
/// Used to evaluate editor placeholders.
295+
/// Previously used to evaluate editor placeholders.
296296
public // COMPILER_INTRINSIC
297297
func _undefined<T>(
298298
_ message: @autoclosure () -> String = String(),
@@ -303,7 +303,7 @@ func _undefined<T>(
303303

304304
#else
305305

306-
/// Used to evaluate editor placeholders.
306+
/// Previously used to evaluate editor placeholders.
307307
public // COMPILER_INTRINSIC
308308
func _undefined<T>(
309309
_ message: @autoclosure () -> StaticString = StaticString(),
@@ -314,6 +314,38 @@ func _undefined<T>(
314314

315315
#endif
316316

317+
/// Called when evaluating an editor placeholder in a playground.
318+
///
319+
/// We always export this into the client since it should never be used in an
320+
/// actual shipping binary and keeps it a pure compiler implementation detail.
321+
///
322+
/// This function should not be inlined in desktop Swift because it is cold and
323+
/// inlining just bloats code. In Embedded Swift, we force inlining as this
324+
/// function is typically just a trap (in release configurations).
325+
#if !$Embedded
326+
@inline(never)
327+
#else
328+
@inline(__always)
329+
#endif
330+
@_alwaysEmitIntoClient // COMPILER_INTRINSIC
331+
internal func _undefinedEditorPlaceholder(
332+
_filenameStart: Builtin.RawPointer,
333+
_filenameLength: Builtin.Word,
334+
_filenameIsASCII: Builtin.Int1,
335+
_line: Builtin.Word
336+
) -> Never {
337+
_assertionFailure(
338+
"Fatal error",
339+
"attempt to evaluate editor placeholder",
340+
file: StaticString(
341+
_start: _filenameStart,
342+
utf8CodeUnitCount: _filenameLength,
343+
isASCII: _filenameIsASCII),
344+
line: UInt(_line),
345+
flags: 0
346+
)
347+
}
348+
317349
/// Called when falling off the end of a switch and the type can be represented
318350
/// as a raw value.
319351
///
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-run-simple-swift(-Xfrontend -warn-on-editor-placeholder) 2> %t/output || true
3+
// RUN: %FileCheck %s < %t/output
4+
// REQUIRES: executable_test
5+
6+
print(<#placeholder#>)
7+
// CHECK: editor_placeholder_exec.swift:[[@LINE-1]]: Fatal error: attempt to evaluate editor placeholder

0 commit comments

Comments
 (0)