From 92e6a00056818011027d87ce57da26c0b9eedc7c Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Sun, 17 Aug 2025 11:48:21 +0100 Subject: [PATCH 1/3] [Diags] Avoid infinite recursion on decl printing request cycle The ASTPrinter may kick requests that may emit diagnostics, make sure we don't attempt to recursively print the decl since that would lead to infinite recursion when diagnosing the cycle. --- lib/AST/DiagnosticEngine.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index a26d6eafec562..2ceaa744717df 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -1410,11 +1410,15 @@ DiagnosticEngine::diagnosticInfoForDiagnostic(const Diagnostic &diagnostic, loc = decl->getLoc(); // If the location of the decl is invalid still, try to pretty-print the - // declaration into a buffer and capture the source location there. + // declaration into a buffer and capture the source location there. Make + // sure we don't have an active request running since printing AST can + // kick requests that may themselves emit diagnostics. This won't help the + // underlying cycle, but it at least stops us from overflowing the stack. if (loc.isInvalid()) { - loc = evaluateOrDefault( - decl->getASTContext().evaluator, PrettyPrintDeclRequest{decl}, - SourceLoc()); + PrettyPrintDeclRequest req(decl); + auto &eval = decl->getASTContext().evaluator; + if (!eval.hasActiveRequest(req)) + loc = evaluateOrDefault(eval, req, SourceLoc()); } } From 45065f30692d27b9fc3734de2fd9781fa0f460ce Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Sun, 17 Aug 2025 11:48:21 +0100 Subject: [PATCH 2/3] [Diags] Allow multiple in-flight diagnostics Lift the limitation of a single active diagnostic, which was a pretty easy-to-hit footgun. We now maintain an array of active in-flight diagnostics, which gets flushed once all them have ended. --- include/swift/AST/DiagnosticEngine.h | 95 +++++++++++------- lib/AST/DiagnosticEngine.cpp | 99 +++++++++++-------- .../1a9cf8aaa2cfa83f.swift | 2 +- .../56edea24a97933f.swift | 2 +- .../5cc8bc3069f97958.swift | 2 +- .../64915463735bcf5b.swift | 2 +- .../66e337320b1924c.swift | 2 +- .../72eed0e8ff21c1a.swift | 2 +- .../7aa9d3699dddb337.swift | 2 +- .../82fe033c6bdba61.swift | 2 +- .../a81ff5cc2d29ef15.swift | 2 +- .../ad9313b914fb2.swift | 2 +- .../bafa48a4eecbfb62.swift | 2 +- .../bf67776f769fa0f1.swift | 2 +- .../db15a23c5f8aeff.swift | 2 +- .../f8296a9a293c6ae7.swift | 2 +- .../fca26dd570bcdf1c.swift | 2 +- .../ff105cea796d442f.swift | 2 +- 18 files changed, 133 insertions(+), 93 deletions(-) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/1a9cf8aaa2cfa83f.swift (83%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/56edea24a97933f.swift (84%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/5cc8bc3069f97958.swift (86%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/64915463735bcf5b.swift (86%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/66e337320b1924c.swift (82%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/72eed0e8ff21c1a.swift (85%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/7aa9d3699dddb337.swift (84%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/82fe033c6bdba61.swift (82%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/a81ff5cc2d29ef15.swift (84%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/ad9313b914fb2.swift (81%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/bafa48a4eecbfb62.swift (87%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/bf67776f769fa0f1.swift (84%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/db15a23c5f8aeff.swift (83%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/f8296a9a293c6ae7.swift (85%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/fca26dd570bcdf1c.swift (85%) rename validation-test/{compiler_crashers_2 => compiler_crashers_2_fixed}/ff105cea796d442f.swift (86%) diff --git a/include/swift/AST/DiagnosticEngine.h b/include/swift/AST/DiagnosticEngine.h index ad73eac78834b..08a2c93c152bf 100644 --- a/include/swift/AST/DiagnosticEngine.h +++ b/include/swift/AST/DiagnosticEngine.h @@ -279,6 +279,19 @@ namespace swift { } }; + namespace detail { + /// Stores information for an active diagnostic that hasn't been emitted yet. + /// This includes both "in-flight" diagnostics as well as diagnostics queued + /// for a transaction. + struct ActiveDiagnostic { + Diagnostic Diag; + SmallVector WrappedDiagnostics; + SmallVector, 4> WrappedDiagnosticArgs; + + ActiveDiagnostic(Diagnostic diag) : Diag(std::move(diag)) {} + }; + } // namespace detail + /// A diagnostic that has no input arguments, so it is trivially-destructable. using ZeroArgDiagnostic = Diag<>; @@ -293,33 +306,40 @@ namespace swift { friend class DiagnosticEngine; DiagnosticEngine *Engine; + unsigned Idx; bool IsActive; /// Create a new in-flight diagnostic. /// /// This constructor is only available to the DiagnosticEngine. - InFlightDiagnostic(DiagnosticEngine &Engine) - : Engine(&Engine), IsActive(true) { } - + InFlightDiagnostic(DiagnosticEngine &Engine, unsigned idx) + : Engine(&Engine), Idx(idx), IsActive(true) {} + InFlightDiagnostic(const InFlightDiagnostic &) = delete; InFlightDiagnostic &operator=(const InFlightDiagnostic &) = delete; InFlightDiagnostic &operator=(InFlightDiagnostic &&) = delete; + /// Retrieve the underlying active diagnostic information. + detail::ActiveDiagnostic &getActiveDiag() const; + + /// Retrieve the underlying diagnostic. + Diagnostic &getDiag() const { return getActiveDiag().Diag; } + public: /// Create an active but unattached in-flight diagnostic. /// /// The resulting diagnostic can be used as a dummy, accepting the /// syntax to add additional information to a diagnostic without /// actually emitting a diagnostic. - InFlightDiagnostic() : Engine(0), IsActive(true) { } - + InFlightDiagnostic() : Engine(0), Idx(0), IsActive(true) {} + /// Transfer an in-flight diagnostic to a new object, which is /// typically used when returning in-flight diagnostics. InFlightDiagnostic(InFlightDiagnostic &&Other) - : Engine(Other.Engine), IsActive(Other.IsActive) { + : Engine(Other.Engine), Idx(Other.Idx), IsActive(Other.IsActive) { Other.IsActive = false; } - + ~InFlightDiagnostic() { if (IsActive) flush(); @@ -784,16 +804,12 @@ namespace swift { /// Tracks diagnostic behaviors and state DiagnosticState state; - /// The currently active diagnostic, if there is one. - std::optional ActiveDiagnostic; - - /// Diagnostics wrapped by ActiveDiagnostic, if any. - SmallVector WrappedDiagnostics; - SmallVector, 4> WrappedDiagnosticArgs; + /// The currently active diagnostics. + SmallVector ActiveDiagnostics; /// All diagnostics that have are no longer active but have not yet /// been emitted due to an open transaction. - SmallVector TentativeDiagnostics; + SmallVector TentativeDiagnostics; llvm::BumpPtrAllocator TransactionAllocator; /// A set of all strings involved in current transactional chain. @@ -816,6 +832,9 @@ namespace swift { /// emitted once all transactions have closed. unsigned TransactionCount = 0; + /// The number of currently in-flight diagnostics. + unsigned NumActiveDiags = 0; + /// For batch mode, use this to know where to output a diagnostic from a /// non-primary file. It's any location in the buffer of the current primary /// input being compiled. @@ -851,7 +870,7 @@ namespace swift { public: explicit DiagnosticEngine(SourceManager &SourceMgr) - : SourceMgr(SourceMgr), ActiveDiagnostic(), + : SourceMgr(SourceMgr), ActiveDiagnostics(), TransactionStrings(TransactionAllocator), DiagnosticStringsSaver(DiagnosticStringsAllocator) {} @@ -870,6 +889,7 @@ namespace swift { } void flushConsumers() { + ASSERT(NumActiveDiags == 0 && "Expected in-flight diags to be flushed"); for (auto consumer : Consumers) consumer->flush(); } @@ -1001,10 +1021,9 @@ namespace swift { /// \returns An in-flight diagnostic, to which additional information can /// be attached. InFlightDiagnostic diagnose(SourceLoc Loc, const Diagnostic &D) { - assert(!ActiveDiagnostic && "Already have an active diagnostic"); - ActiveDiagnostic = D; - ActiveDiagnostic->setLoc(Loc); - return InFlightDiagnostic(*this); + auto IFD = beginDiagnostic(D); + getActiveDiagnostic(IFD).Diag.setLoc(Loc); + return IFD; } /// Emit a diagnostic with the given set of diagnostic arguments. @@ -1080,10 +1099,9 @@ namespace swift { /// \returns An in-flight diagnostic, to which additional information can /// be attached. InFlightDiagnostic diagnose(const Decl *decl, const Diagnostic &diag) { - assert(!ActiveDiagnostic && "Already have an active diagnostic"); - ActiveDiagnostic = diag; - ActiveDiagnostic->setDecl(decl); - return InFlightDiagnostic(*this); + auto IFD = beginDiagnostic(diag); + getActiveDiagnostic(IFD).Diag.setDecl(decl); + return IFD; } /// Emit a diagnostic with the given set of diagnostic arguments. @@ -1137,16 +1155,21 @@ namespace swift { DiagnosticFormatOptions FormatOpts = DiagnosticFormatOptions()); private: + /// Begins a new in-flight diagnostic. + InFlightDiagnostic beginDiagnostic(const Diagnostic &D); + + /// Ends an in-flight diagnostic. Once all in-flight diagnostics have ended, + /// they will either be emitted, or captured by an open transaction. + void endDiagnostic(const InFlightDiagnostic &D); + /// Called when tentative diagnostic is about to be flushed, /// to apply any required transformations e.g. copy string arguments /// to extend their lifetime. void onTentativeDiagnosticFlush(Diagnostic &diagnostic); - /// Flush the active diagnostic. - void flushActiveDiagnostic(); - - /// Retrieve the active diagnostic. - Diagnostic &getActiveDiagnostic() { return *ActiveDiagnostic; } + /// Retrieve the stored active diagnostic for a given InFlightDiagnostic. + detail::ActiveDiagnostic & + getActiveDiagnostic(const InFlightDiagnostic &diag); /// Generate DiagnosticInfo for a Diagnostic to be passed to consumers. std::optional @@ -1162,7 +1185,7 @@ namespace swift { /// Handle a new diagnostic, which will either be emitted, or added to an /// active transaction. - void handleDiagnostic(Diagnostic &&diag); + void handleDiagnostic(detail::ActiveDiagnostic &&diag); /// Clear any tentative diagnostics. void clearTentativeDiagnostics(); @@ -1291,12 +1314,12 @@ namespace swift { } bool hasErrors() const { - ArrayRef diagnostics(Engine.TentativeDiagnostics.begin() + - PrevDiagnostics, - Engine.TentativeDiagnostics.end()); + ArrayRef diagnostics( + Engine.TentativeDiagnostics.begin() + PrevDiagnostics, + Engine.TentativeDiagnostics.end()); for (auto &diagnostic : diagnostics) { - auto behavior = Engine.state.determineBehavior(diagnostic); + auto behavior = Engine.state.determineBehavior(diagnostic.Diag); if (behavior == DiagnosticBehavior::Fatal || behavior == DiagnosticBehavior::Error) return true; @@ -1361,14 +1384,14 @@ namespace swift { // The first diagnostic is assumed to be the parent. If this is not an // error or warning, we'll assert later when trying to add children. - Diagnostic &parent = Engine.TentativeDiagnostics[PrevDiagnostics]; + Diagnostic &parent = Engine.TentativeDiagnostics[PrevDiagnostics].Diag; // Associate the children with the parent. for (auto diag = Engine.TentativeDiagnostics.begin() + PrevDiagnostics + 1; diag != Engine.TentativeDiagnostics.end(); ++diag) { - diag->setIsChildNote(true); - parent.addChildNote(std::move(*diag)); + diag->Diag.setIsChildNote(true); + parent.addChildNote(std::move(diag->Diag)); } // Erase the children, they'll be emitted alongside their parent. diff --git a/lib/AST/DiagnosticEngine.cpp b/lib/AST/DiagnosticEngine.cpp index 2ceaa744717df..34c6ec51ab86e 100644 --- a/lib/AST/DiagnosticEngine.cpp +++ b/lib/AST/DiagnosticEngine.cpp @@ -205,11 +205,14 @@ static char extractCharBefore(SourceManager &SM, SourceLoc Loc) { return chars[0]; } +detail::ActiveDiagnostic &InFlightDiagnostic::getActiveDiag() const { + return Engine->getActiveDiagnostic(*this); +} + InFlightDiagnostic &InFlightDiagnostic::highlight(SourceRange R) { assert(IsActive && "Cannot modify an inactive diagnostic"); if (Engine && R.isValid()) - Engine->getActiveDiagnostic() - .addRange(toCharSourceRange(Engine->SourceMgr, R)); + getDiag().addRange(toCharSourceRange(Engine->SourceMgr, R)); return *this; } @@ -217,15 +220,14 @@ InFlightDiagnostic &InFlightDiagnostic::highlightChars(SourceLoc Start, SourceLoc End) { assert(IsActive && "Cannot modify an inactive diagnostic"); if (Engine && Start.isValid()) - Engine->getActiveDiagnostic() - .addRange(toCharSourceRange(Engine->SourceMgr, Start, End)); + getDiag().addRange(toCharSourceRange(Engine->SourceMgr, Start, End)); return *this; } InFlightDiagnostic &InFlightDiagnostic::highlightChars(CharSourceRange Range) { assert(IsActive && "Cannot modify an inactive diagnostic"); if (Engine && Range.getStart().isValid()) - Engine->getActiveDiagnostic().addRange(Range); + getDiag().addRange(Range); return *this; } @@ -260,7 +262,7 @@ InFlightDiagnostic &InFlightDiagnostic::fixItRemove(SourceRange R) { charRange = CharSourceRange(charRange.getStart(), charRange.getByteLength()+1); } - Engine->getActiveDiagnostic().addFixIt(Diagnostic::FixIt(charRange, {}, {})); + getDiag().addFixIt(Diagnostic::FixIt(charRange, {}, {})); return *this; } @@ -270,8 +272,7 @@ InFlightDiagnostic::fixItReplace(SourceRange R, StringRef FormatString, auto &SM = Engine->SourceMgr; auto charRange = toCharSourceRange(SM, R); - Engine->getActiveDiagnostic().addFixIt( - Diagnostic::FixIt(charRange, FormatString, Args)); + getDiag().addFixIt(Diagnostic::FixIt(charRange, FormatString, Args)); return *this; } @@ -307,9 +308,8 @@ InFlightDiagnostic::fixItReplaceChars(SourceLoc Start, SourceLoc End, ArrayRef Args) { assert(IsActive && "Cannot modify an inactive diagnostic"); if (Engine && Start.isValid()) - Engine->getActiveDiagnostic().addFixIt( - Diagnostic::FixIt(toCharSourceRange(Engine->SourceMgr, Start, End), - FormatString, Args)); + getDiag().addFixIt(Diagnostic::FixIt( + toCharSourceRange(Engine->SourceMgr, Start, End), FormatString, Args)); return *this; } @@ -350,7 +350,7 @@ SourceLoc DiagnosticEngine::getBestAddImportFixItLoc(SourceFile *SF) const { InFlightDiagnostic &InFlightDiagnostic::fixItAddImport(StringRef ModuleName) { assert(IsActive && "Cannot modify an inactive diagnostic"); - auto decl = Engine->ActiveDiagnostic->getDecl(); + auto decl = getDiag().getDecl(); if (!decl) return *this; @@ -428,16 +428,14 @@ InFlightDiagnostic &InFlightDiagnostic::fixItExchange(SourceRange R1, auto text1 = SM.extractText(charRange1); auto text2 = SM.extractText(charRange2); - Engine->getActiveDiagnostic().addFixIt( - Diagnostic::FixIt(charRange1, "%0", {text2})); - Engine->getActiveDiagnostic().addFixIt( - Diagnostic::FixIt(charRange2, "%0", {text1})); + getDiag().addFixIt(Diagnostic::FixIt(charRange1, "%0", {text2})); + getDiag().addFixIt(Diagnostic::FixIt(charRange2, "%0", {text1})); return *this; } InFlightDiagnostic & InFlightDiagnostic::limitBehavior(DiagnosticBehavior limit) { - Engine->getActiveDiagnostic().setBehaviorLimit(limit); + getDiag().setBehaviorLimit(limit); return *this; } @@ -496,30 +494,33 @@ InFlightDiagnostic::wrapIn(const Diagnostic &wrapper) { // so we don't get a None return or influence future diagnostics. DiagnosticState tempState; Engine->state.swap(tempState); - llvm::SaveAndRestore - limit(Engine->getActiveDiagnostic().BehaviorLimit, - DiagnosticBehavior::Unspecified); - Engine->WrappedDiagnostics.push_back(*Engine->diagnosticInfoForDiagnostic( - Engine->getActiveDiagnostic(), /* includeDiagnosticName= */ false)); + auto &ActiveDiag = getActiveDiag(); + auto &Diag = ActiveDiag.Diag; + + llvm::SaveAndRestore limit( + Diag.BehaviorLimit, DiagnosticBehavior::Unspecified); + + ActiveDiag.WrappedDiagnostics.push_back(*Engine->diagnosticInfoForDiagnostic( + Diag, /* includeDiagnosticName= */ false)); Engine->state.swap(tempState); - auto &wrapped = Engine->WrappedDiagnostics.back(); + auto &wrapped = ActiveDiag.WrappedDiagnostics.back(); // Copy and update its arg list. - Engine->WrappedDiagnosticArgs.emplace_back(wrapped.FormatArgs); - wrapped.FormatArgs = Engine->WrappedDiagnosticArgs.back(); + ActiveDiag.WrappedDiagnosticArgs.emplace_back(wrapped.FormatArgs); + wrapped.FormatArgs = ActiveDiag.WrappedDiagnosticArgs.back(); // Overwrite the ID and arguments with those from the wrapper. - Engine->getActiveDiagnostic().ID = wrapper.ID; - Engine->getActiveDiagnostic().Args = wrapper.Args; + Diag.ID = wrapper.ID; + Diag.Args = wrapper.Args; // Intentionally keeping the original GroupID here // Set the argument to the diagnostic being wrapped. ASSERT(wrapper.getArgs().front().getKind() == DiagnosticArgumentKind::Diagnostic); - Engine->getActiveDiagnostic().Args.front() = &wrapped; + Diag.Args.front() = &wrapped; return *this; } @@ -530,7 +531,7 @@ void InFlightDiagnostic::flush() { IsActive = false; if (Engine) - Engine->flushActiveDiagnostic(); + Engine->endDiagnostic(*this); } void Diagnostic::addChildNote(Diagnostic &&D) { @@ -1354,32 +1355,48 @@ void DiagnosticState::updateFor(DiagnosticBehavior behavior) { previousBehavior = behavior; } -void DiagnosticEngine::flushActiveDiagnostic() { - assert(ActiveDiagnostic && "No active diagnostic to flush"); - handleDiagnostic(std::move(*ActiveDiagnostic)); - ActiveDiagnostic.reset(); +InFlightDiagnostic DiagnosticEngine::beginDiagnostic(const Diagnostic &D) { + unsigned idx = ActiveDiagnostics.size(); + ActiveDiagnostics.emplace_back(D); + NumActiveDiags += 1; + return InFlightDiagnostic(*this, idx); +} + +void DiagnosticEngine::endDiagnostic(const InFlightDiagnostic &D) { + // Decrement the number of active diagnostics. We wait until all in-flight + // diagnostics have ended to ensure a FIFO ordering. + ASSERT(NumActiveDiags > 0 && "Unbalanced call to endDiagnostic"); + NumActiveDiags -= 1; + if (NumActiveDiags > 0) + return; + + for (auto &D : ActiveDiagnostics) + handleDiagnostic(std::move(D)); + + ActiveDiagnostics.clear(); +} + +detail::ActiveDiagnostic & +DiagnosticEngine::getActiveDiagnostic(const InFlightDiagnostic &diag) { + return ActiveDiagnostics[diag.Idx]; } -void DiagnosticEngine::handleDiagnostic(Diagnostic &&diag) { +void DiagnosticEngine::handleDiagnostic(detail::ActiveDiagnostic &&diag) { if (TransactionCount == 0) { - emitDiagnostic(diag); - WrappedDiagnostics.clear(); - WrappedDiagnosticArgs.clear(); + emitDiagnostic(diag.Diag); } else { - onTentativeDiagnosticFlush(diag); + onTentativeDiagnosticFlush(diag.Diag); TentativeDiagnostics.emplace_back(std::move(diag)); } } void DiagnosticEngine::clearTentativeDiagnostics() { TentativeDiagnostics.clear(); - WrappedDiagnostics.clear(); - WrappedDiagnosticArgs.clear(); } void DiagnosticEngine::emitTentativeDiagnostics() { for (auto &diag : TentativeDiagnostics) { - emitDiagnostic(diag); + emitDiagnostic(diag.Diag); } clearTentativeDiagnostics(); } diff --git a/validation-test/compiler_crashers_2/1a9cf8aaa2cfa83f.swift b/validation-test/compiler_crashers_2_fixed/1a9cf8aaa2cfa83f.swift similarity index 83% rename from validation-test/compiler_crashers_2/1a9cf8aaa2cfa83f.swift rename to validation-test/compiler_crashers_2_fixed/1a9cf8aaa2cfa83f.swift index 92a703da54eb3..b08add06cc2fb 100644 --- a/validation-test/compiler_crashers_2/1a9cf8aaa2cfa83f.swift +++ b/validation-test/compiler_crashers_2_fixed/1a9cf8aaa2cfa83f.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"diagnoseInvalidObjCName(swift::ValueDecl*, swift::ObjCAttr*)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop @objcMembers class a open extension a { func 0.0 diff --git a/validation-test/compiler_crashers_2/56edea24a97933f.swift b/validation-test/compiler_crashers_2_fixed/56edea24a97933f.swift similarity index 84% rename from validation-test/compiler_crashers_2/56edea24a97933f.swift rename to validation-test/compiler_crashers_2_fixed/56edea24a97933f.swift index f6762eba2d498..f64af92306ad6 100644 --- a/validation-test/compiler_crashers_2/56edea24a97933f.swift +++ b/validation-test/compiler_crashers_2_fixed/56edea24a97933f.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::isRepresentableInObjC(swift::VarDecl const*, swift::ObjCReason)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class a class b open extension b { @objc c : a diff --git a/validation-test/compiler_crashers_2/5cc8bc3069f97958.swift b/validation-test/compiler_crashers_2_fixed/5cc8bc3069f97958.swift similarity index 86% rename from validation-test/compiler_crashers_2/5cc8bc3069f97958.swift rename to validation-test/compiler_crashers_2_fixed/5cc8bc3069f97958.swift index e80667ec63bb3..996cb30444deb 100644 --- a/validation-test/compiler_crashers_2/5cc8bc3069f97958.swift +++ b/validation-test/compiler_crashers_2_fixed/5cc8bc3069f97958.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"(anonymous namespace)::TypeResolver::resolveImplicitlyUnwrappedOptionalType(swift::ImplicitlyUnwrappedOptionalTypeRepr*, swift::TypeResolutionOptions, bool)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s { enum a: b! { } diff --git a/validation-test/compiler_crashers_2/64915463735bcf5b.swift b/validation-test/compiler_crashers_2_fixed/64915463735bcf5b.swift similarity index 86% rename from validation-test/compiler_crashers_2/64915463735bcf5b.swift rename to validation-test/compiler_crashers_2_fixed/64915463735bcf5b.swift index ea0f8f0111370..67ffb2847a5c7 100644 --- a/validation-test/compiler_crashers_2/64915463735bcf5b.swift +++ b/validation-test/compiler_crashers_2_fixed/64915463735bcf5b.swift @@ -1,4 +1,4 @@ // {"kind":"typecheck","signature":"swift::Evaluator::diagnoseCycle(swift::ActiveRequest const&)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: OS=macosx import Distributed typealias DefaultDistributedActorSystem = LocalTestingDistributedActorSystem distributed actor a{distributed... diff --git a/validation-test/compiler_crashers_2/66e337320b1924c.swift b/validation-test/compiler_crashers_2_fixed/66e337320b1924c.swift similarity index 82% rename from validation-test/compiler_crashers_2/66e337320b1924c.swift rename to validation-test/compiler_crashers_2_fixed/66e337320b1924c.swift index 6d712726de2f7..8e41eee816eda 100644 --- a/validation-test/compiler_crashers_2/66e337320b1924c.swift +++ b/validation-test/compiler_crashers_2_fixed/66e337320b1924c.swift @@ -1,3 +1,3 @@ // {"kind":"typecheck","signature":"swift::ProtocolRequiresClassRequest::diagnoseCycle(swift::DiagnosticEngine&) const","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s struct b let b c a = b protocol a : a diff --git a/validation-test/compiler_crashers_2/72eed0e8ff21c1a.swift b/validation-test/compiler_crashers_2_fixed/72eed0e8ff21c1a.swift similarity index 85% rename from validation-test/compiler_crashers_2/72eed0e8ff21c1a.swift rename to validation-test/compiler_crashers_2_fixed/72eed0e8ff21c1a.swift index f4581a132109e..d5639d345e040 100644 --- a/validation-test/compiler_crashers_2/72eed0e8ff21c1a.swift +++ b/validation-test/compiler_crashers_2_fixed/72eed0e8ff21c1a.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"isParamListRepresentableInLanguage(swift::AbstractFunctionDecl const*, swift::ParameterList const*, swift::ObjCReason)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class a open extension a { @objc b(_) diff --git a/validation-test/compiler_crashers_2/7aa9d3699dddb337.swift b/validation-test/compiler_crashers_2_fixed/7aa9d3699dddb337.swift similarity index 84% rename from validation-test/compiler_crashers_2/7aa9d3699dddb337.swift rename to validation-test/compiler_crashers_2_fixed/7aa9d3699dddb337.swift index 7d32e52511c7b..ef7871d8ee0f6 100644 --- a/validation-test/compiler_crashers_2/7aa9d3699dddb337.swift +++ b/validation-test/compiler_crashers_2_fixed/7aa9d3699dddb337.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::PatternTypeRequest::evaluate(swift::Evaluator&, swift::ContextualPattern) const","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop @objcMembers class a open extension a { var b diff --git a/validation-test/compiler_crashers_2/82fe033c6bdba61.swift b/validation-test/compiler_crashers_2_fixed/82fe033c6bdba61.swift similarity index 82% rename from validation-test/compiler_crashers_2/82fe033c6bdba61.swift rename to validation-test/compiler_crashers_2_fixed/82fe033c6bdba61.swift index 68e2502839039..ea43bff0c0236 100644 --- a/validation-test/compiler_crashers_2/82fe033c6bdba61.swift +++ b/validation-test/compiler_crashers_2_fixed/82fe033c6bdba61.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::DerivedConformance::deriveDecodable(swift::ValueDecl*)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s struct a { var b, c : Codable { diff --git a/validation-test/compiler_crashers_2/a81ff5cc2d29ef15.swift b/validation-test/compiler_crashers_2_fixed/a81ff5cc2d29ef15.swift similarity index 84% rename from validation-test/compiler_crashers_2/a81ff5cc2d29ef15.swift rename to validation-test/compiler_crashers_2_fixed/a81ff5cc2d29ef15.swift index ee5783b1a903d..8f9d57cb13841 100644 --- a/validation-test/compiler_crashers_2/a81ff5cc2d29ef15.swift +++ b/validation-test/compiler_crashers_2_fixed/a81ff5cc2d29ef15.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::IsStaticRequest::evaluate(swift::Evaluator&, swift::FuncDecl*) const","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop @objcMembers class a open extension a { ... diff --git a/validation-test/compiler_crashers_2/ad9313b914fb2.swift b/validation-test/compiler_crashers_2_fixed/ad9313b914fb2.swift similarity index 81% rename from validation-test/compiler_crashers_2/ad9313b914fb2.swift rename to validation-test/compiler_crashers_2_fixed/ad9313b914fb2.swift index 8d25aa55a222f..6c56558edbc85 100644 --- a/validation-test/compiler_crashers_2/ad9313b914fb2.swift +++ b/validation-test/compiler_crashers_2_fixed/ad9313b914fb2.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::Evaluator::diagnoseCycle(swift::ActiveRequest const&)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s class a let _ b = a class b : b.c diff --git a/validation-test/compiler_crashers_2/bafa48a4eecbfb62.swift b/validation-test/compiler_crashers_2_fixed/bafa48a4eecbfb62.swift similarity index 87% rename from validation-test/compiler_crashers_2/bafa48a4eecbfb62.swift rename to validation-test/compiler_crashers_2_fixed/bafa48a4eecbfb62.swift index 506b7134048c2..38aef2d70c875 100644 --- a/validation-test/compiler_crashers_2/bafa48a4eecbfb62.swift +++ b/validation-test/compiler_crashers_2_fixed/bafa48a4eecbfb62.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"diagnoseUnknownType(swift::TypeResolution const&, swift::Type, swift::SourceRange, swift::DeclRefTypeRepr*, swift::optionset::OptionSet)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class b open extension b { @objc c : a diff --git a/validation-test/compiler_crashers_2/bf67776f769fa0f1.swift b/validation-test/compiler_crashers_2_fixed/bf67776f769fa0f1.swift similarity index 84% rename from validation-test/compiler_crashers_2/bf67776f769fa0f1.swift rename to validation-test/compiler_crashers_2_fixed/bf67776f769fa0f1.swift index 0bc770bef97af..ad88a55f6ba3d 100644 --- a/validation-test/compiler_crashers_2/bf67776f769fa0f1.swift +++ b/validation-test/compiler_crashers_2_fixed/bf67776f769fa0f1.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"(anonymous namespace)::TypeResolver::resolveType(swift::TypeRepr*, swift::TypeResolutionOptions)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class a open extension a { @objc b : _ diff --git a/validation-test/compiler_crashers_2/db15a23c5f8aeff.swift b/validation-test/compiler_crashers_2_fixed/db15a23c5f8aeff.swift similarity index 83% rename from validation-test/compiler_crashers_2/db15a23c5f8aeff.swift rename to validation-test/compiler_crashers_2_fixed/db15a23c5f8aeff.swift index 91e705fd10182..6d49f28bbc024 100644 --- a/validation-test/compiler_crashers_2/db15a23c5f8aeff.swift +++ b/validation-test/compiler_crashers_2_fixed/db15a23c5f8aeff.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","original":"36a5bbda","signature":"swift::SuperclassDeclRequest::diagnoseCycle(swift::DiagnosticEngine&) const","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s { class a: a { } diff --git a/validation-test/compiler_crashers_2/f8296a9a293c6ae7.swift b/validation-test/compiler_crashers_2_fixed/f8296a9a293c6ae7.swift similarity index 85% rename from validation-test/compiler_crashers_2/f8296a9a293c6ae7.swift rename to validation-test/compiler_crashers_2_fixed/f8296a9a293c6ae7.swift index ac8da3cce6fc9..2d875f2714084 100644 --- a/validation-test/compiler_crashers_2/f8296a9a293c6ae7.swift +++ b/validation-test/compiler_crashers_2_fixed/f8296a9a293c6ae7.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"(anonymous namespace)::TypeResolver::resolveCompositionType(swift::CompositionTypeRepr*, swift::TypeResolutionOptions)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class a open extension a { @objc b : Int & diff --git a/validation-test/compiler_crashers_2/fca26dd570bcdf1c.swift b/validation-test/compiler_crashers_2_fixed/fca26dd570bcdf1c.swift similarity index 85% rename from validation-test/compiler_crashers_2/fca26dd570bcdf1c.swift rename to validation-test/compiler_crashers_2_fixed/fca26dd570bcdf1c.swift index 395d470a2d3b0..ac6ae7e300572 100644 --- a/validation-test/compiler_crashers_2/fca26dd570bcdf1c.swift +++ b/validation-test/compiler_crashers_2_fixed/fca26dd570bcdf1c.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"(anonymous namespace)::TypeResolver::resolveVarargType(swift::VarargTypeRepr*, swift::TypeResolutionOptions)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class a open extension a { @objc b : Int... diff --git a/validation-test/compiler_crashers_2/ff105cea796d442f.swift b/validation-test/compiler_crashers_2_fixed/ff105cea796d442f.swift similarity index 86% rename from validation-test/compiler_crashers_2/ff105cea796d442f.swift rename to validation-test/compiler_crashers_2_fixed/ff105cea796d442f.swift index 7792cf2aea778..c47fa2fdd7fe8 100644 --- a/validation-test/compiler_crashers_2/ff105cea796d442f.swift +++ b/validation-test/compiler_crashers_2_fixed/ff105cea796d442f.swift @@ -1,5 +1,5 @@ // {"kind":"typecheck","signature":"swift::InFlightDiagnostic swift::diagnoseAttrWithRemovalFixIt&>(swift::Decl const*, swift::DeclAttribute const*, swift::Diag<>&)","signatureAssert":"Assertion failed: (!ActiveDiagnostic && \"Already have an active diagnostic\"), function diagnose"} -// RUN: not --crash %target-swift-frontend -typecheck %s +// RUN: not %target-swift-frontend -typecheck %s // REQUIRES: objc_interop class a open extension a { @objc class b From 89feb8fabb5b47771b9dacd1411cb45b2a9d10ef Mon Sep 17 00:00:00 2001 From: Hamish Knight Date: Sun, 17 Aug 2025 11:48:21 +0100 Subject: [PATCH 3/3] [Diags] Remove some now unnecessary calls to `flush` --- lib/Sema/CSApply.cpp | 3 --- lib/Sema/CSDiagnostics.cpp | 17 ++--------------- lib/Sema/CSDiagnostics.h | 2 +- lib/Sema/ImportResolution.cpp | 2 -- lib/Sema/TypeCheckAccess.cpp | 4 +--- lib/Sema/TypeCheckDeclPrimary.cpp | 2 -- lib/Sema/TypeCheckPattern.cpp | 1 - lib/Sema/TypeCheckProtocol.cpp | 16 ++++------------ lib/Serialization/Deserialization.cpp | 4 +--- 9 files changed, 9 insertions(+), 42 deletions(-) diff --git a/lib/Sema/CSApply.cpp b/lib/Sema/CSApply.cpp index 50925acd9a1c2..84d810a10fda1 100644 --- a/lib/Sema/CSApply.cpp +++ b/lib/Sema/CSApply.cpp @@ -5092,9 +5092,6 @@ namespace { // If the property is settable, we don't know whether the // user wanted the getter or setter. Provide notes for each. if (isSettable) { - // Flush the primary diagnostic. We have notes to add. - primaryDiag.flush(); - // Add notes for the getter and setter, respectively. de.diagnose(modifierLoc, diag::expr_selector_add_modifier, false, var) diff --git a/lib/Sema/CSDiagnostics.cpp b/lib/Sema/CSDiagnostics.cpp index 525c8ec622840..e1ad24ab0f54c 100644 --- a/lib/Sema/CSDiagnostics.cpp +++ b/lib/Sema/CSDiagnostics.cpp @@ -1923,7 +1923,6 @@ bool MissingOptionalUnwrapFailure::diagnoseAsError() { "#default value#" "> }"); } - diag.flush(); offerDefaultValueUnwrapFixIt(varDecl->getDeclContext(), initializer); offerForceUnwrapFixIt(initializer); @@ -3150,7 +3149,7 @@ void ContextualFailure::tryFixIts(InFlightDiagnostic &diagnostic) const { if (tryIntegerCastFixIts(diagnostic)) return; - if (tryProtocolConformanceFixIt(diagnostic)) + if (tryProtocolConformanceFixIt()) return; if (tryTypeCoercionFixIt(diagnostic)) @@ -3521,8 +3520,7 @@ bool ContextualFailure::tryTypeCoercionFixIt( return false; } -bool ContextualFailure::tryProtocolConformanceFixIt( - InFlightDiagnostic &diagnostic) const { +bool ContextualFailure::tryProtocolConformanceFixIt() const { auto innermostTyCtx = getDC()->getInnermostTypeContext(); if (!innermostTyCtx) return false; @@ -3556,8 +3554,6 @@ bool ContextualFailure::tryProtocolConformanceFixIt( if (!shouldOfferFixIt) return false; - diagnostic.flush(); - // Let's build a list of protocols that the context does not conform to. SmallVector missingProtoTypeStrings; SmallVector missingProtocols; @@ -4090,7 +4086,6 @@ bool SubscriptMisuseFailure::diagnoseAsError() { } else { diag.fixItReplace(SourceRange(memberExpr->getDotLoc(), memberExpr->getLoc()), "[<#index#>]"); } - diag.flush(); if (auto overload = getOverloadChoiceIfAvailable(locator)) { emitDiagnosticAt(overload->choice.getDecl(), diag::kind_declared_here, @@ -5355,8 +5350,6 @@ bool MissingArgumentsFailure::diagnoseAsError() { diag.fixItInsertAfter(getRawAnchor().getEndLoc(), fixIt.str()); } - diag.flush(); - if (auto selectedOverload = getCalleeOverloadChoiceIfAvailable(locator)) { if (auto *decl = selectedOverload->choice.getDeclOrNull()) { emitDiagnosticAt(decl, diag::decl_declared_here, decl); @@ -5724,8 +5717,6 @@ bool MissingArgumentsFailure::diagnoseInvalidTupleDestructuring() const { diagnostic.fixItRemove(TE->getLParenLoc()).fixItRemove(TE->getRParenLoc()); } - diagnostic.flush(); - // Add a note which points to the overload choice location. emitDiagnosticAt(decl, diag::decl_declared_here, decl); return true; @@ -6126,8 +6117,6 @@ bool ExtraneousArgumentsFailure::diagnoseAsError() { } } - diag.flush(); - // If all of the parameters are anonymous, let's point out references // to make it explicit where parameters are used in complex closure body, // which helps in situations where braces are missing for potential inner @@ -8621,8 +8610,6 @@ void MissingRawRepresentableInitFailure::fixIt( .fixItInsert(range.Start, rawReprObjType->getString() + "(rawValue: ") .fixItInsertAfter(range.End, ")"); } else if (valueObjType) { - diagnostic.flush(); - std::string fixItBefore = RawReprType->getString() + "(rawValue: "; std::string fixItAfter; diff --git a/lib/Sema/CSDiagnostics.h b/lib/Sema/CSDiagnostics.h index 5c65d8a23c067..db63643637066 100644 --- a/lib/Sema/CSDiagnostics.h +++ b/lib/Sema/CSDiagnostics.h @@ -726,7 +726,7 @@ class ContextualFailure : public FailureDiagnostic { /// Try to add a fix-it to conform the decl context (if it's a type) to the /// protocol - bool tryProtocolConformanceFixIt(InFlightDiagnostic &diagnostic) const; + bool tryProtocolConformanceFixIt() const; private: Type resolve(Type rawType) const { diff --git a/lib/Sema/ImportResolution.cpp b/lib/Sema/ImportResolution.cpp index 0b4df8782715f..e14ef37dfb046 100644 --- a/lib/Sema/ImportResolution.cpp +++ b/lib/Sema/ImportResolution.cpp @@ -1159,7 +1159,6 @@ CheckInconsistentAccessLevelOnImport::evaluate( error.fixItInsert(implicitImport->getStartLoc(), diag::inconsistent_implicit_access_level_on_import_fixit, otherAccessLevel); - error.flush(); diags.diagnose(implicitImport, diag::inconsistent_implicit_access_level_on_import_silence); } @@ -1352,7 +1351,6 @@ ScopedImportLookupRequest::evaluate(Evaluator &evaluator, emittedDiag->fixItReplace(SourceRange(import->getKindLoc()), getImportKindString(*actualKind)); - emittedDiag->flush(); if (decls.size() == 1) ctx.Diags.diagnose(decls.front(), diag::decl_declared_here, diff --git a/lib/Sema/TypeCheckAccess.cpp b/lib/Sema/TypeCheckAccess.cpp index df58d18e1b2c3..56c702a1e0a59 100644 --- a/lib/Sema/TypeCheckAccess.cpp +++ b/lib/Sema/TypeCheckAccess.cpp @@ -363,12 +363,10 @@ void AccessControlCheckerBase::checkTypeAccess( static void highlightOffendingType(InFlightDiagnostic &diag, const TypeRepr *complainRepr) { if (!complainRepr) { - diag.flush(); return; } diag.highlight(complainRepr->getSourceRange()); - diag.flush(); if (auto *declRefTR = dyn_cast(complainRepr)) { const ValueDecl *VD = declRefTR->getBoundDecl(); @@ -2480,7 +2478,7 @@ class DeclAvailabilityChecker : public DeclVisitor { ); if (refRange.isValid()) diag.highlight(refRange); - diag.flush(); + PGD->diagnose(diag::name_declared_here, PGD->getName()); } diff --git a/lib/Sema/TypeCheckDeclPrimary.cpp b/lib/Sema/TypeCheckDeclPrimary.cpp index a290483e08c72..bb64bc738022b 100644 --- a/lib/Sema/TypeCheckDeclPrimary.cpp +++ b/lib/Sema/TypeCheckDeclPrimary.cpp @@ -2036,7 +2036,6 @@ static void diagnoseChangesByAccessNote( if (fixItLoc.isInvalid()) fixItLoc = attr->getRangeWithAt().Start; } - diag.flush(); if (!fixItLoc) fixItLoc = VD->getAttributeInsertionLoc(true); @@ -4028,7 +4027,6 @@ class DeclChecker : public DeclVisitor { nominal->getDeclaredType()); diag.highlight(extTypeRepr->getSourceRange()); if (firstNominalIsNotMostSpecific) { - diag.flush(); Type mostSpecificProtocol = extTypeNominal->getDeclaredType(); ED->diagnose(diag::composition_in_extended_type_alternative, mostSpecificProtocol) diff --git a/lib/Sema/TypeCheckPattern.cpp b/lib/Sema/TypeCheckPattern.cpp index 7b32dc99b585f..52d8705d7b072 100644 --- a/lib/Sema/TypeCheckPattern.cpp +++ b/lib/Sema/TypeCheckPattern.cpp @@ -1010,7 +1010,6 @@ void repairTupleOrAssociatedValuePatternIfApplicable( auto trailingParen = SourceRange(enumElementInnerPat->getEndLoc()); diag.fixItRemove(leadingParen).fixItRemove(trailingParen); } - diag.flush(); addDeclNote(); enumElementInnerPat = semantic; } else { diff --git a/lib/Sema/TypeCheckProtocol.cpp b/lib/Sema/TypeCheckProtocol.cpp index a1350bfd42a99..825de49b1eccb 100644 --- a/lib/Sema/TypeCheckProtocol.cpp +++ b/lib/Sema/TypeCheckProtocol.cpp @@ -4049,16 +4049,14 @@ static void diagnoseProtocolStubFixit( // Issue diagnostics for witness types. if (auto MissingTypeWitness = dyn_cast(VD)) { - std::optional diag; if (isa(DC->getSelfNominalTypeDecl())) { auto expectedTy = getTupleConformanceTypeWitness(DC, MissingTypeWitness); - diag.emplace(Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type_tuple, - MissingTypeWitness, expectedTy)); + Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type_tuple, + MissingTypeWitness, expectedTy); } else { - diag.emplace(Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type, - MissingTypeWitness)); + Diags.diagnose(MissingTypeWitness, diag::no_witnesses_type, + MissingTypeWitness); } - diag.value().flush(); continue; } @@ -4208,7 +4206,6 @@ void ConformanceChecker::checkNonFinalClassWitness(ValueDecl *requirement, // If the main diagnostic is emitted on the conformance, we want to // attach the fix-it to the note that shows where the initializer is // defined. - fixItDiag.value().flush(); fixItDiag.emplace(diags.diagnose(ctor, diag::decl_declared_here, ctor)); } @@ -4387,7 +4384,6 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { if (diagLoc == witness->getLoc()) { fixDeclarationName(diag, witness, requirement->getName()); } else { - diag.flush(); diags.diagnose(witness, diag::decl_declared_here, witness); } } @@ -4568,7 +4564,6 @@ ConformanceChecker::resolveWitnessViaLookup(ValueDecl *requirement) { if (diagLoc == witness->getLoc()) { addOptionalityFixIts(adjustments, ctx, witness, diag); } else { - diag.flush(); diags.diagnose(witness, diag::decl_declared_here, witness); } } @@ -5661,7 +5656,6 @@ void ConformanceChecker::resolveValueWitnesses() { // If the main diagnostic is emitted on the conformance, we want // to attach the fix-it to the note that shows where the // witness is defined. - fixItDiag.value().flush(); fixItDiag.emplace( witness->diagnose(diag::make_decl_objc, witness)); } @@ -5681,7 +5675,6 @@ void ConformanceChecker::resolveValueWitnesses() { // If the main diagnostic is emitted on the conformance, we want // to attach the fix-it to the note that shows where the // witness is defined. - fixItDiag.value().flush(); fixItDiag.emplace( witness->diagnose(diag::make_decl_objc, witness)); } @@ -5701,7 +5694,6 @@ void ConformanceChecker::resolveValueWitnesses() { // If the main diagnostic is emitted on the conformance, we want // to attach the fix-it to the note that shows where the // witness is defined. - fixItDiag.value().flush(); fixItDiag.emplace( witness->diagnose(diag::make_decl_objc, witness)); } diff --git a/lib/Serialization/Deserialization.cpp b/lib/Serialization/Deserialization.cpp index 40663997609e3..5705760de92ef 100644 --- a/lib/Serialization/Deserialization.cpp +++ b/lib/Serialization/Deserialization.cpp @@ -255,9 +255,7 @@ ModularizationError::diagnose(const ModuleFile *MF, llvm_unreachable("Unhandled ModularizationError::Kind in switch."); }; - auto inFlight = diagnoseError(errorKind); - inFlight.limitBehavior(limit); - inFlight.flush(); + diagnoseError(errorKind).limitBehavior(limit); // We could pass along the `path` information through notes. // However, for a top-level decl a path would just duplicate the