Skip to content

Commit eb428be

Browse files
Merge pull request #78398 from AnthonyLatsis/micronecta-scholtzi
DiagnosticEngine: Fix diagnostic groups behavior for wrapped diagnostics
2 parents 28160c9 + c4793b6 commit eb428be

File tree

9 files changed

+244
-49
lines changed

9 files changed

+244
-49
lines changed

include/swift/AST/DiagnosticEngine.h

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
#include "swift/AST/ActorIsolation.h"
2222
#include "swift/AST/DeclNameLoc.h"
2323
#include "swift/AST/DiagnosticConsumer.h"
24-
#include "swift/AST/DiagnosticGroups.h"
2524
#include "swift/AST/TypeLoc.h"
2625
#include "swift/Basic/PrintDiagnosticNamesMode.h"
2726
#include "swift/Basic/Statistic.h"
@@ -68,6 +67,8 @@ namespace swift {
6867
/// this enumeration type that uniquely identifies it.
6968
enum class DiagID : uint32_t;
7069

70+
enum class DiagGroupID : uint16_t;
71+
7172
/// Describes a diagnostic along with its argument types.
7273
///
7374
/// The diagnostics header introduces instances of this type for each
@@ -512,11 +513,17 @@ namespace swift {
512513
friend DiagnosticEngine;
513514
friend class InFlightDiagnostic;
514515

515-
Diagnostic(DiagID ID, DiagGroupID GroupID) : ID(ID), GroupID(GroupID) {}
516-
517516
/// Constructs a Diagnostic with DiagGroupID infered from DiagID.
518517
Diagnostic(DiagID ID);
519518

519+
protected:
520+
/// Only use this constructor privately in this class or in unit tests by
521+
/// subclassing.
522+
/// In unit tests, it is used as a means for associating diagnostics with
523+
/// groups and, thus, circumventing the need to otherwise define mock
524+
/// diagnostics, which is not accounted for in the current design.
525+
Diagnostic(DiagID ID, DiagGroupID GroupID) : ID(ID), GroupID(GroupID) {}
526+
520527
public:
521528
// All constructors are intentionally implicit.
522529
template<typename ...ArgTypes>
@@ -527,8 +534,9 @@ namespace swift {
527534
gatherArgs(VArgs...);
528535
}
529536

530-
/*implicit*/Diagnostic(DiagID ID, ArrayRef<DiagnosticArgument> Args)
531-
: ID(ID), Args(Args.begin(), Args.end()) {}
537+
Diagnostic(DiagID ID, ArrayRef<DiagnosticArgument> Args) : Diagnostic(ID) {
538+
this->Args.append(Args.begin(), Args.end());
539+
}
532540

533541
template <class... ArgTypes>
534542
static Diagnostic fromTuple(Diag<ArgTypes...> id,
@@ -902,7 +910,9 @@ namespace swift {
902910
/// Don't emit any remarks
903911
bool suppressRemarks = false;
904912

905-
/// Treat these warnings as errors. Indices here correspond to DiagID enum
913+
/// A mapping from `DiagGroupID` identifiers to Boolean values indicating
914+
/// whether warnings belonging to the respective diagnostic groups should be
915+
/// escalated to errors.
906916
llvm::BitVector warningsAsErrors;
907917

908918
/// Whether a fatal error has occurred
@@ -944,16 +954,23 @@ namespace swift {
944954
void setSuppressRemarks(bool val) { suppressRemarks = val; }
945955
bool getSuppressRemarks() const { return suppressRemarks; }
946956

947-
/// Whether a warning should be upgraded to an error or not
948-
void setWarningAsErrorForDiagID(DiagID id, bool value) {
957+
/// Sets whether warnings belonging to the diagnostic group identified by
958+
/// `id` should be escalated to errors.
959+
void setWarningsAsErrorsForDiagGroupID(DiagGroupID id, bool value) {
949960
warningsAsErrors[(unsigned)id] = value;
950961
}
951-
bool getWarningAsErrorForDiagID(DiagID id) {
962+
963+
/// Returns a Boolean value indicating whether warnings belonging to the
964+
/// diagnostic group identified by `id` should be escalated to errors.
965+
bool getWarningsAsErrorsForDiagGroupID(DiagGroupID id) {
952966
return warningsAsErrors[(unsigned)id];
953967
}
954968

955-
/// Whether all warnings should be upgraded to errors or not
969+
/// Whether all warnings should be upgraded to errors or not.
956970
void setAllWarningsAsErrors(bool value) {
971+
// This works as intended because every diagnostic belongs to either a
972+
// custom group or the top-level `DiagGroupID::no_group`, which is also
973+
// a group.
957974
if (value) {
958975
warningsAsErrors.set();
959976
} else {

include/swift/AST/DiagnosticGroups.def

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,6 @@ GROUP(no_group, "")
2525
GROUP(DeprecatedDeclaration, "DeprecatedDeclaration.md")
2626
GROUP(Unsafe, "Unsafe.md")
2727
GROUP(UnknownWarningGroup, "UnknownWarningGroup.md")
28-
GROUP(DeclarationUnavailableFromAsynchronousContext, "DeclarationUnavailableFromAsynchronousContext.md")
2928

3029
#define UNDEFINE_DIAGNOSTIC_GROUPS_MACROS
3130
#include "swift/AST/DefineDiagnosticGroupsMacros.h"

include/swift/AST/DiagnosticGroups.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ enum class DiagGroupID : uint16_t {
3333

3434
constexpr const auto DiagGroupsCount = [] {
3535
size_t count = 0;
36-
#define GROUP(Name, Version) count++;
36+
#define GROUP(Name, Version) ++count;
3737
#include "DiagnosticGroups.def"
3838
return count;
3939
}();

include/swift/AST/DiagnosticsSema.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5963,7 +5963,7 @@ ERROR(async_decl_must_be_available_from_async,none,
59635963
ERROR(async_named_decl_must_be_available_from_async,none,
59645964
"asynchronous %kind0 must be available from asynchronous contexts",
59655965
(const ValueDecl *))
5966-
GROUPED_ERROR(async_unavailable_decl,DeclarationUnavailableFromAsynchronousContext,none,
5966+
ERROR(async_unavailable_decl,none,
59675967
"%kindbase0 is unavailable from asynchronous contexts%select{|; %1}1",
59685968
(const ValueDecl *, StringRef))
59695969

lib/AST/DiagnosticEngine.cpp

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ DiagnosticState::DiagnosticState() {
176176
// Initialize our ignored diagnostics to default
177177
ignoredDiagnostics.resize(LocalDiagID::NumDiags);
178178
// Initialize warningsAsErrors to default
179-
warningsAsErrors.resize(LocalDiagID::NumDiags);
179+
warningsAsErrors.resize(DiagGroupsCount);
180180
}
181181

182182
Diagnostic::Diagnostic(DiagID ID)
@@ -551,9 +551,7 @@ void DiagnosticEngine::setWarningsAsErrorsRules(
551551
if (auto groupID = getDiagGroupIDByName(name);
552552
groupID && *groupID != DiagGroupID::no_group) {
553553
getDiagGroupInfoByID(*groupID).traverseDepthFirst([&](auto group) {
554-
for (DiagID diagID : group.diagnostics) {
555-
state.setWarningAsErrorForDiagID(diagID, isEnabled);
556-
}
554+
state.setWarningsAsErrorsForDiagGroupID(*groupID, isEnabled);
557555
});
558556
} else {
559557
unknownGroups.push_back(std::string(name));
@@ -1232,7 +1230,7 @@ DiagnosticBehavior DiagnosticState::determineBehavior(const Diagnostic &diag) {
12321230
// 4) If the user substituted a different behavior for this behavior, apply
12331231
// that change
12341232
if (lvl == DiagnosticBehavior::Warning) {
1235-
if (getWarningAsErrorForDiagID(diag.getID()))
1233+
if (getWarningsAsErrorsForDiagGroupID(diag.getGroupID()))
12361234
lvl = DiagnosticBehavior::Error;
12371235
if (suppressWarnings)
12381236
lvl = DiagnosticBehavior::Ignore;

test/attr/attr_availability_noasync.swift

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
// RUN: %target-typecheck-verify-swift -print-diagnostic-groups
1+
// RUN: %target-typecheck-verify-swift
22

33
// REQUIRES: concurrency
44

@@ -27,16 +27,16 @@ actor IOActor {
2727

2828
@available(SwiftStdlib 5.5, *)
2929
func asyncFunc() async {
30-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
30+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
3131
basicNoAsync()
3232

33-
// expected-warning@+1{{global function 'messageNoAsync' is unavailable from asynchronous contexts; a message from the author; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
33+
// expected-warning@+1{{global function 'messageNoAsync' is unavailable from asynchronous contexts; a message from the author; this is an error in the Swift 6 language mode}}
3434
messageNoAsync()
3535

36-
// expected-warning@+1{{global function 'renamedNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}{{5-19=asyncReplacement}}
36+
// expected-warning@+1{{global function 'renamedNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}{{5-19=asyncReplacement}}
3737
renamedNoAsync() { _ in }
3838

39-
// expected-warning@+1{{global function 'readStringFromIO' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}{{13-29=IOActor.readString}}
39+
// expected-warning@+1{{global function 'readStringFromIO' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}{{13-29=IOActor.readString}}
4040
let _ = readStringFromIO()
4141
}
4242

@@ -76,7 +76,7 @@ func test_defers_sync() {
7676
}
7777

7878
func local_async_func() async {
79-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
79+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
8080
defer { basicNoAsync() }
8181
_ = ()
8282
}
@@ -89,7 +89,7 @@ func test_defers_sync() {
8989

9090
// local async closure
9191
let local_async_closure = { () async -> Void in
92-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
92+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
9393
defer { basicNoAsync() }
9494
_ = ()
9595
}
@@ -102,7 +102,7 @@ func test_defers_sync() {
102102

103103
var local_async_var: Void {
104104
get async {
105-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
105+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
106106
defer { basicNoAsync() }
107107
return ()
108108
}
@@ -112,9 +112,9 @@ func test_defers_sync() {
112112
@available(SwiftStdlib 5.5, *)
113113
func test_defer_async() async {
114114
defer {
115-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
115+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
116116
defer { basicNoAsync() }
117-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
117+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
118118
basicNoAsync()
119119
}
120120

@@ -124,7 +124,7 @@ func test_defer_async() async {
124124
}
125125

126126
func local_async_func() async {
127-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
127+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
128128
defer { basicNoAsync() }
129129
_ = ()
130130
}
@@ -136,7 +136,7 @@ func test_defer_async() async {
136136
_ = local_sync_closure
137137

138138
let local_async_closure = { () async -> Void in
139-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
139+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
140140
defer { basicNoAsync() }
141141
_ = ()
142142
}
@@ -149,7 +149,7 @@ func test_defer_async() async {
149149

150150
var local_async_var: Void {
151151
get async {
152-
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode [DeclarationUnavailableFromAsynchronousContext]}}
152+
// expected-warning@+1{{global function 'basicNoAsync' is unavailable from asynchronous contexts; this is an error in the Swift 6 language mode}}
153153
defer { basicNoAsync() }
154154
return ()
155155
}

unittests/AST/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ add_swift_unittest(SwiftASTTests
44
ASTWalkerTests.cpp
55
IndexSubsetTests.cpp
66
DiagnosticConsumerTests.cpp
7+
DiagnosticGroupsTests.cpp
78
SourceLocTests.cpp
89
TestContext.cpp
910
TypeMatchTests.cpp

0 commit comments

Comments
 (0)