Skip to content

Commit b55c4f1

Browse files
committed
[nfc] allow ErrorTypeRepr to store a ZeroArgDiagnostic
There are sometimes parsing stuations where we don't want to emit a parsing error, because of feature guarding. For example, if a Feature involves new syntax for a type, we must be able to parse both the true and false sides of an ifdef guarding that new syntax based on a Feature flag.
1 parent b598baf commit b55c4f1

10 files changed

+58
-23
lines changed

include/swift/AST/DiagnosticEngine.h

+3
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,9 @@ namespace swift {
509509
void addChildNote(Diagnostic &&D);
510510
void insertChildNote(unsigned beforeIndex, Diagnostic &&D);
511511
};
512+
513+
/// A diagnostic that has no input arguments, so it is trivially-destructable.
514+
using ZeroArgDiagnostic = Diag<>;
512515

513516
/// Describes an in-flight diagnostic, which is currently active
514517
/// within the diagnostic engine and can be augmented within additional

include/swift/AST/TypeRepr.h

+26-7
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include "swift/AST/Attr.h"
2121
#include "swift/AST/DeclContext.h"
22+
#include "swift/AST/DiagnosticEngine.h"
2223
#include "swift/AST/GenericSignature.h"
2324
#include "swift/AST/Identifier.h"
2425
#include "swift/AST/Type.h"
@@ -195,17 +196,35 @@ class alignas(1 << TypeReprAlignInBits) TypeRepr
195196
/// A TypeRepr for a type with a syntax error. Can be used both as a
196197
/// top-level TypeRepr and as a part of other TypeRepr.
197198
///
198-
/// The client should make sure to emit a diagnostic at the construction time
199-
/// (in the parser). All uses of this type should be ignored and not
200-
/// re-diagnosed.
199+
/// The client can either emit a detailed diagnostic at the construction time
200+
/// (in the parser) or store a zero-arg diagnostic in this TypeRepr to be
201+
/// emitted after parsing, during type resolution.
202+
///
203+
/// All uses of this type should be ignored and not re-diagnosed.
201204
class ErrorTypeRepr : public TypeRepr {
202205
SourceRange Range;
206+
llvm::Optional<ZeroArgDiagnostic> DelayedDiag;
207+
208+
ErrorTypeRepr(SourceRange Range, llvm::Optional<ZeroArgDiagnostic> Diag)
209+
: TypeRepr(TypeReprKind::Error), Range(Range), DelayedDiag(Diag) {}
203210

204211
public:
205-
ErrorTypeRepr() : TypeRepr(TypeReprKind::Error) {}
206-
ErrorTypeRepr(SourceLoc Loc) : TypeRepr(TypeReprKind::Error), Range(Loc) {}
207-
ErrorTypeRepr(SourceRange Range)
208-
: TypeRepr(TypeReprKind::Error), Range(Range) {}
212+
static ErrorTypeRepr *
213+
create(ASTContext &Context, SourceRange Range,
214+
llvm::Optional<ZeroArgDiagnostic> DelayedDiag = llvm::None) {
215+
assert((!DelayedDiag || Range) && "diagnostic needs a location");
216+
return new (Context) ErrorTypeRepr(Range, DelayedDiag);
217+
}
218+
219+
static ErrorTypeRepr *
220+
create(ASTContext &Context, SourceLoc Loc = SourceLoc(),
221+
llvm::Optional<ZeroArgDiagnostic> DelayedDiag = llvm::None) {
222+
return create(Context, SourceRange(Loc), DelayedDiag);
223+
}
224+
225+
/// If there is a delayed diagnostic stored in this TypeRepr, consumes and
226+
/// emits that diagnostic.
227+
void dischargeDiagnostic(ASTContext &Context);
209228

210229
static bool classof(const TypeRepr *T) {
211230
return T->getKind() == TypeReprKind::Error;

lib/AST/DiagnosticEngine.cpp

+3
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@
4242

4343
using namespace swift;
4444

45+
static_assert(IsTriviallyDestructible<ZeroArgDiagnostic>::value,
46+
"ZeroArgDiagnostic is meant to be trivially destructable");
47+
4548
namespace {
4649
enum class DiagnosticOptions {
4750
/// No options.

lib/AST/TypeRepr.cpp

+9
Original file line numberDiff line numberDiff line change
@@ -653,6 +653,15 @@ void SILBoxTypeRepr::printImpl(ASTPrinter &Printer,
653653
Printer.printKeyword("sil_box", Opts);
654654
}
655655

656+
void ErrorTypeRepr::dischargeDiagnostic(swift::ASTContext &Context) {
657+
if (!DelayedDiag)
658+
return;
659+
660+
// Consume and emit the diagnostic.
661+
Context.Diags.diagnose(Range.Start, *DelayedDiag).highlight(Range);
662+
DelayedDiag = llvm::None;
663+
}
664+
656665
// See swift/Basic/Statistic.h for declaration: this enables tracing
657666
// TypeReprs, is defined here to avoid too much layering violation / circular
658667
// linkage dependency.

lib/Parse/ParseDecl.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -9665,7 +9665,7 @@ Parser::parseDeclSubscript(SourceLoc StaticLoc,
96659665

96669666
if (ElementTy.isNull()) {
96679667
// Always set an element type.
9668-
ElementTy = makeParserResult(ElementTy, new (Context) ErrorTypeRepr());
9668+
ElementTy = makeParserResult(ElementTy, ErrorTypeRepr::create(Context));
96699669
}
96709670
}
96719671

lib/Parse/ParseGeneric.cpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ ParserStatus Parser::parseGenericWhereClause(
339339
ParserResult<TypeRepr> Protocol = parseType();
340340
Status |= Protocol;
341341
if (Protocol.isNull())
342-
Protocol = makeParserResult(new (Context) ErrorTypeRepr(PreviousLoc));
342+
Protocol = makeParserResult(ErrorTypeRepr::create(Context, PreviousLoc));
343343

344344
// Add the requirement.
345345
Requirements.push_back(RequirementRepr::getTypeConstraint(
@@ -358,7 +358,7 @@ ParserStatus Parser::parseGenericWhereClause(
358358
ParserResult<TypeRepr> SecondType = parseType();
359359
Status |= SecondType;
360360
if (SecondType.isNull())
361-
SecondType = makeParserResult(new (Context) ErrorTypeRepr(PreviousLoc));
361+
SecondType = makeParserResult(ErrorTypeRepr::create(Context, PreviousLoc));
362362

363363
// Add the requirement
364364
if (FirstType.hasCodeCompletion()) {
@@ -373,7 +373,7 @@ ParserStatus Parser::parseGenericWhereClause(
373373
// completion token in the TypeRepr.
374374
Requirements.push_back(RequirementRepr::getTypeConstraint(
375375
FirstType.get(), EqualLoc,
376-
new (Context) ErrorTypeRepr(SecondType.get()->getLoc()),
376+
ErrorTypeRepr::create(Context, SecondType.get()->getLoc()),
377377
isRequirementExpansion));
378378
} else {
379379
Requirements.push_back(RequirementRepr::getSameType(
@@ -383,7 +383,7 @@ ParserStatus Parser::parseGenericWhereClause(
383383
} else if (FirstType.hasCodeCompletion()) {
384384
// Recover by adding dummy constraint.
385385
Requirements.push_back(RequirementRepr::getTypeConstraint(
386-
FirstType.get(), PreviousLoc, new (Context) ErrorTypeRepr(PreviousLoc),
386+
FirstType.get(), PreviousLoc, ErrorTypeRepr::create(Context, PreviousLoc),
387387
isRequirementExpansion));
388388
} else {
389389
diagnose(Tok, diag::expected_requirement_delim);

lib/Parse/ParsePattern.cpp

+2-2
Original file line numberDiff line numberDiff line change
@@ -1053,7 +1053,7 @@ ParserResult<Pattern> Parser::parseTypedPattern() {
10531053
}
10541054
}
10551055
} else {
1056-
Ty = makeParserResult(new (Context) ErrorTypeRepr(PreviousLoc));
1056+
Ty = makeParserResult(ErrorTypeRepr::create(Context, PreviousLoc));
10571057
}
10581058

10591059
result = makeParserResult(result,
@@ -1278,7 +1278,7 @@ parseOptionalPatternTypeAnnotation(ParserResult<Pattern> result) {
12781278

12791279
TypeRepr *repr = Ty.getPtrOrNull();
12801280
if (!repr)
1281-
repr = new (Context) ErrorTypeRepr(PreviousLoc);
1281+
repr = ErrorTypeRepr::create(Context, PreviousLoc);
12821282

12831283
return makeParserResult(status, new (Context) TypedPattern(P, repr));
12841284
}

lib/Parse/ParseType.cpp

+6-6
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
232232
CodeCompletionCallbacks->completeTypeSimpleBeginning();
233233
}
234234
return makeParserCodeCompletionResult<TypeRepr>(
235-
new (Context) ErrorTypeRepr(consumeToken(tok::code_complete)));
235+
ErrorTypeRepr::create(Context, consumeToken(tok::code_complete)));
236236
case tok::l_square: {
237237
ty = parseTypeCollection();
238238
break;
@@ -255,7 +255,7 @@ ParserResult<TypeRepr> Parser::parseTypeSimple(
255255
diag.fixItInsert(getEndOfPreviousLoc(), " <#type#>");
256256
}
257257
if (Tok.isKeyword() && !Tok.isAtStartOfLine()) {
258-
ty = makeParserErrorResult(new (Context) ErrorTypeRepr(Tok.getLoc()));
258+
ty = makeParserErrorResult(ErrorTypeRepr::create(Context, Tok.getLoc()));
259259
consumeToken();
260260
return ty;
261261
}
@@ -685,8 +685,8 @@ ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
685685
auto diag = diagnose(Tok, diag::extra_rbracket);
686686
diag.fixItInsert(result.get()->getStartLoc(), getTokenText(tok::l_square));
687687
consumeToken();
688-
return makeParserErrorResult(new (Context)
689-
ErrorTypeRepr(getTypeErrorLoc()));
688+
return makeParserErrorResult(ErrorTypeRepr::create(Context,
689+
getTypeErrorLoc()));
690690
}
691691

692692
if (Tok.is(tok::colon)) {
@@ -702,8 +702,8 @@ ParserResult<TypeRepr> Parser::parseDeclResultType(Diag<> MessageID) {
702702
diag.fixItInsertAfter(secondType.get()->getEndLoc(), getTokenText(tok::r_square));
703703
}
704704
}
705-
return makeParserErrorResult(new (Context)
706-
ErrorTypeRepr(getTypeErrorLoc()));
705+
return makeParserErrorResult(ErrorTypeRepr::create(Context,
706+
getTypeErrorLoc()));
707707
}
708708
}
709709
return result;

lib/Sema/PreCheckExpr.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -2010,7 +2010,7 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
20102010
Ctx.Diags.diagnose(AE->getArgsExpr()->getLoc(),
20112011
diag::expected_type_before_arrow);
20122012
auto ArgRange = AE->getArgsExpr()->getSourceRange();
2013-
auto ErrRepr = new (Ctx) ErrorTypeRepr(ArgRange);
2013+
auto ErrRepr = ErrorTypeRepr::create(Ctx, ArgRange);
20142014
ArgsTypeRepr =
20152015
TupleTypeRepr::create(Ctx, {ErrRepr}, ArgRange);
20162016
}
@@ -2025,8 +2025,8 @@ TypeExpr *PreCheckExpression::simplifyTypeExpr(Expr *E) {
20252025
if (!ResultTypeRepr) {
20262026
Ctx.Diags.diagnose(AE->getResultExpr()->getLoc(),
20272027
diag::expected_type_after_arrow);
2028-
ResultTypeRepr = new (Ctx)
2029-
ErrorTypeRepr(AE->getResultExpr()->getSourceRange());
2028+
ResultTypeRepr =
2029+
ErrorTypeRepr::create(Ctx, AE->getResultExpr()->getSourceRange());
20302030
}
20312031

20322032
auto NewTypeRepr = new (Ctx)

lib/Sema/TypeCheckType.cpp

+1
Original file line numberDiff line numberDiff line change
@@ -2431,6 +2431,7 @@ NeverNullType TypeResolver::resolveType(TypeRepr *repr,
24312431

24322432
switch (repr->getKind()) {
24332433
case TypeReprKind::Error:
2434+
cast<ErrorTypeRepr>(repr)->dischargeDiagnostic(getASTContext());
24342435
return ErrorType::get(getASTContext());
24352436

24362437
case TypeReprKind::Attributed:

0 commit comments

Comments
 (0)