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 "rust-hir-type-check-type.h"
20 : : #include "rust-hir-type-check-expr.h"
21 : : #include "rust-hir-type-check-enumitem.h"
22 : : #include "rust-type-util.h"
23 : :
24 : : namespace Rust {
25 : : namespace Resolver {
26 : :
27 : : TyTy::VariantDef *
28 : 407 : TypeCheckEnumItem::Resolve (HIR::EnumItem *item, int64_t last_discriminant)
29 : : {
30 : 407 : TypeCheckEnumItem resolver (last_discriminant);
31 : 407 : switch (item->get_enum_item_kind ())
32 : : {
33 : 193 : case HIR::EnumItem::EnumItemKind::Named:
34 : 193 : resolver.visit (static_cast<HIR::EnumItem &> (*item));
35 : 193 : break;
36 : :
37 : 172 : case HIR::EnumItem::EnumItemKind::Tuple:
38 : 172 : resolver.visit (static_cast<HIR::EnumItemTuple &> (*item));
39 : 172 : break;
40 : :
41 : 41 : case HIR::EnumItem::EnumItemKind::Struct:
42 : 41 : resolver.visit (static_cast<HIR::EnumItemStruct &> (*item));
43 : 41 : break;
44 : :
45 : 1 : case HIR::EnumItem::EnumItemKind::Discriminant:
46 : 1 : resolver.visit (static_cast<HIR::EnumItemDiscriminant &> (*item));
47 : 1 : break;
48 : : }
49 : 407 : return resolver.variant;
50 : 407 : }
51 : :
52 : 407 : TypeCheckEnumItem::TypeCheckEnumItem (int64_t last_discriminant)
53 : 407 : : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant)
54 : 407 : {}
55 : :
56 : : void
57 : 193 : TypeCheckEnumItem::visit (HIR::EnumItem &item)
58 : : {
59 : 193 : if (last_discriminant == INT64_MAX)
60 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
61 : :
62 : 386 : Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (),
63 : 193 : item.get_mappings ().get_nodeid (),
64 : 193 : mappings->get_next_hir_id (
65 : 193 : item.get_mappings ().get_crate_num ()),
66 : 193 : item.get_mappings ().get_local_defid ());
67 : 193 : HIR::LiteralExpr *discim_expr
68 : 193 : = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant),
69 : : HIR::Literal::LitType::INT,
70 : 193 : PrimitiveCoreType::CORETYPE_I64, item.get_locus (),
71 : 386 : {});
72 : :
73 : 193 : TyTy::BaseType *isize = nullptr;
74 : 193 : bool ok = context->lookup_builtin ("isize", &isize);
75 : 193 : rust_assert (ok);
76 : 193 : context->insert_type (mapping, isize);
77 : :
78 : 193 : const CanonicalPath *canonical_path = nullptr;
79 : 193 : ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (),
80 : : &canonical_path);
81 : 0 : rust_assert (ok);
82 : :
83 : 193 : RustIdent ident{*canonical_path, item.get_locus ()};
84 : 193 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
85 : 193 : item.get_mappings ().get_defid (),
86 : 193 : item.get_identifier ().as_string (), ident,
87 : 386 : discim_expr);
88 : 193 : }
89 : :
90 : : void
91 : 1 : TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant &item)
92 : : {
93 : 1 : if (last_discriminant == INT64_MAX)
94 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
95 : :
96 : 1 : auto &discriminant = item.get_discriminant_expression ();
97 : 1 : auto capacity_type = TypeCheckExpr::Resolve (discriminant.get ());
98 : 1 : if (capacity_type->get_kind () == TyTy::TypeKind::ERROR)
99 : 0 : return;
100 : :
101 : 1 : TyTy::ISizeType *expected_ty
102 : 1 : = new TyTy::ISizeType (discriminant->get_mappings ().get_hirid ());
103 : 1 : context->insert_type (discriminant->get_mappings (), expected_ty);
104 : :
105 : 1 : unify_site (item.get_mappings ().get_hirid (),
106 : 1 : TyTy::TyWithLocation (expected_ty),
107 : 1 : TyTy::TyWithLocation (capacity_type), item.get_locus ());
108 : :
109 : 1 : const CanonicalPath *canonical_path = nullptr;
110 : 1 : bool ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (),
111 : : &canonical_path);
112 : 0 : rust_assert (ok);
113 : :
114 : 1 : RustIdent ident{*canonical_path, item.get_locus ()};
115 : 1 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
116 : 1 : item.get_mappings ().get_defid (),
117 : 1 : item.get_identifier ().as_string (), ident,
118 : 2 : item.get_discriminant_expression ().get ());
119 : 1 : }
120 : :
121 : : void
122 : 172 : TypeCheckEnumItem::visit (HIR::EnumItemTuple &item)
123 : : {
124 : 172 : if (last_discriminant == INT64_MAX)
125 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
126 : :
127 : 172 : std::vector<TyTy::StructFieldType *> fields;
128 : 172 : size_t idx = 0;
129 : 344 : for (auto &field : item.get_tuple_fields ())
130 : : {
131 : 172 : TyTy::BaseType *field_type
132 : 172 : = TypeCheckType::Resolve (field.get_field_type ().get ());
133 : 172 : TyTy::StructFieldType *ty_field
134 : 344 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
135 : 172 : std::to_string (idx), field_type,
136 : 172 : field.get_locus ());
137 : 172 : fields.push_back (ty_field);
138 : 172 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
139 : 172 : idx++;
140 : : }
141 : :
142 : 344 : Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (),
143 : 172 : item.get_mappings ().get_nodeid (),
144 : 172 : mappings->get_next_hir_id (
145 : 172 : item.get_mappings ().get_crate_num ()),
146 : 172 : item.get_mappings ().get_local_defid ());
147 : 172 : HIR::LiteralExpr *discim_expr
148 : 172 : = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant),
149 : : HIR::Literal::LitType::INT,
150 : 172 : PrimitiveCoreType::CORETYPE_I64, item.get_locus (),
151 : 344 : {});
152 : :
153 : 172 : TyTy::BaseType *isize = nullptr;
154 : 172 : bool ok = context->lookup_builtin ("isize", &isize);
155 : 172 : rust_assert (ok);
156 : 172 : context->insert_type (mapping, isize);
157 : :
158 : 172 : const CanonicalPath *canonical_path = nullptr;
159 : 172 : ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (),
160 : : &canonical_path);
161 : 0 : rust_assert (ok);
162 : :
163 : 172 : RustIdent ident{*canonical_path, item.get_locus ()};
164 : 172 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
165 : 172 : item.get_mappings ().get_defid (),
166 : 172 : item.get_identifier ().as_string (), ident,
167 : : TyTy::VariantDef::VariantType::TUPLE,
168 : 344 : discim_expr, fields);
169 : 172 : }
170 : :
171 : : void
172 : 41 : TypeCheckEnumItem::visit (HIR::EnumItemStruct &item)
173 : : {
174 : 41 : if (last_discriminant == INT64_MAX)
175 : 0 : rust_error_at (item.get_locus (), "discriminant too big");
176 : :
177 : 41 : std::vector<TyTy::StructFieldType *> fields;
178 : 122 : for (auto &field : item.get_struct_fields ())
179 : : {
180 : 81 : TyTy::BaseType *field_type
181 : 81 : = TypeCheckType::Resolve (field.get_field_type ().get ());
182 : 81 : TyTy::StructFieldType *ty_field
183 : 81 : = new TyTy::StructFieldType (field.get_mappings ().get_hirid (),
184 : 81 : field.get_field_name ().as_string (),
185 : 81 : field_type, field.get_locus ());
186 : 81 : fields.push_back (ty_field);
187 : 81 : context->insert_type (field.get_mappings (), ty_field->get_field_type ());
188 : : }
189 : :
190 : 82 : Analysis::NodeMapping mapping (item.get_mappings ().get_crate_num (),
191 : 41 : item.get_mappings ().get_nodeid (),
192 : 41 : mappings->get_next_hir_id (
193 : 41 : item.get_mappings ().get_crate_num ()),
194 : 41 : item.get_mappings ().get_local_defid ());
195 : 41 : HIR::LiteralExpr *discrim_expr
196 : 41 : = new HIR::LiteralExpr (mapping, std::to_string (last_discriminant),
197 : : HIR::Literal::LitType::INT,
198 : 41 : PrimitiveCoreType::CORETYPE_I64, item.get_locus (),
199 : 82 : {});
200 : :
201 : 41 : TyTy::BaseType *isize = nullptr;
202 : 41 : bool ok = context->lookup_builtin ("isize", &isize);
203 : 41 : rust_assert (ok);
204 : 41 : context->insert_type (mapping, isize);
205 : :
206 : 41 : const CanonicalPath *canonical_path = nullptr;
207 : 41 : ok = mappings->lookup_canonical_path (item.get_mappings ().get_nodeid (),
208 : : &canonical_path);
209 : 0 : rust_assert (ok);
210 : :
211 : 41 : RustIdent ident{*canonical_path, item.get_locus ()};
212 : 41 : variant = new TyTy::VariantDef (item.get_mappings ().get_hirid (),
213 : 41 : item.get_mappings ().get_defid (),
214 : 41 : item.get_identifier ().as_string (), ident,
215 : : TyTy::VariantDef::VariantType::STRUCT,
216 : 82 : discrim_expr, fields);
217 : 41 : }
218 : :
219 : : } // namespace Resolver
220 : : } // namespace Rust
|