Line data Source code
1 : // Copyright (C) 2020-2026 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-stmt.h"
20 : #include "rust-hir-type-check-type.h"
21 : #include "rust-hir-type-check-expr.h"
22 : #include "rust-hir-type-check-implitem.h"
23 : #include "rust-hir-type-check-item.h"
24 : #include "rust-hir-type-check-pattern.h"
25 : #include "rust-type-util.h"
26 :
27 : namespace Rust {
28 : namespace Resolver {
29 :
30 : TyTy::BaseType *
31 24190 : TypeCheckStmt::Resolve (HIR::Stmt &stmt)
32 : {
33 24190 : TypeCheckStmt resolver;
34 24190 : stmt.accept_vis (resolver);
35 24190 : return resolver.infered;
36 24190 : }
37 :
38 : void
39 10826 : TypeCheckStmt::visit (HIR::ExprStmt &stmt)
40 : {
41 10826 : infered = TypeCheckExpr::Resolve (stmt.get_expr ());
42 10826 : }
43 :
44 : void
45 46 : TypeCheckStmt::visit (HIR::EmptyStmt &stmt)
46 : {
47 46 : infered = TyTy::TupleType::get_unit_type ();
48 46 : }
49 :
50 : void
51 16 : TypeCheckStmt::visit (HIR::ExternBlock &extern_block)
52 : {
53 32 : for (auto &item : extern_block.get_extern_items ())
54 : {
55 16 : TypeCheckTopLevelExternItem::Resolve (*item, extern_block);
56 : }
57 16 : }
58 :
59 : void
60 56 : TypeCheckStmt::visit (HIR::ConstantItem &constant)
61 : {
62 56 : TyTy::BaseType *type = TypeCheckType::Resolve (constant.get_type ());
63 56 : if (!constant.has_expr ())
64 : {
65 1 : infered = type;
66 1 : return;
67 : }
68 :
69 55 : TyTy::BaseType *expr_type = TypeCheckExpr::Resolve (constant.get_expr ());
70 :
71 110 : infered = coercion_site (
72 55 : constant.get_mappings ().get_hirid (),
73 55 : TyTy::TyWithLocation (type, constant.get_type ().get_locus ()),
74 55 : TyTy::TyWithLocation (expr_type, constant.get_expr ().get_locus ()),
75 : constant.get_locus ());
76 55 : context->insert_type (constant.get_mappings (), infered);
77 : }
78 :
79 : void
80 12890 : TypeCheckStmt::visit (HIR::LetStmt &stmt)
81 : {
82 12890 : infered = TyTy::TupleType::get_unit_type ();
83 :
84 12890 : auto &stmt_pattern = stmt.get_pattern ();
85 :
86 : // Resolve the type annotation before the init expression so the normal
87 : // coercion site below can check the init against the declared type.
88 12890 : TyTy::BaseType *specified_ty = nullptr;
89 12890 : location_t specified_ty_locus = UNKNOWN_LOCATION;
90 12890 : if (stmt.has_type ())
91 : {
92 2155 : specified_ty = TypeCheckType::Resolve (stmt.get_type ());
93 2155 : specified_ty_locus = stmt.get_type ().get_locus ();
94 : }
95 :
96 12890 : TyTy::BaseType *init_expr_ty = nullptr;
97 12890 : location_t init_expr_locus = UNKNOWN_LOCATION;
98 12890 : if (stmt.has_init_expr ())
99 : {
100 11751 : init_expr_locus = stmt.get_init_expr ().get_locus ();
101 :
102 : // Try blocks have a block whose tail expression is:
103 : //
104 : // Try::from_ok(tail)
105 : //
106 : // We can forward the annotated let type to block initializers so
107 : // the block can pass it to its tail expression
108 11751 : bool push_expected = specified_ty != nullptr
109 11751 : && stmt.get_init_expr ().get_expression_type ()
110 11768 : == HIR::Expr::ExprType::Block;
111 17 : if (push_expected)
112 17 : context->push_expected_type (specified_ty);
113 11751 : init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ());
114 11751 : if (push_expected)
115 17 : context->pop_expected_type ();
116 11751 : if (init_expr_ty->get_kind () == TyTy::TypeKind::ERROR)
117 : return;
118 :
119 11716 : init_expr_ty->append_reference (
120 11716 : stmt_pattern.get_mappings ().get_hirid ());
121 : }
122 :
123 : // let x:i32 = 123;
124 12855 : if (specified_ty != nullptr && init_expr_ty != nullptr)
125 : {
126 3772 : coercion_site (stmt.get_mappings ().get_hirid (),
127 1886 : TyTy::TyWithLocation (specified_ty, specified_ty_locus),
128 1886 : TyTy::TyWithLocation (init_expr_ty, init_expr_locus),
129 : stmt.get_locus ());
130 1886 : TypeCheckPattern::Resolve (stmt_pattern, specified_ty);
131 : }
132 : else
133 : {
134 : // let x:i32;
135 10969 : if (specified_ty != nullptr)
136 : {
137 264 : TypeCheckPattern::Resolve (stmt_pattern, specified_ty);
138 : }
139 : // let x = 123;
140 10705 : else if (init_expr_ty != nullptr)
141 : {
142 9830 : TypeCheckPattern::Resolve (stmt_pattern, init_expr_ty);
143 : }
144 : // let x;
145 : else
146 : {
147 875 : auto infer
148 875 : = new TyTy::InferType (stmt_pattern.get_mappings ().get_hirid (),
149 : TyTy::InferType::InferTypeKind::GENERAL,
150 : TyTy::InferType::TypeHint::Default (),
151 875 : stmt.get_locus ());
152 875 : TypeCheckPattern::Resolve (stmt_pattern, infer);
153 : }
154 : }
155 : }
156 :
157 : void
158 0 : TypeCheckStmt::visit (HIR::TypePath &path)
159 : {
160 0 : infered = TypeCheckType::Resolve (path);
161 0 : }
162 : void
163 0 : TypeCheckStmt::visit (HIR::QualifiedPathInType &path)
164 : {
165 0 : infered = TypeCheckType::Resolve (path);
166 0 : }
167 :
168 : void
169 138 : TypeCheckStmt::visit (HIR::TupleStruct &struct_decl)
170 : {
171 138 : infered = TypeCheckItem::Resolve (struct_decl);
172 138 : }
173 :
174 : void
175 10 : TypeCheckStmt::visit (HIR::Enum &enum_decl)
176 : {
177 10 : infered = TypeCheckItem::Resolve (enum_decl);
178 10 : }
179 :
180 : void
181 129 : TypeCheckStmt::visit (HIR::StructStruct &struct_decl)
182 : {
183 129 : infered = TypeCheckItem::Resolve (struct_decl);
184 129 : }
185 :
186 : void
187 0 : TypeCheckStmt::visit (HIR::Union &union_decl)
188 : {
189 0 : infered = TypeCheckItem::Resolve (union_decl);
190 0 : }
191 :
192 : void
193 64 : TypeCheckStmt::visit (HIR::Function &function)
194 : {
195 64 : infered = TypeCheckItem::Resolve (function);
196 64 : }
197 :
198 : void
199 0 : TypeCheckStmt::visit (HIR::Module &module)
200 : {
201 0 : infered = TypeCheckItem::Resolve (module);
202 0 : }
203 :
204 : void
205 0 : TypeCheckStmt::visit (HIR::TypeAlias &type_alias)
206 : {
207 0 : infered = TypeCheckItem::Resolve (type_alias);
208 0 : }
209 :
210 : void
211 1 : TypeCheckStmt::visit (HIR::StaticItem &static_item)
212 : {
213 1 : infered = TypeCheckItem::Resolve (static_item);
214 1 : }
215 :
216 : void
217 6 : TypeCheckStmt::visit (HIR::Trait &trait)
218 : {
219 6 : infered = TypeCheckItem::Resolve (trait);
220 6 : }
221 :
222 : void
223 8 : TypeCheckStmt::visit (HIR::ImplBlock &impl)
224 : {
225 8 : infered = TypeCheckItem::Resolve (impl);
226 8 : }
227 :
228 : } // namespace Resolver
229 : } // namespace Rust
|