]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/resolve/rust-rib.h
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / resolve / rust-rib.h
CommitLineData
767698ff 1// Copyright (C) 2020-2024 Free Software Foundation, Inc.
8288dc0f
AC
2
3// This file is part of GCC.
4
5// GCC is free software; you can redistribute it and/or modify it under
6// the terms of the GNU General Public License as published by the Free
7// Software Foundation; either version 3, or (at your option) any later
8// version.
9
10// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
11// WARRANTY; without even the implied warranty of MERCHANTABILITY or
12// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13// for more details.
14
15// You should have received a copy of the GNU General Public License
16// along with GCC; see the file COPYING3. If not see
17// <http://www.gnu.org/licenses/>.
18
19#ifndef RUST_RIB_H
20#define RUST_RIB_H
21
22#include "rust-system.h"
23#include "rust-ast.h"
24#include "optional.h"
25#include "expected.h"
26
27namespace Rust {
28namespace Resolver2_0 {
29
f7d8356a
AC
30/**
31
32pub enum Namespace {
33 /// The type namespace includes `struct`s, `enum`s, `union`s, `trait`s, and
34`mod`s
35 /// (and, by extension, crates).
36 ///
37 /// Note that the type namespace includes other items; this is not an
38 /// exhaustive list.
39 TypeNS,
40 /// The value namespace includes `fn`s, `const`s, `static`s, and local
41variables (including function arguments). ValueNS,
42 /// The macro namespace includes `macro_rules!` macros, declarative `macro`s,
43 /// procedural macros, attribute macros, `derive` macros, and non-macro
44attributes
45 /// like `#[inline]` and `#[rustfmt::skip]`.
46 MacroNS,
47}
48
49*/
50
51// FIXME: There's no `labels` namespace, not sure if we need one or how to keep
52// one
53// FIXME: And where are things like loop labels kept?
54
8288dc0f
AC
55/**
56 * All namespaces that Rust's name resolution needs to handle
57 */
58// TODO: Move to `rust-forever-stack.h`?
59enum class Namespace
60{
61 Values,
62 Types,
63 Labels,
64 Macros,
65 // TODO: Which namespaces are we missing?
66};
67
68/**
69 * Error returned by `Rib::insert` when the key was already present in the Rib's
70 * map. The class contains the previously-inserted NodeId as well as the name of
71 * the node.
72 */
73struct DuplicateNameError
74{
75 // TODO: We might need multiple kinds of errors later down the line
76 DuplicateNameError (std::string name, NodeId existing);
77
78 std::string name;
79 NodeId existing;
80};
81
82/**
83 * A rib is a container of nodes, either declaration or usages, as well as the
84 * identifier each node uses. They are used to delimit lexical scopes, and have
85 * an impact on name resolution - they restrict certain name accesses and serve
86 * as boundaries between scopes.
87
88 * For example, if we are resolving the following *variable* use:
89 *
90 * ```rust
91 * fn outer() {
92 * let a = 15; // decl
93 * fn inner() -> i32 {
94 * a // use
95 * }
96 * }
97 * ```
98 *
99 * The `Function` rib we will have pushed will restrict the access to `outer`'s
100 * `a` declaration: Variable uses cannot cross function boundaries. On the other
101 * hand, if we were resolving a type usage, this would be perfectly allowed.
102 */
103class Rib
104{
105public:
106 enum class Kind
107 {
108 Normal,
109 Module,
110 Function,
111 ConstantItem, // -> this variant has a boolean
112 TraitOrImpl,
113 /* Any item other than a Module, Function, Constant, Trait or Impl block */
114 Item,
115 Closure,
116 MacroDefinition,
117 /* Ban the use of forward-declared generic parameters in defaults */
118 ForwardTypeParamBan,
119 /* Const generic, as in the following example: fn foo<T, const X: T>() {} */
120 ConstParamType,
5a0e099e 121 } kind;
8288dc0f
AC
122
123 Rib (Kind kind);
124 Rib (Kind kind, std::string identifier, NodeId id);
125 Rib (Kind kind, std::unordered_map<std::string, NodeId> values);
126
127 // TODO: What's the correctbehavior if the key already exists? What if a decl
128 // and use are in the same rib? Is that possible? Okay based on RibKind?
129
130 /**
131 * Insert a new node in the rib
132 *
133 * @param name The name associated with the AST node
134 * @param id Its NodeId
5a0e099e 135 * @param can_shadow If the newly inserted value can shadow an existing one
8288dc0f
AC
136 *
137 * @return `DuplicateNameError` if the node is already present in the rib. The
138 * `DuplicateNameError` class contains the NodeId of the existing
139 * node. Returns the new NodeId on success.
140 */
5a0e099e
AC
141 tl::expected<NodeId, DuplicateNameError> insert (std::string name, NodeId id,
142 bool can_shadow = false);
8288dc0f
AC
143
144 /**
145 * Access an inserted NodeId.
146 *
147 * @return tl::nullopt if the key does not exist, the NodeId otherwise
148 */
149 tl::optional<NodeId> get (const std::string &name);
150
151 /* View all the values stored in the rib */
152 const std::unordered_map<std::string, NodeId> &get_values () const;
153
154private:
8288dc0f
AC
155 std::unordered_map<std::string, NodeId> values;
156};
157
158} // namespace Resolver2_0
159} // namespace Rust
160
161#endif // !RUST_RIB_H