]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/rust/typecheck/rust-typecheck-context.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / rust / typecheck / rust-typecheck-context.cc
CommitLineData
a945c346 1// Copyright (C) 2020-2024 Free Software Foundation, Inc.
06688fe4
PH
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 "rust-hir-type-check.h"
20
21namespace Rust {
22namespace Resolver {
23
24TypeCheckContext *
25TypeCheckContext::get ()
26{
27 static TypeCheckContext *instance;
28 if (instance == nullptr)
29 instance = new TypeCheckContext ();
30
31 return instance;
32}
33
34TypeCheckContext::TypeCheckContext () {}
35
36TypeCheckContext::~TypeCheckContext () {}
37
38bool
39TypeCheckContext::lookup_builtin (NodeId id, TyTy::BaseType **type)
40{
41 auto ref_it = node_id_refs.find (id);
42 if (ref_it == node_id_refs.end ())
43 return false;
44
45 auto it = resolved.find (ref_it->second);
46 if (it == resolved.end ())
47 return false;
48
49 *type = it->second;
50 return true;
51}
52
53bool
54TypeCheckContext::lookup_builtin (std::string name, TyTy::BaseType **type)
55{
56 for (auto &builtin : builtins)
57 {
58 if (name.compare (builtin->as_string ()) == 0)
59 {
60 *type = builtin.get ();
61 return true;
62 }
63 }
64 return false;
65}
66
67void
68TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::BaseType *type)
69{
70 node_id_refs[ref] = id;
71 resolved[id] = type;
72 builtins.push_back (std::unique_ptr<TyTy::BaseType> (type));
73}
74
75void
76TypeCheckContext::insert_type (const Analysis::NodeMapping &mappings,
77 TyTy::BaseType *type)
78{
79 rust_assert (type != nullptr);
80 NodeId ref = mappings.get_nodeid ();
81 HirId id = mappings.get_hirid ();
82 node_id_refs[ref] = id;
83 resolved[id] = type;
84}
85
86void
87TypeCheckContext::insert_implicit_type (TyTy::BaseType *type)
88{
89 rust_assert (type != nullptr);
90 resolved[type->get_ref ()] = type;
91}
92
93void
94TypeCheckContext::insert_implicit_type (HirId id, TyTy::BaseType *type)
95{
96 rust_assert (type != nullptr);
97 resolved[id] = type;
98}
99
100bool
101TypeCheckContext::lookup_type (HirId id, TyTy::BaseType **type) const
102{
103 auto it = resolved.find (id);
104 if (it == resolved.end ())
105 return false;
106
107 *type = it->second;
108 return true;
109}
110
111void
112TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id)
113{
114 rust_assert (node_id_refs.find (ref) == node_id_refs.end ());
115 node_id_refs[ref] = id;
116}
117
118bool
119TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id)
120{
121 auto it = node_id_refs.find (ref);
122 if (it == node_id_refs.end ())
123 return false;
124
125 *id = it->second;
126 return true;
127}
128
129TyTy::BaseType *
130TypeCheckContext::peek_return_type ()
131{
7ad24d80 132 rust_assert (!return_type_stack.empty ());
06688fe4
PH
133 return return_type_stack.back ().second;
134}
135
136void
137TypeCheckContext::push_return_type (TypeCheckContextItem item,
138 TyTy::BaseType *return_type)
139{
140 return_type_stack.push_back ({std::move (item), return_type});
141}
142
143void
144TypeCheckContext::pop_return_type ()
145{
245ce6f2 146 rust_assert (!return_type_stack.empty ());
06688fe4
PH
147 return_type_stack.pop_back ();
148}
149
150TypeCheckContextItem &
151TypeCheckContext::peek_context ()
152{
245ce6f2 153 rust_assert (!return_type_stack.empty ());
06688fe4
PH
154 return return_type_stack.back ().first;
155}
156
615ee14c
PH
157void
158TypeCheckContext::iterate (std::function<bool (HirId, TyTy::BaseType *)> cb)
159{
160 for (auto it = resolved.begin (); it != resolved.end (); it++)
161 {
162 if (!cb (it->first, it->second))
163 return;
164 }
165}
166
167bool
168TypeCheckContext::have_loop_context () const
169{
170 return !loop_type_stack.empty ();
171}
172
173void
174TypeCheckContext::push_new_loop_context (HirId id, Location locus)
175{
176 TyTy::BaseType *infer_var
177 = new TyTy::InferType (id, TyTy::InferType::InferTypeKind::GENERAL, locus);
178 loop_type_stack.push_back (infer_var);
179}
180
181void
182TypeCheckContext::push_new_while_loop_context (HirId id)
183{
184 TyTy::BaseType *infer_var = new TyTy::ErrorType (id);
185 loop_type_stack.push_back (infer_var);
186}
187
188TyTy::BaseType *
189TypeCheckContext::peek_loop_context ()
190{
191 return loop_type_stack.back ();
192}
193
194TyTy::BaseType *
195TypeCheckContext::pop_loop_context ()
196{
197 auto back = peek_loop_context ();
198 loop_type_stack.pop_back ();
199 return back;
200}
201
202void
203TypeCheckContext::swap_head_loop_context (TyTy::BaseType *val)
204{
205 loop_type_stack.pop_back ();
206 loop_type_stack.push_back (val);
207}
208
209void
210TypeCheckContext::insert_trait_reference (DefId id, TraitReference &&ref)
211{
212 rust_assert (trait_context.find (id) == trait_context.end ());
213 trait_context.emplace (id, std::move (ref));
214}
215
216bool
217TypeCheckContext::lookup_trait_reference (DefId id, TraitReference **ref)
218{
219 auto it = trait_context.find (id);
220 if (it == trait_context.end ())
221 return false;
222
223 *ref = &it->second;
224 return true;
225}
226
227void
228TypeCheckContext::insert_receiver (HirId id, TyTy::BaseType *t)
229{
230 receiver_context[id] = t;
231}
232
233bool
234TypeCheckContext::lookup_receiver (HirId id, TyTy::BaseType **ref)
235{
236 auto it = receiver_context.find (id);
237 if (it == receiver_context.end ())
238 return false;
239
240 *ref = it->second;
241 return true;
242}
243
244void
245TypeCheckContext::insert_associated_trait_impl (
246 HirId id, AssociatedImplTrait &&associated)
247{
248 rust_assert (associated_impl_traits.find (id)
249 == associated_impl_traits.end ());
250 associated_impl_traits.emplace (id, std::move (associated));
251}
252
253bool
254TypeCheckContext::lookup_associated_trait_impl (
255 HirId id, AssociatedImplTrait **associated)
256{
257 auto it = associated_impl_traits.find (id);
258 if (it == associated_impl_traits.end ())
259 return false;
260
261 *associated = &it->second;
262 return true;
263}
264
265void
266TypeCheckContext::insert_associated_type_mapping (HirId id, HirId mapping)
267{
268 associated_type_mappings[id] = mapping;
269}
270
271void
272TypeCheckContext::clear_associated_type_mapping (HirId id)
273{
274 auto it = associated_type_mappings.find (id);
275 if (it != associated_type_mappings.end ())
276 associated_type_mappings.erase (it);
277}
278
279// lookup any associated type mappings, the out parameter of mapping is
280// allowed to be nullptr which allows this interface to do a simple does exist
281// check
282bool
283TypeCheckContext::lookup_associated_type_mapping (HirId id, HirId *mapping)
284{
285 auto it = associated_type_mappings.find (id);
286 if (it == associated_type_mappings.end ())
287 return false;
288
289 if (mapping != nullptr)
290 *mapping = it->second;
291
292 return true;
293}
294
295void
296TypeCheckContext::insert_associated_impl_mapping (
297 HirId trait_id, const TyTy::BaseType *impl_type, HirId impl_id)
298{
299 auto it = associated_traits_to_impls.find (trait_id);
300 if (it == associated_traits_to_impls.end ())
301 {
302 associated_traits_to_impls[trait_id] = {};
303 }
304
305 associated_traits_to_impls[trait_id].push_back ({impl_type, impl_id});
306}
307
308bool
309TypeCheckContext::lookup_associated_impl_mapping_for_self (
310 HirId trait_id, const TyTy::BaseType *self, HirId *mapping)
311{
312 auto it = associated_traits_to_impls.find (trait_id);
313 if (it == associated_traits_to_impls.end ())
314 return false;
315
316 for (auto &item : it->second)
317 {
318 if (item.first->can_eq (self, false))
319 {
320 *mapping = item.second;
321 return true;
322 }
323 }
324 return false;
325}
326
327void
328TypeCheckContext::insert_autoderef_mappings (
329 HirId id, std::vector<Adjustment> &&adjustments)
330{
331 rust_assert (autoderef_mappings.find (id) == autoderef_mappings.end ());
332 autoderef_mappings.emplace (id, std::move (adjustments));
333}
334
335bool
336TypeCheckContext::lookup_autoderef_mappings (
337 HirId id, std::vector<Adjustment> **adjustments)
338{
339 auto it = autoderef_mappings.find (id);
340 if (it == autoderef_mappings.end ())
341 return false;
342
343 *adjustments = &it->second;
344 return true;
345}
346
347void
348TypeCheckContext::insert_cast_autoderef_mappings (
349 HirId id, std::vector<Adjustment> &&adjustments)
350{
351 rust_assert (cast_autoderef_mappings.find (id)
352 == cast_autoderef_mappings.end ());
353 cast_autoderef_mappings.emplace (id, std::move (adjustments));
354}
355
356bool
357TypeCheckContext::lookup_cast_autoderef_mappings (
358 HirId id, std::vector<Adjustment> **adjustments)
359{
360 auto it = cast_autoderef_mappings.find (id);
361 if (it == cast_autoderef_mappings.end ())
362 return false;
363
364 *adjustments = &it->second;
365 return true;
366}
367
368void
369TypeCheckContext::insert_variant_definition (HirId id, HirId variant)
370{
371 auto it = variants.find (id);
372 rust_assert (it == variants.end ());
373
374 variants[id] = variant;
375}
376
377bool
378TypeCheckContext::lookup_variant_definition (HirId id, HirId *variant)
379{
380 auto it = variants.find (id);
381 if (it == variants.end ())
382 return false;
383
384 *variant = it->second;
385 return true;
386}
387
388void
389TypeCheckContext::insert_operator_overload (HirId id, TyTy::FnType *call_site)
390{
391 auto it = operator_overloads.find (id);
392 rust_assert (it == operator_overloads.end ());
393
394 operator_overloads[id] = call_site;
395}
396
397bool
398TypeCheckContext::lookup_operator_overload (HirId id, TyTy::FnType **call)
399{
400 auto it = operator_overloads.find (id);
401 if (it == operator_overloads.end ())
402 return false;
403
404 *call = it->second;
405 return true;
406}
407
408void
409TypeCheckContext::insert_unconstrained_check_marker (HirId id, bool status)
410{
411 unconstrained[id] = status;
412}
413
414bool
415TypeCheckContext::have_checked_for_unconstrained (HirId id, bool *result)
416{
417 auto it = unconstrained.find (id);
418 bool found = it != unconstrained.end ();
419 if (!found)
420 return false;
421
422 *result = it->second;
423 return true;
424}
425
426void
427TypeCheckContext::insert_resolved_predicate (HirId id,
428 TyTy::TypeBoundPredicate predicate)
429{
430 auto it = predicates.find (id);
431 rust_assert (it == predicates.end ());
432
433 predicates.insert ({id, predicate});
434}
435
436bool
437TypeCheckContext::lookup_predicate (HirId id, TyTy::TypeBoundPredicate *result)
438{
439 auto it = predicates.find (id);
440 bool found = it != predicates.end ();
441 if (!found)
442 return false;
443
444 *result = it->second;
445 return true;
446}
447
448void
449TypeCheckContext::insert_query (HirId id)
450{
451 querys_in_progress.insert (id);
452}
453
454void
455TypeCheckContext::query_completed (HirId id)
456{
457 querys_in_progress.erase (id);
458}
459
460bool
461TypeCheckContext::query_in_progress (HirId id) const
462{
463 return querys_in_progress.find (id) != querys_in_progress.end ();
464}
465
466void
467TypeCheckContext::insert_trait_query (DefId id)
468{
469 trait_queries_in_progress.insert (id);
470}
471
472void
473TypeCheckContext::trait_query_completed (DefId id)
474{
475 trait_queries_in_progress.erase (id);
476}
477
478bool
479TypeCheckContext::trait_query_in_progress (DefId id) const
480{
481 return trait_queries_in_progress.find (id)
482 != trait_queries_in_progress.end ();
483}
484
740a1997
PH
485// TypeCheckContextItem
486
615ee14c
PH
487TypeCheckContextItem::Item::Item (HIR::Function *item) : item (item) {}
488
489TypeCheckContextItem::Item::Item (HIR::ImplBlock *impl_block,
490 HIR::Function *item)
491 : impl_item ({impl_block, item})
492{}
493
494TypeCheckContextItem::Item::Item (HIR::TraitItemFunc *trait_item)
495 : trait_item (trait_item)
496{}
497
498TypeCheckContextItem::TypeCheckContextItem (HIR::Function *item)
499 : type (ItemType::ITEM), item (item)
500{}
501
502TypeCheckContextItem::TypeCheckContextItem (HIR::ImplBlock *impl_block,
503 HIR::Function *item)
504 : type (ItemType::IMPL_ITEM), item (impl_block, item)
505{}
506
507TypeCheckContextItem::TypeCheckContextItem (HIR::TraitItemFunc *trait_item)
508 : type (ItemType::TRAIT_ITEM), item (trait_item)
509{}
510
511HIR::Function *
512TypeCheckContextItem::get_item ()
513{
514 rust_assert (get_type () == ItemType::ITEM);
515 return item.item;
516}
517
518std::pair<HIR::ImplBlock *, HIR::Function *> &
519TypeCheckContextItem::get_impl_item ()
520{
521 rust_assert (get_type () == ItemType::IMPL_ITEM);
522 return item.impl_item;
523}
524
525HIR::TraitItemFunc *
526TypeCheckContextItem::get_trait_item ()
527{
528 rust_assert (get_type () == ItemType::TRAIT_ITEM);
529 return item.trait_item;
530}
531
532TypeCheckContextItem::ItemType
533TypeCheckContextItem::get_type () const
534{
535 return type;
536}
537
740a1997
PH
538TyTy::FnType *
539TypeCheckContextItem::get_context_type ()
540{
541 auto &context = *TypeCheckContext::get ();
542
543 HirId reference = UNKNOWN_HIRID;
544 switch (get_type ())
545 {
546 case ITEM:
547 reference = get_item ()->get_mappings ().get_hirid ();
548 break;
549
550 case IMPL_ITEM:
551 reference = get_impl_item ().second->get_mappings ().get_hirid ();
552 break;
553
554 case TRAIT_ITEM:
555 reference = get_trait_item ()->get_mappings ().get_hirid ();
556 break;
557 }
558
559 rust_assert (reference != UNKNOWN_HIRID);
560
561 TyTy::BaseType *lookup = nullptr;
562 bool ok = context.lookup_type (reference, &lookup);
563 rust_assert (ok);
564 rust_assert (lookup->get_kind () == TyTy::TypeKind::FNDEF);
565 return static_cast<TyTy::FnType *> (lookup);
566}
567
06688fe4
PH
568} // namespace Resolver
569} // namespace Rust