Branch data Line data Source code
1 : : // Copyright (C) 2020-2025 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 "rust-hir-expr.h"
20 : : #include "rust-hir-type-check-type.h"
21 : : #include "rust-hir-type-check-expr.h"
22 : : #include "rust-hir-type-check-enumitem.h"
23 : : #include "rust-type-util.h"
24 : : #include "rust-immutable-name-resolution-context.h"
25 : :
26 : : // for flag_name_resolution_2_0
27 : : #include "options.h"
28 : :
29 : : namespace Rust {
30 : : namespace Resolver {
31 : :
32 : : TyTy::VariantDef *
33 : 842 : TypeCheckEnumItem::Resolve (HIR::EnumItem &item, int64_t last_discriminant)
34 : : {
35 : 842 : TypeCheckEnumItem resolver (last_discriminant);
36 : 842 : switch (item.get_enum_item_kind ())
37 : : {
38 : 384 : case HIR::EnumItem::EnumItemKind::Named:
39 : 384 : resolver.visit (static_cast<HIR::EnumItem &> (item));
40 : 384 : break;
41 : :
42 : 370 : case HIR::EnumItem::EnumItemKind::Tuple:
43 : 370 : resolver.visit (static_cast<HIR::EnumItemTuple &> (item));
44 : 370 : break;
45 : :
46 : 68 : case HIR::EnumItem::EnumItemKind::Struct:
47 : 68 : resolver.visit (static_cast<HIR::EnumItemStruct &> (item));
48 : 68 : break;
49 : :
50 : 20 : case HIR::EnumItem::EnumItemKind::Discriminant:
51 : 20 : resolver.visit (static_cast<HIR::EnumItemDiscriminant &> (item));
52 : 20 : break;
53 : : }
54 : 842 : return resolver.variant;
55 : 842 : }
56 : :
57 : 842 : TypeCheckEnumItem::TypeCheckEnumItem (int64_t last_discriminant)
58 : 842 : : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant)
59 : 842 : {}
60 : :
61 : : void
62 : 384 : TypeCheckEnumItem::visit (HIR::EnumItem &item)
63 : : {
64 : 384 : if (last_discriminant == INT64_MAX)
65 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
66 : :
67 : 768 : Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (),
68 : 384 : item.get_mappings ().get_nodeid (),
69 : 384 : mappings.get_next_hir_id (
70 : 384 : item.get_mappings ().get_crate_num ()),
71 : 384 : item.get_mappings ().get_local_defid ());
72 : 384 : auto discim_expr = std::make_unique<HIR::LiteralExpr> (
73 : 768 : HIR::LiteralExpr (mapping, std::to_string (last_discriminant),
74 : : HIR::Literal::LitType::INT,
75 : 1152 : PrimitiveCoreType::CORETYPE_I64, item.get_locus (), {}));
76 : :
77 : 384 : TyTy::BaseType *isize = nullptr;
78 : 384 : bool ok = context->lookup_builtin ("isize", &isize);
79 : 384 : rust_assert (ok);
80 : 384 : context->insert_type (mapping, isize);
81 : :
82 : 384 : tl::optional<CanonicalPath> canonical_path;
83 : :
84 : 384 : if (flag_name_resolution_2_0)
85 : : {
86 : 68 : auto &nr_ctx
87 : 68 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
88 : :
89 : 68 : canonical_path
90 : 136 : = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
91 : : }
92 : : else
93 : : {
94 : 316 : canonical_path
95 : 316 : = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
96 : : }
97 : :
98 : 384 : rust_assert (canonical_path.has_value ());
99 : :
100 : 384 : RustIdent ident{*canonical_path, item.get_locus ()};
101 : 384 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
102 : 384 : item.get_mappings ().get_defid (),
103 : 384 : item.get_identifier ().as_string (), ident,
104 : 1536 : std::move (discim_expr));
105 : 768 : }
106 : :
107 : : void
108 : 20 : TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item)
109 : : {
110 : 20 : if (last_discriminant == INT64_MAX)
111 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
112 : :
113 : 20 : auto &discriminant = item.get_discriminant_expression ();
114 : 20 : auto capacity_type = TypeCheckExpr::Resolve (discriminant);
115 : 20 : if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
116 : 0 : return;
117 : :
118 : 20 : TyTy::ISizeType *expected_ty
119 : 20 : = new TyTy::ISizeType (discriminant.get_mappings ().get_hirid ());
120 : 20 : context->insert_type (discriminant.get_mappings (), expected_ty);
121 : :
122 : 20 : unify_site (item.get_mappings ().get_hirid (),
123 : 20 : TyTy::TyWithLocation (expected_ty),
124 : 20 : TyTy::TyWithLocation (capacity_type), item.get_locus ());
125 : :
126 : 20 : tl::optional<CanonicalPath> canonical_path;
127 : :
128 : 20 : if (flag_name_resolution_2_0)
129 : : {
130 : 11 : auto &nr_ctx
131 : 11 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
132 : :
133 : 11 : canonical_path
134 : 22 : = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
135 : : }
136 : : else
137 : : {
138 : 9 : canonical_path
139 : 9 : = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
140 : : }
141 : :
142 : 20 : rust_assert (canonical_path.has_value ());
143 : :
144 : 20 : RustIdent ident{*canonical_path, item.get_locus ()};
145 : 20 : variant
146 : 20 : = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
147 : 20 : item.get_mappings ().get_defid (),
148 : 20 : item.get_identifier ().as_string (), ident,
149 : 80 : item.get_discriminant_expression ().clone_expr ());
150 : 40 : }
151 : :
152 : : void
153 : 370 : TypeCheckEnumItem::visit (HIR::EnumItemTuple &item)
154 : : {
155 : 370 : if (last_discriminant == INT64_MAX)
156 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
157 : :
158 : 370 : std::vector<TyTy::StructFieldType *> fields;
159 : 370 : size_t idx = 0;
160 : 727 : for (auto &field : item.get_tuple_fields ())
161 : : {
162 : 357 : TyTy::BaseType *field_type
163 : 357 : = TypeCheckType::Resolve (field.get_field_type ());
164 : 357 : TyTy::StructFieldType *ty_field
165 : 714 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
166 : 357 : std::to_string (idx), field_type,
167 : 357 : field.get_locus ());
168 : 357 : fields.push_back (ty_field);
169 : 357 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
170 : 357 : idx++;
171 : : }
172 : :
173 : 740 : Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (),
174 : 370 : item.get_mappings ().get_nodeid (),
175 : 370 : mappings.get_next_hir_id (
176 : 370 : item.get_mappings ().get_crate_num ()),
177 : 370 : item.get_mappings ().get_local_defid ());
178 : 370 : auto discim_expr = std::make_unique<HIR::LiteralExpr> (
179 : 740 : HIR::LiteralExpr (mapping, std::to_string (last_discriminant),
180 : : HIR::Literal::LitType::INT,
181 : 1110 : PrimitiveCoreType::CORETYPE_I64, item.get_locus (), {}));
182 : :
183 : 370 : TyTy::BaseType *isize = nullptr;
184 : 370 : bool ok = context->lookup_builtin ("isize", &isize);
185 : 370 : rust_assert (ok);
186 : 370 : context->insert_type (mapping, isize);
187 : :
188 : 370 : tl::optional<CanonicalPath> canonical_path;
189 : :
190 : 370 : if (flag_name_resolution_2_0)
191 : : {
192 : 81 : auto &nr_ctx
193 : 81 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
194 : :
195 : 81 : canonical_path
196 : 162 : = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
197 : : }
198 : : else
199 : : {
200 : 289 : canonical_path
201 : 289 : = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
202 : : }
203 : :
204 : 370 : rust_assert (canonical_path.has_value ());
205 : :
206 : 370 : RustIdent ident{*canonical_path, item.get_locus ()};
207 : 370 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
208 : 370 : item.get_mappings ().get_defid (),
209 : 370 : item.get_identifier ().as_string (), ident,
210 : : TyTy::VariantDef::VariantType::TUPLE,
211 : 1480 : std::move (discim_expr), fields);
212 : 740 : }
213 : :
214 : : void
215 : 68 : TypeCheckEnumItem::visit (HIR::EnumItemStruct &item)
216 : : {
217 : 68 : if (last_discriminant == INT64_MAX)
218 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
219 : :
220 : 68 : std::vector<TyTy::StructFieldType *> fields;
221 : 187 : for (auto &field : item.get_struct_fields ())
222 : : {
223 : 119 : TyTy::BaseType *field_type
224 : 119 : = TypeCheckType::Resolve (field.get_field_type ());
225 : 119 : TyTy::StructFieldType *ty_field
226 : 119 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
227 : 119 : field.get_field_name ().as_string (),
228 : 238 : field_type, field.get_locus ());
229 : 119 : fields.push_back (ty_field);
230 : 119 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
231 : : }
232 : :
233 : 136 : Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (),
234 : 68 : item.get_mappings ().get_nodeid (),
235 : 68 : mappings.get_next_hir_id (
236 : 68 : item.get_mappings ().get_crate_num ()),
237 : 68 : item.get_mappings ().get_local_defid ());
238 : 68 : auto discrim_expr = std::make_unique<HIR::LiteralExpr> (
239 : 136 : HIR::LiteralExpr (mapping, std::to_string (last_discriminant),
240 : : HIR::Literal::LitType::INT,
241 : 204 : PrimitiveCoreType::CORETYPE_I64, item.get_locus (), {}));
242 : :
243 : 68 : TyTy::BaseType *isize = nullptr;
244 : 68 : bool ok = context->lookup_builtin ("isize", &isize);
245 : 68 : rust_assert (ok);
246 : 68 : context->insert_type (mapping, isize);
247 : :
248 : 68 : tl::optional<CanonicalPath> canonical_path;
249 : :
250 : 68 : if (flag_name_resolution_2_0)
251 : : {
252 : 14 : auto &nr_ctx
253 : 14 : = Resolver2_0::ImmutableNameResolutionContext::get ().resolver ();
254 : :
255 : 14 : canonical_path
256 : 28 : = nr_ctx.types.to_canonical_path (item.get_mappings ().get_nodeid ());
257 : : }
258 : : else
259 : : {
260 : 54 : canonical_path
261 : 54 : = mappings.lookup_canonical_path (item.get_mappings ().get_nodeid ());
262 : : }
263 : :
264 : 68 : rust_assert (canonical_path.has_value ());
265 : :
266 : 68 : RustIdent ident{*canonical_path, item.get_locus ()};
267 : 68 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
268 : 68 : item.get_mappings ().get_defid (),
269 : 68 : item.get_identifier ().as_string (), ident,
270 : : TyTy::VariantDef::VariantType::STRUCT,
271 : 272 : std::move (discrim_expr), fields);
272 : 136 : }
273 : :
274 : : } // namespace Resolver
275 : : } // namespace Rust
|