Skip to content

Commit 4ecf914

Browse files
authored
Make SemIRLoc data private to diagnostics (#4867)
I think the name of `SemIRLoc` might be leading to a few suggestions to use it for non-diagnostic purposes that I've been responding to. At the same time, a short name seems desirable given its frequency of use for diagnostics. I did also clean up misuse in #4857, and eval.cpp (noted below) might be similar. We don't typically use `friend` to emphasize relationships, but given the diagnostic-specific intent and ways it's been used, perhaps it's reasonable to close the API of this type using `friend`? eval.cpp inspects contents, but it's not clear that's needed because changing logic doesn't affect tests, so I'm just removing it. Note that SemIRLoc could've also been a loc_id, and it seems like the current approach would mishandle that (i.e., print for `LocId::None` when that seems not to be the intent). I figure we can add a `has_value` or `AddNoteRequiringLoc` or something like that if needed.
1 parent bb67c7d commit 4ecf914

File tree

3 files changed

+24
-19
lines changed

3 files changed

+24
-19
lines changed

toolchain/check/diagnostic_helpers.h

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -12,29 +12,37 @@
1212

1313
namespace Carbon::Check {
1414

15-
// Diagnostic locations produced by checking may be either a parse node
16-
// directly, or an inst ID which is later translated to a parse node.
17-
struct SemIRLoc {
15+
// Tracks a location for diagnostic use, which is either a parse node or an inst
16+
// ID which can be translated to a parse node. Used when code needs to support
17+
// multiple possible ways of reporting a diagnostic location.
18+
class SemIRLoc {
19+
public:
1820
// NOLINTNEXTLINE(google-explicit-constructor)
1921
SemIRLoc(SemIR::InstId inst_id)
20-
: inst_id(inst_id), is_inst_id(true), token_only(false) {}
22+
: inst_id_(inst_id), is_inst_id_(true), token_only_(false) {}
2123

2224
// NOLINTNEXTLINE(google-explicit-constructor)
2325
SemIRLoc(Parse::NodeId node_id) : SemIRLoc(node_id, false) {}
2426

2527
// NOLINTNEXTLINE(google-explicit-constructor)
2628
SemIRLoc(SemIR::LocId loc_id) : SemIRLoc(loc_id, false) {}
2729

30+
// If `token_only` is true, refers to the specific node; otherwise, refers to
31+
// the node and its children.
2832
explicit SemIRLoc(SemIR::LocId loc_id, bool token_only)
29-
: loc_id(loc_id), is_inst_id(false), token_only(token_only) {}
33+
: loc_id_(loc_id), is_inst_id_(false), token_only_(token_only) {}
34+
35+
private:
36+
// Only allow member access for diagnostics.
37+
friend class SemIRDiagnosticConverter;
3038

3139
union {
32-
SemIR::InstId inst_id;
33-
SemIR::LocId loc_id;
40+
SemIR::InstId inst_id_;
41+
SemIR::LocId loc_id_;
3442
};
3543

36-
bool is_inst_id;
37-
bool token_only;
44+
bool is_inst_id_;
45+
bool token_only_;
3846
};
3947

4048
inline auto TokenOnly(SemIR::LocId loc_id) -> SemIRLoc {

toolchain/check/eval.cpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2126,9 +2126,6 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
21262126
&context.emitter(), [&](auto& builder) {
21272127
CARBON_DIAGNOSTIC(ResolvingSpecificHere, Note, "in {0} used here",
21282128
InstIdAsType);
2129-
if (loc.is_inst_id && !loc.inst_id.has_value()) {
2130-
return;
2131-
}
21322129
builder.Note(loc, ResolvingSpecificHere,
21332130
GetInstForSpecific(context, specific_id));
21342131
});

toolchain/check/sem_ir_diagnostic_converter.cpp

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
5353
if (import_loc_id.is_node_id()) {
5454
// For imports in the current file, the location is simple.
5555
in_import_loc = ConvertLocInFile(cursor_ir, import_loc_id.node_id(),
56-
loc.token_only, context_fn);
56+
loc.token_only_, context_fn);
5757
} else if (import_loc_id.is_import_ir_inst_id()) {
5858
// For implicit imports, we need to unravel the location a little
5959
// further.
@@ -67,7 +67,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
6767
"Should only be one layer of implicit imports");
6868
in_import_loc =
6969
ConvertLocInFile(implicit_ir.sem_ir, implicit_loc_id.node_id(),
70-
loc.token_only, context_fn);
70+
loc.token_only_, context_fn);
7171
}
7272

7373
// TODO: Add an "In implicit import of prelude." note for the case where we
@@ -91,16 +91,16 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
9191
return std::nullopt;
9292
} else {
9393
// Parse nodes always refer to the current IR.
94-
return ConvertLocInFile(cursor_ir, loc_id.node_id(), loc.token_only,
94+
return ConvertLocInFile(cursor_ir, loc_id.node_id(), loc.token_only_,
9595
context_fn);
9696
}
9797
};
9898

9999
// Handle the base location.
100-
if (loc.is_inst_id) {
101-
cursor_inst_id = loc.inst_id;
100+
if (loc.is_inst_id_) {
101+
cursor_inst_id = loc.inst_id_;
102102
} else {
103-
if (auto diag_loc = handle_loc(loc.loc_id)) {
103+
if (auto diag_loc = handle_loc(loc.loc_id_)) {
104104
return *diag_loc;
105105
}
106106
CARBON_CHECK(cursor_inst_id.has_value(), "Should have been set");
@@ -135,7 +135,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
135135
}
136136

137137
// `None` parse node but not an import; just nothing to point at.
138-
return ConvertLocInFile(cursor_ir, Parse::NodeId::None, loc.token_only,
138+
return ConvertLocInFile(cursor_ir, Parse::NodeId::None, loc.token_only_,
139139
context_fn);
140140
}
141141
}

0 commit comments

Comments
 (0)