Skip to content

Commit c99c02b

Browse files
committed
Transform EditorPlaceholderExpr into trap if executed in playground
mode (take 2) Allow untyped placeholder to take arbitrary type, but default to Void. Add _undefined<T>() function, which is like fatalError() but has arbitrary return type. In playground mode, merely warn about outstanding placeholders instead of erroring out, and transform placeholders into calls to _undefined(). This way, code with outstanding placeholders will only crash when it attempts to evaluate such placeholders. When generating constraints for an iterated sequence of type T, emit T convertible to $T1 $T1 conforms to SequenceType instead of T convertible to SequenceType This ensures that an untyped placeholder in for-each sequence position doesn't get inferred to have type SequenceType. (The conversion is still necessary because the sequence may have IUO type.) The new constraint system precipitates changes in CSSimplify and CSDiag, and ends up fixing 18741539 along the way. (NOTE: There is a small regression in diagnosis of issues like the following: class C {} class D: C {} func f(a: [C]!) { for _: D in a {} } It complains that [C]! doesn't conform to SequenceType when it should be complaining that C is not convertible to D.) <rdar://problem/21167372> (Originally Swift SVN r31481)
1 parent f6329bc commit c99c02b

27 files changed

+226
-51
lines changed

include/swift/AST/ASTContext.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,9 @@ class ASTContext {
481481
/// Retrieve the declaration of Swift._unimplemented_initializer.
482482
FuncDecl *getUnimplementedInitializerDecl(LazyResolver *resolver) const;
483483

484+
/// Retrieve the declaration of Swift._undefined.
485+
FuncDecl *getUndefinedDecl(LazyResolver *resolver) const;
486+
484487
// Retrieve the declaration of Swift._stdlib_isOSVersionAtLeast.
485488
FuncDecl *getIsOSVersionAtLeastDecl(LazyResolver *resolver) const;
486489

include/swift/AST/DiagnosticsParse.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ ERROR(lex_unary_postfix_dot_is_reserved,lexing,none,
132132
"postfix '.' is reserved", ())
133133
ERROR(lex_editor_placeholder,lexing,none,
134134
"editor placeholder in source file", ())
135+
WARNING(lex_editor_placeholder_in_playground,lexing,none,
136+
"editor placeholder in source file", ())
135137

136138
//------------------------------------------------------------------------------
137139
// Declaration parsing diagnostics

include/swift/AST/DiagnosticsSema.def

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -832,6 +832,8 @@ NOTE(note_no_in_class_init_3plus,sema_tcd,none,
832832
(Identifier, Identifier, Identifier, bool))
833833
ERROR(missing_unimplemented_init_runtime,sema_tcd,none,
834834
"standard library error: missing _unimplemented_initializer", ())
835+
ERROR(missing_undefined_runtime,sema_tcd,none,
836+
"standard library error: missing _undefined", ())
835837
WARNING(unsupported_synthesize_init_variadic,sema_tcd,none,
836838
"synthesizing a variadic inherited initializer for subclass %0 is "
837839
"unsupported",

include/swift/AST/Expr.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3745,6 +3745,7 @@ class EditorPlaceholderExpr : public Expr {
37453745
SourceLoc Loc;
37463746
TypeLoc PlaceholderTy;
37473747
TypeRepr *ExpansionTyR;
3748+
Expr *SemanticExpr;
37483749

37493750
public:
37503751
EditorPlaceholderExpr(Identifier Placeholder, SourceLoc Loc,
@@ -3753,7 +3754,8 @@ class EditorPlaceholderExpr : public Expr {
37533754
: Expr(ExprKind::EditorPlaceholder, /*Implicit=*/false),
37543755
Placeholder(Placeholder), Loc(Loc),
37553756
PlaceholderTy(PlaceholderTy),
3756-
ExpansionTyR(ExpansionTyR) {
3757+
ExpansionTyR(ExpansionTyR),
3758+
SemanticExpr(nullptr) {
37573759
}
37583760

37593761
Identifier getPlaceholder() const { return Placeholder; }
@@ -3767,6 +3769,9 @@ class EditorPlaceholderExpr : public Expr {
37673769
static bool classof(const Expr *E) {
37683770
return E->getKind() == ExprKind::EditorPlaceholder;
37693771
}
3772+
3773+
Expr *getSemanticExpr() const { return SemanticExpr; }
3774+
void setSemanticExpr(Expr *SE) { SemanticExpr = SE; }
37703775
};
37713776

37723777
#undef SWIFT_FORWARD_SOURCE_LOCS_TO

include/swift/AST/ExprNodes.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,7 @@ EXPR(Assign, Expr)
156156
EXPR(DefaultValue, Expr)
157157
EXPR(CodeCompletion, Expr)
158158
UNCHECKED_EXPR(UnresolvedPattern, Expr)
159-
UNCHECKED_EXPR(EditorPlaceholder, Expr)
159+
EXPR(EditorPlaceholder, Expr)
160160

161161
#undef EXPR_RANGE
162162
#undef UNCHECKED_EXPR

lib/AST/ASTContext.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,9 @@ struct ASTContext::Implementation {
177177
/// func _unimplemented_initializer(className: StaticString).
178178
FuncDecl *UnimplementedInitializerDecl = nullptr;
179179

180+
/// func _undefined<T>(msg: StaticString, file: StaticString, line: UInt) -> T
181+
FuncDecl *UndefinedDecl = nullptr;
182+
180183
/// func _stdlib_isOSVersionAtLeast(Builtin.Word,Builtin.Word, Builtin.word)
181184
// -> Builtin.Int1
182185
FuncDecl *IsOSVersionAtLeastDecl = nullptr;
@@ -985,6 +988,21 @@ ASTContext::getUnimplementedInitializerDecl(LazyResolver *resolver) const {
985988
return decl;
986989
}
987990

991+
FuncDecl *
992+
ASTContext::getUndefinedDecl(LazyResolver *resolver) const {
993+
if (Impl.UndefinedDecl)
994+
return Impl.UndefinedDecl;
995+
996+
// Look for the function.
997+
CanType input, output;
998+
auto decl = findLibraryIntrinsic(*this, "_undefined", resolver);
999+
if (!decl)
1000+
return nullptr;
1001+
1002+
Impl.UndefinedDecl = decl;
1003+
return decl;
1004+
}
1005+
9881006
FuncDecl *ASTContext::getIsOSVersionAtLeastDecl(LazyResolver *resolver) const {
9891007
if (Impl.IsOSVersionAtLeastDecl)
9901008
return Impl.IsOSVersionAtLeastDecl;

lib/AST/ASTWalker.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,7 @@ class Traversal : public ASTVisitor<Traversal, Expr*, Stmt*,
824824
}
825825

826826
Expr *visitEditorPlaceholderExpr(EditorPlaceholderExpr *E) {
827+
HANDLE_SEMANTIC_EXPR(E);
827828
return E;
828829
}
829830

lib/AST/Expr.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -286,6 +286,7 @@ void Expr::propagateLValueAccessKind(AccessKind accessKind,
286286
LEAF_LVALUE_EXPR(DiscardAssignment)
287287
LEAF_LVALUE_EXPR(DynamicLookup)
288288
LEAF_LVALUE_EXPR(OpaqueValue)
289+
LEAF_LVALUE_EXPR(EditorPlaceholder)
289290

290291
COMPLETE_PHYSICAL_LVALUE_EXPR(AnyTry, getSubExpr())
291292
PARTIAL_PHYSICAL_LVALUE_EXPR(BindOptional, getSubExpr())

lib/AST/Verifier.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -462,8 +462,8 @@ struct ASTNodeBase {};
462462
} while (!activeScope->isModuleScopeContext());
463463
}
464464

465-
Out << "AST verification error: archetype " << archetype
466-
<< " not allowed in this context\n";
465+
Out << "AST verification error: archetype "
466+
<< archetype->getString() << " not allowed in this context\n";
467467

468468
auto knownDC = Ctx.ArchetypeContexts.find(archetype);
469469
if (knownDC != Ctx.ArchetypeContexts.end()) {

lib/Parse/Lexer.cpp

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1279,9 +1279,13 @@ void Lexer::tryLexEditorPlaceholder() {
12791279
if (Ptr[0] == '<' && Ptr[1] == '#')
12801280
break;
12811281
if (Ptr[0] == '#' && Ptr[1] == '>') {
1282-
// Found it. Flag it as error for the rest of the compiler pipeline and
1283-
// lex it as an identifier.
1284-
diagnose(TokStart, diag::lex_editor_placeholder);
1282+
// Found it. Flag it as error (or warning, if in playground mode) for the
1283+
// rest of the compiler pipeline and lex it as an identifier.
1284+
if (LangOpts.Playground) {
1285+
diagnose(TokStart, diag::lex_editor_placeholder_in_playground);
1286+
} else {
1287+
diagnose(TokStart, diag::lex_editor_placeholder);
1288+
}
12851289
CurPtr = Ptr+2;
12861290
formToken(tok::identifier, TokStart);
12871291
return;

0 commit comments

Comments
 (0)