1 // Copyright (C) 2020-2024 Free Software Foundation, Inc.
3 // This file is part of GCC.
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
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
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/>.
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"
28 TypeCheckEnumItem::Resolve (HIR::EnumItem
*item
, int64_t last_discriminant
)
30 TypeCheckEnumItem
resolver (last_discriminant
);
31 switch (item
->get_enum_item_kind ())
33 case HIR::EnumItem::EnumItemKind::Named
:
34 resolver
.visit (static_cast<HIR::EnumItem
&> (*item
));
37 case HIR::EnumItem::EnumItemKind::Tuple
:
38 resolver
.visit (static_cast<HIR::EnumItemTuple
&> (*item
));
41 case HIR::EnumItem::EnumItemKind::Struct
:
42 resolver
.visit (static_cast<HIR::EnumItemStruct
&> (*item
));
45 case HIR::EnumItem::EnumItemKind::Discriminant
:
46 resolver
.visit (static_cast<HIR::EnumItemDiscriminant
&> (*item
));
49 return resolver
.variant
;
52 TypeCheckEnumItem::TypeCheckEnumItem (int64_t last_discriminant
)
53 : TypeCheckBase (), variant (nullptr), last_discriminant (last_discriminant
)
57 TypeCheckEnumItem::visit (HIR::EnumItem
&item
)
59 if (last_discriminant
== INT64_MAX
)
60 rust_error_at (item
.get_locus (), "discriminant too big");
62 Analysis::NodeMapping
mapping (item
.get_mappings ().get_crate_num (),
63 item
.get_mappings ().get_nodeid (),
64 mappings
->get_next_hir_id (
65 item
.get_mappings ().get_crate_num ()),
66 item
.get_mappings ().get_local_defid ());
67 HIR::LiteralExpr
*discim_expr
68 = new HIR::LiteralExpr (mapping
, std::to_string (last_discriminant
),
69 HIR::Literal::LitType::INT
,
70 PrimitiveCoreType::CORETYPE_I64
, item
.get_locus (),
73 TyTy::BaseType
*isize
= nullptr;
74 bool ok
= context
->lookup_builtin ("isize", &isize
);
76 context
->insert_type (mapping
, isize
);
78 const CanonicalPath
*canonical_path
= nullptr;
79 ok
= mappings
->lookup_canonical_path (item
.get_mappings ().get_nodeid (),
83 RustIdent ident
{*canonical_path
, item
.get_locus ()};
84 variant
= new TyTy::VariantDef (item
.get_mappings ().get_hirid (),
85 item
.get_mappings ().get_defid (),
86 item
.get_identifier ().as_string (), ident
,
91 TypeCheckEnumItem::visit (HIR::EnumItemDiscriminant
&item
)
93 if (last_discriminant
== INT64_MAX
)
94 rust_error_at (item
.get_locus (), "discriminant too big");
96 auto &discriminant
= item
.get_discriminant_expression ();
97 auto capacity_type
= TypeCheckExpr::Resolve (discriminant
.get ());
98 if (capacity_type
->get_kind () == TyTy::TypeKind::ERROR
)
101 TyTy::ISizeType
*expected_ty
102 = new TyTy::ISizeType (discriminant
->get_mappings ().get_hirid ());
103 context
->insert_type (discriminant
->get_mappings (), expected_ty
);
105 unify_site (item
.get_mappings ().get_hirid (),
106 TyTy::TyWithLocation (expected_ty
),
107 TyTy::TyWithLocation (capacity_type
), item
.get_locus ());
109 const CanonicalPath
*canonical_path
= nullptr;
110 bool ok
= mappings
->lookup_canonical_path (item
.get_mappings ().get_nodeid (),
114 RustIdent ident
{*canonical_path
, item
.get_locus ()};
115 variant
= new TyTy::VariantDef (item
.get_mappings ().get_hirid (),
116 item
.get_mappings ().get_defid (),
117 item
.get_identifier ().as_string (), ident
,
118 item
.get_discriminant_expression ().get ());
122 TypeCheckEnumItem::visit (HIR::EnumItemTuple
&item
)
124 if (last_discriminant
== INT64_MAX
)
125 rust_error_at (item
.get_locus (), "discriminant too big");
127 std::vector
<TyTy::StructFieldType
*> fields
;
129 for (auto &field
: item
.get_tuple_fields ())
131 TyTy::BaseType
*field_type
132 = TypeCheckType::Resolve (field
.get_field_type ().get ());
133 TyTy::StructFieldType
*ty_field
134 = new TyTy::StructFieldType (field
.get_mappings ().get_hirid (),
135 std::to_string (idx
), field_type
,
137 fields
.push_back (ty_field
);
138 context
->insert_type (field
.get_mappings (), ty_field
->get_field_type ());
142 Analysis::NodeMapping
mapping (item
.get_mappings ().get_crate_num (),
143 item
.get_mappings ().get_nodeid (),
144 mappings
->get_next_hir_id (
145 item
.get_mappings ().get_crate_num ()),
146 item
.get_mappings ().get_local_defid ());
147 HIR::LiteralExpr
*discim_expr
148 = new HIR::LiteralExpr (mapping
, std::to_string (last_discriminant
),
149 HIR::Literal::LitType::INT
,
150 PrimitiveCoreType::CORETYPE_I64
, item
.get_locus (),
153 TyTy::BaseType
*isize
= nullptr;
154 bool ok
= context
->lookup_builtin ("isize", &isize
);
156 context
->insert_type (mapping
, isize
);
158 const CanonicalPath
*canonical_path
= nullptr;
159 ok
= mappings
->lookup_canonical_path (item
.get_mappings ().get_nodeid (),
163 RustIdent ident
{*canonical_path
, item
.get_locus ()};
164 variant
= new TyTy::VariantDef (item
.get_mappings ().get_hirid (),
165 item
.get_mappings ().get_defid (),
166 item
.get_identifier ().as_string (), ident
,
167 TyTy::VariantDef::VariantType::TUPLE
,
168 discim_expr
, fields
);
172 TypeCheckEnumItem::visit (HIR::EnumItemStruct
&item
)
174 if (last_discriminant
== INT64_MAX
)
175 rust_error_at (item
.get_locus (), "discriminant too big");
177 std::vector
<TyTy::StructFieldType
*> fields
;
178 for (auto &field
: item
.get_struct_fields ())
180 TyTy::BaseType
*field_type
181 = TypeCheckType::Resolve (field
.get_field_type ().get ());
182 TyTy::StructFieldType
*ty_field
183 = new TyTy::StructFieldType (field
.get_mappings ().get_hirid (),
184 field
.get_field_name ().as_string (),
185 field_type
, field
.get_locus ());
186 fields
.push_back (ty_field
);
187 context
->insert_type (field
.get_mappings (), ty_field
->get_field_type ());
190 Analysis::NodeMapping
mapping (item
.get_mappings ().get_crate_num (),
191 item
.get_mappings ().get_nodeid (),
192 mappings
->get_next_hir_id (
193 item
.get_mappings ().get_crate_num ()),
194 item
.get_mappings ().get_local_defid ());
195 HIR::LiteralExpr
*discrim_expr
196 = new HIR::LiteralExpr (mapping
, std::to_string (last_discriminant
),
197 HIR::Literal::LitType::INT
,
198 PrimitiveCoreType::CORETYPE_I64
, item
.get_locus (),
201 TyTy::BaseType
*isize
= nullptr;
202 bool ok
= context
->lookup_builtin ("isize", &isize
);
204 context
->insert_type (mapping
, isize
);
206 const CanonicalPath
*canonical_path
= nullptr;
207 ok
= mappings
->lookup_canonical_path (item
.get_mappings ().get_nodeid (),
211 RustIdent ident
{*canonical_path
, item
.get_locus ()};
212 variant
= new TyTy::VariantDef (item
.get_mappings ().get_hirid (),
213 item
.get_mappings ().get_defid (),
214 item
.get_identifier ().as_string (), ident
,
215 TyTy::VariantDef::VariantType::STRUCT
,
216 discrim_expr
, fields
);
219 } // namespace Resolver