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.
This commit is contained in:
Jon Ross-Perkins
2025-01-29 20:46:30 +00:00
committed by GitHub
parent bb67c7dfb2
commit 4ecf914a07
3 changed files with 24 additions and 19 deletions
+17 -9
View File
@@ -12,12 +12,14 @@
namespace Carbon::Check {
// Diagnostic locations produced by checking may be either a parse node
// directly, or an inst ID which is later translated to a parse node.
struct SemIRLoc {
// Tracks a location for diagnostic use, which is either a parse node or an inst
// ID which can be translated to a parse node. Used when code needs to support
// multiple possible ways of reporting a diagnostic location.
class SemIRLoc {
public:
// NOLINTNEXTLINE(google-explicit-constructor)
SemIRLoc(SemIR::InstId inst_id)
: inst_id(inst_id), is_inst_id(true), token_only(false) {}
: inst_id_(inst_id), is_inst_id_(true), token_only_(false) {}
// NOLINTNEXTLINE(google-explicit-constructor)
SemIRLoc(Parse::NodeId node_id) : SemIRLoc(node_id, false) {}
@@ -25,16 +27,22 @@ struct SemIRLoc {
// NOLINTNEXTLINE(google-explicit-constructor)
SemIRLoc(SemIR::LocId loc_id) : SemIRLoc(loc_id, false) {}
// If `token_only` is true, refers to the specific node; otherwise, refers to
// the node and its children.
explicit SemIRLoc(SemIR::LocId loc_id, bool token_only)
: loc_id(loc_id), is_inst_id(false), token_only(token_only) {}
: loc_id_(loc_id), is_inst_id_(false), token_only_(token_only) {}
private:
// Only allow member access for diagnostics.
friend class SemIRDiagnosticConverter;
union {
SemIR::InstId inst_id;
SemIR::LocId loc_id;
SemIR::InstId inst_id_;
SemIR::LocId loc_id_;
};
bool is_inst_id;
bool token_only;
bool is_inst_id_;
bool token_only_;
};
inline auto TokenOnly(SemIR::LocId loc_id) -> SemIRLoc {
-3
View File
@@ -2126,9 +2126,6 @@ auto TryEvalBlockForSpecific(Context& context, SemIRLoc loc,
&context.emitter(), [&](auto& builder) {
CARBON_DIAGNOSTIC(ResolvingSpecificHere, Note, "in {0} used here",
InstIdAsType);
if (loc.is_inst_id && !loc.inst_id.has_value()) {
return;
}
builder.Note(loc, ResolvingSpecificHere,
GetInstForSpecific(context, specific_id));
});
@@ -53,7 +53,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
if (import_loc_id.is_node_id()) {
// For imports in the current file, the location is simple.
in_import_loc = ConvertLocInFile(cursor_ir, import_loc_id.node_id(),
loc.token_only, context_fn);
loc.token_only_, context_fn);
} else if (import_loc_id.is_import_ir_inst_id()) {
// For implicit imports, we need to unravel the location a little
// further.
@@ -67,7 +67,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
"Should only be one layer of implicit imports");
in_import_loc =
ConvertLocInFile(implicit_ir.sem_ir, implicit_loc_id.node_id(),
loc.token_only, context_fn);
loc.token_only_, context_fn);
}
// TODO: Add an "In implicit import of prelude." note for the case where we
@@ -91,16 +91,16 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
return std::nullopt;
} else {
// Parse nodes always refer to the current IR.
return ConvertLocInFile(cursor_ir, loc_id.node_id(), loc.token_only,
return ConvertLocInFile(cursor_ir, loc_id.node_id(), loc.token_only_,
context_fn);
}
};
// Handle the base location.
if (loc.is_inst_id) {
cursor_inst_id = loc.inst_id;
if (loc.is_inst_id_) {
cursor_inst_id = loc.inst_id_;
} else {
if (auto diag_loc = handle_loc(loc.loc_id)) {
if (auto diag_loc = handle_loc(loc.loc_id_)) {
return *diag_loc;
}
CARBON_CHECK(cursor_inst_id.has_value(), "Should have been set");
@@ -135,7 +135,7 @@ auto SemIRDiagnosticConverter::ConvertLocImpl(SemIRLoc loc,
}
// `None` parse node but not an import; just nothing to point at.
return ConvertLocInFile(cursor_ir, Parse::NodeId::None, loc.token_only,
return ConvertLocInFile(cursor_ir, Parse::NodeId::None, loc.token_only_,
context_fn);
}
}