Add diagnostics for extend impl misuse. (#3721)

To make the implementation simpler, make `PopWithParseNodeIf` return
`pair<NodeId, optional<value>>` rather than `optional<pair<NodeId,
value>>`. While wrapping the whole result in `optional` seems more
principled, it's significantly harder to work with.
This commit is contained in:
Richard Smith
2024-02-23 22:07:29 +00:00
committed by GitHub
parent 8ad0c70f9f
commit 8e8eeb3243
8 changed files with 185 additions and 94 deletions
+25 -22
View File
@@ -9,6 +9,7 @@
#include "common/vlog.h"
#include "llvm/ADT/SmallVector.h"
#include "toolchain/parse/node_ids.h"
#include "toolchain/parse/node_kind.h"
#include "toolchain/parse/tree.h"
#include "toolchain/parse/typed_nodes.h"
@@ -247,28 +248,6 @@ class NodeStack {
return std::make_pair(parse_node, id);
}
// Pops the top of the stack and returns the parse_node and the ID if it is
// of the specified kind.
template <const Parse::NodeKind& RequiredParseKind>
auto PopWithParseNodeIf()
-> std::optional<decltype(PopWithParseNode<RequiredParseKind>())> {
if (!PeekIs<RequiredParseKind>()) {
return std::nullopt;
}
return PopWithParseNode<RequiredParseKind>();
}
// Pops the top of the stack and returns the parse_node and the ID if it is
// of the specified category
template <Parse::NodeCategory RequiredParseCategory>
auto PopWithParseNodeIf()
-> std::optional<decltype(PopWithParseNode<RequiredParseCategory>())> {
if (!PeekIs<RequiredParseCategory>()) {
return std::nullopt;
}
return PopWithParseNode<RequiredParseCategory>();
}
// Pops an expression from the top of the stack and returns the ID.
// Expressions always map Parse::NodeCategory::Expr nodes to SemIR::InstId.
auto PopExpr() -> SemIR::InstId { return PopExprWithParseNode().second; }
@@ -320,6 +299,30 @@ class NodeStack {
return std::nullopt;
}
// Pops the top of the stack and returns the parse_node and the ID if it is
// of the specified kind.
template <const Parse::NodeKind& RequiredParseKind>
auto PopWithParseNodeIf()
-> std::pair<Parse::NodeIdForKind<RequiredParseKind>,
decltype(PopIf<RequiredParseKind>())> {
if (!PeekIs<RequiredParseKind>()) {
return {Parse::NodeId::Invalid, std::nullopt};
}
return PopWithParseNode<RequiredParseKind>();
}
// Pops the top of the stack and returns the parse_node and the ID if it is
// of the specified category.
template <Parse::NodeCategory RequiredParseCategory>
auto PopWithParseNodeIf()
-> std::pair<Parse::NodeIdInCategory<RequiredParseCategory>,
decltype(PopIf<RequiredParseCategory>())> {
if (!PeekIs<RequiredParseCategory>()) {
return {Parse::NodeId::Invalid, std::nullopt};
}
return PopWithParseNode<RequiredParseCategory>();
}
// Peeks at the parse node of the top of the node stack.
auto PeekParseNode() const -> Parse::NodeId {
return stack_.back().parse_node;