Branch data Line data Source code
1 : : // Copyright (C) 2020-2024 Free Software Foundation, Inc.
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 : : #include "optional.h"
20 : : #include "rust-ast-full.h"
21 : : #include "rust-hir-map.h"
22 : : #include "rust-late-name-resolver-2.0.h"
23 : : #include "rust-default-resolver.h"
24 : : #include "rust-name-resolution-context.h"
25 : : #include "rust-path.h"
26 : : #include "rust-tyty.h"
27 : : #include "rust-hir-type-check.h"
28 : :
29 : : namespace Rust {
30 : : namespace Resolver2_0 {
31 : :
32 : 27 : Late::Late (NameResolutionContext &ctx) : DefaultResolver (ctx) {}
33 : :
34 : : static NodeId
35 : 513 : next_node_id ()
36 : : {
37 : 513 : return Analysis::Mappings::get ()->get_next_node_id ();
38 : : };
39 : :
40 : : static HirId
41 : 513 : next_hir_id ()
42 : : {
43 : 513 : return Analysis::Mappings::get ()->get_next_hir_id ();
44 : : };
45 : :
46 : : void
47 : 27 : Late::setup_builtin_types ()
48 : : {
49 : : // access the global type context to setup the TyTys
50 : 27 : auto &ty_ctx = *Resolver::TypeCheckContext::get ();
51 : :
52 : : // Late builtin type struct helper
53 : 27 : struct LType
54 : : {
55 : : std::string name;
56 : : NodeId node_id;
57 : : NodeId hir_id;
58 : : TyTy::BaseType *type;
59 : :
60 : 486 : explicit LType (std::string name, TyTy::BaseType *type)
61 : 486 : : name (name), node_id (next_node_id ()), hir_id (type->get_ref ()),
62 : 486 : type (type)
63 : 486 : {}
64 : : };
65 : :
66 : 27 : static const LType builtins[] = {
67 : 54 : {LType ("bool", new TyTy::BoolType (next_hir_id ()))},
68 : 54 : {LType ("u8", new TyTy::UintType (next_hir_id (), TyTy::UintType::U8))},
69 : 54 : {LType ("u16", new TyTy::UintType (next_hir_id (), TyTy::UintType::U16))},
70 : 54 : {LType ("u32", new TyTy::UintType (next_hir_id (), TyTy::UintType::U32))},
71 : 54 : {LType ("u64", new TyTy::UintType (next_hir_id (), TyTy::UintType::U64))},
72 : 54 : {LType ("u128", new TyTy::UintType (next_hir_id (), TyTy::UintType::U128))},
73 : 54 : {LType ("i8", new TyTy::IntType (next_hir_id (), TyTy::IntType::I8))},
74 : 54 : {LType ("i16", new TyTy::IntType (next_hir_id (), TyTy::IntType::I16))},
75 : 54 : {LType ("i32", new TyTy::IntType (next_hir_id (), TyTy::IntType::I32))},
76 : 54 : {LType ("i64", new TyTy::IntType (next_hir_id (), TyTy::IntType::I64))},
77 : 54 : {LType ("i128", new TyTy::IntType (next_hir_id (), TyTy::IntType::I128))},
78 : 54 : {LType ("f32", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F32))},
79 : 54 : {LType ("f64", new TyTy::FloatType (next_hir_id (), TyTy::FloatType::F64))},
80 : 54 : {LType ("usize", new TyTy::USizeType (next_hir_id ()))},
81 : 54 : {LType ("isize", new TyTy::ISizeType (next_hir_id ()))},
82 : 54 : {LType ("char", new TyTy::CharType (next_hir_id ()))},
83 : 54 : {LType ("str", new TyTy::StrType (next_hir_id ()))},
84 : 54 : {LType ("!", new TyTy::NeverType (next_hir_id ()))},
85 : :
86 : : // the unit type `()` does not play a part in name-resolution - so we only
87 : : // insert it in the type context...
88 : 540 : };
89 : :
90 : 513 : for (const auto &builtin : builtins)
91 : : {
92 : : // we should be able to use `insert_at_root` or `insert` here, since we're
93 : : // at the root :) hopefully!
94 : 486 : auto ok = ctx.types.insert (builtin.name, builtin.node_id);
95 : 486 : rust_assert (ok);
96 : :
97 : 486 : ctx.mappings.insert_node_to_hir (builtin.node_id, builtin.hir_id);
98 : 486 : ty_ctx.insert_builtin (builtin.hir_id, builtin.node_id, builtin.type);
99 : 486 : }
100 : :
101 : : // ...here!
102 : 27 : auto *unit_type = TyTy::TupleType::get_unit_type (next_hir_id ());
103 : 27 : ty_ctx.insert_builtin (unit_type->get_ref (), next_node_id (), unit_type);
104 : 27 : }
105 : :
106 : : void
107 : 27 : Late::go (AST::Crate &crate)
108 : : {
109 : 27 : setup_builtin_types ();
110 : :
111 : 110 : for (auto &item : crate.items)
112 : 83 : item->accept_vis (*this);
113 : 27 : }
114 : :
115 : : void
116 : 0 : Late::new_label (Identifier name, NodeId id)
117 : : {
118 : : // labels can always shadow, so `insert` should never fail. if it does, we're
119 : : // in big trouble!
120 : 0 : auto ok = ctx.labels.insert (name, id);
121 : :
122 : 0 : rust_assert (ok);
123 : 0 : }
124 : :
125 : : void
126 : 20 : Late::visit (AST::LetStmt &let)
127 : : {
128 : : // so we don't need that method
129 : 20 : DefaultResolver::visit (let);
130 : :
131 : : // how do we deal with the fact that `let a = blipbloup` should look for a
132 : : // label and cannot go through function ribs, but `let a = blipbloup()` can?
133 : :
134 : : // how do we insert ribs here, and only pop them when we exit the current
135 : : // function?
136 : : // keep a list of ribs to pop when a scope exits? so only for blocks?
137 : : // how do we pop ribs that need to be popped not in order?
138 : : // I think it's not important if we have shadowing, correct?
139 : :
140 : : // if we have shadowing, it should work! we'll see
141 : :
142 : : // ctx.insert(Identifier name, NodeId id, Namespace ns)
143 : : // ctx.scoped (Rib::Kind::Normal /* FIXME: Is that valid? */,
144 : : // Namespace::Labels,
145 : : // let.get_node_id (), [] () {});
146 : 20 : }
147 : :
148 : : void
149 : 28 : Late::visit (AST::IdentifierPattern &identifier)
150 : : {
151 : : // do we insert in labels or in values
152 : : // but values does not allow shadowing... since functions cannot shadow
153 : : // do we insert functions in labels as well?
154 : 28 : auto ok
155 : 28 : = ctx.values.insert (identifier.get_ident (), identifier.get_node_id ());
156 : :
157 : 28 : rust_assert (ok);
158 : 28 : }
159 : :
160 : : void
161 : 17 : Late::visit (AST::IdentifierExpr &expr)
162 : : {
163 : : // TODO: same thing as visit(PathInExpression) here?
164 : :
165 : 17 : tl::optional<Rib::Definition> resolved = tl::nullopt;
166 : 17 : auto label = ctx.labels.get (expr.get_ident ());
167 : 17 : auto value = ctx.values.get (expr.get_ident ());
168 : :
169 : 17 : if (label)
170 : : {
171 : 0 : resolved = label;
172 : : }
173 : 17 : else if (value)
174 : : {
175 : 17 : resolved = value;
176 : : }
177 : : else
178 : : {
179 : 0 : rust_error_at (expr.get_locus (),
180 : : "could not resolve identifier expression: %qs",
181 : 0 : expr.get_ident ().as_string ().c_str ());
182 : 0 : return;
183 : : }
184 : :
185 : 17 : ctx.map_usage (Usage (expr.get_node_id ()),
186 : 17 : Definition (resolved->get_node_id ()));
187 : :
188 : : // in the old resolver, resolutions are kept in the resolver, not the mappings
189 : : // :/ how do we deal with that?
190 : : // ctx.mappings.insert_resolved_name(expr, resolved);
191 : :
192 : : // For empty types, do we perform a lookup in ctx.types or should the
193 : : // toplevel instead insert a name in ctx.values? (like it currently does)
194 : 34 : }
195 : :
196 : : void
197 : 27 : Late::visit (AST::PathInExpression &expr)
198 : : {
199 : : // TODO: How do we have a nice error with `can't capture dynamic environment
200 : : // in a function item` error here?
201 : : // do we emit it in `get<Namespace::Labels>`?
202 : :
203 : 27 : auto value = ctx.values.resolve_path (expr.get_segments ());
204 : 27 : if (!value.has_value ())
205 : 0 : rust_unreachable (); // Should have been resolved earlier
206 : :
207 : 27 : if (value->is_ambiguous ())
208 : : {
209 : 1 : rust_error_at (expr.get_locus (), ErrorCode::E0659, "%qs is ambiguous",
210 : 1 : expr.as_string ().c_str ());
211 : 1 : return;
212 : : }
213 : 26 : ctx.map_usage (Usage (expr.get_node_id ()),
214 : 26 : Definition (value->get_node_id ()));
215 : 27 : }
216 : :
217 : : void
218 : 44 : Late::visit (AST::TypePath &type)
219 : : {
220 : : // should we add type path resolution in `ForeverStack` directly? Since it's
221 : : // quite more complicated.
222 : : // maybe we can overload `resolve_path<Namespace::Types>` to only do
223 : : // typepath-like path resolution? that sounds good
224 : :
225 : 44 : auto resolved = ctx.types.get (type.get_segments ().back ()->as_string ());
226 : :
227 : 44 : ctx.map_usage (Usage (type.get_node_id ()),
228 : 44 : Definition (resolved->get_node_id ()));
229 : 44 : }
230 : :
231 : : void
232 : 0 : Late::visit (AST::StructExprStructBase &s)
233 : : {
234 : 0 : auto resolved = ctx.types.get (s.get_struct_name ().as_string ());
235 : :
236 : 0 : ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
237 : 0 : Definition (resolved->get_node_id ()));
238 : 0 : DefaultResolver::visit (s);
239 : 0 : }
240 : :
241 : : void
242 : 2 : Late::visit (AST::StructExprStructFields &s)
243 : : {
244 : 2 : auto resolved = ctx.types.get (s.get_struct_name ().as_string ());
245 : :
246 : 2 : ctx.map_usage (Usage (s.get_struct_name ().get_node_id ()),
247 : 2 : Definition (resolved->get_node_id ()));
248 : :
249 : 2 : DefaultResolver::visit (s);
250 : 2 : }
251 : :
252 : : } // namespace Resolver2_0
253 : : } // namespace Rust
|