1pub mod bindings;
2pub mod control_flow;
3pub mod definitions;
4pub mod dot_access;
5pub mod functions;
6pub mod impl_blocks;
7pub mod indexed_access;
8pub mod literals;
9pub mod operators;
10pub mod patterns;
11pub mod primitives;
12pub mod propagate;
13pub mod select;
14pub mod struct_call;
15
16use syntax::ast::Expression;
17use syntax::types::Type;
18
19use super::super::Checker;
20
21impl Checker<'_, '_> {
22 pub fn infer_expression(&mut self, expression: Expression, expected_ty: &Type) -> Expression {
23 let parent_is_subexpression = std::mem::replace(&mut self.inference.in_subexpression, true);
26
27 let result = self.infer_expression_inner(expression, expected_ty, parent_is_subexpression);
28
29 self.inference.in_subexpression = parent_is_subexpression;
30 result
31 }
32
33 fn infer_expression_inner(
34 &mut self,
35 expression: Expression,
36 expected_ty: &Type,
37 parent_is_subexpression: bool,
38 ) -> Expression {
39 match expression {
40 Expression::Literal { literal, span, .. } => {
41 self.infer_literal(literal, expected_ty, span)
42 }
43
44 Expression::Block { items, span, .. } => self.infer_block(items, span, expected_ty),
45
46 Expression::Function { .. } => self.infer_function(expression, expected_ty),
47
48 Expression::Lambda {
49 params,
50 return_annotation,
51 body,
52 span,
53 ..
54 } => self.infer_lambda(params, return_annotation, body, span, expected_ty),
55
56 Expression::Unit { span, .. } => self.infer_unit(span, expected_ty),
57
58 Expression::Identifier {
59 ref value, span, ..
60 } => self.infer_identifier(value.clone(), span, expected_ty),
61
62 Expression::Let {
63 binding,
64 value,
65 mutable,
66 mut_span,
67 else_block,
68 else_span,
69 span,
70 typed_pattern: _,
71 ty: _,
72 } => self.infer_let_binding(
73 *binding,
74 value,
75 mutable,
76 mut_span,
77 else_block,
78 else_span,
79 span,
80 expected_ty,
81 ),
82
83 Expression::Call {
84 expression,
85 args: call_args,
86 type_args,
87 span,
88 ..
89 } => {
90 let is_panic = matches!(&*expression, Expression::Identifier { value, .. } if value == "panic");
91 let result =
92 self.infer_function_call(expression, call_args, type_args, span, expected_ty);
93 if parent_is_subexpression && is_panic {
94 self.sink
95 .push(diagnostics::infer::never_call_in_expression(span));
96 }
97 result
98 }
99
100 Expression::If {
101 condition,
102 consequence,
103 alternative,
104 span,
105 ..
106 } => self.infer_if(condition, consequence, alternative, span, expected_ty),
107
108 Expression::IfLet { .. } => {
109 unreachable!("IfLet should be desugared to Match before type inference")
110 }
111
112 Expression::Match {
113 subject,
114 arms,
115 origin,
116 span,
117 ..
118 } => self.infer_match(subject, arms, origin, span, expected_ty),
119
120 Expression::Tuple { elements, span, .. } => {
121 self.infer_tuple(elements, span, expected_ty)
122 }
123
124 Expression::StructCall {
125 name,
126 field_assignments,
127 spread,
128 span,
129 ..
130 } => self.infer_struct_call(name, field_assignments, spread, span, expected_ty),
131
132 Expression::DotAccess {
133 expression,
134 member,
135 span,
136 ..
137 } => self.infer_dot_access_or_qualified_path(expression, member, span, expected_ty),
138
139 Expression::Enum { .. } => self.infer_enum_definition(expression),
140
141 Expression::ValueEnum { .. } => self.infer_value_enum_definition(expression),
142
143 Expression::Struct { .. } => self.infer_struct_definition(expression),
144
145 Expression::TypeAlias { .. } => self.infer_type_alias_definition(expression),
146
147 Expression::VariableDeclaration { .. } => expression,
148
149 Expression::ImplBlock {
150 annotation,
151 ty: _,
152 methods,
153 receiver_name,
154 generics,
155 span,
156 } => self.infer_impl_block(annotation, methods, receiver_name, generics, span),
157
158 Expression::Interface { .. } => self.infer_interface(expression),
159
160 Expression::Assignment {
161 target,
162 value,
163 compound_operator,
164 span,
165 } => self.infer_assignment(target, value, compound_operator, span),
166
167 Expression::Return {
168 expression, span, ..
169 } => self.infer_return_statement(expression, span, parent_is_subexpression),
170
171 Expression::Propagate {
172 expression, span, ..
173 } => {
174 if parent_is_subexpression {
175 self.check_failure_propagation_in_subexpression(&expression, span);
176 }
177 self.infer_propagate(expression, span, expected_ty)
178 }
179
180 Expression::TryBlock {
181 items,
182 try_keyword_span,
183 span,
184 ..
185 } => self.infer_try_block(items, try_keyword_span, span, expected_ty),
186
187 Expression::RecoverBlock {
188 items,
189 recover_keyword_span,
190 span,
191 ..
192 } => self.infer_recover_block(items, recover_keyword_span, span, expected_ty),
193
194 Expression::Binary {
195 operator,
196 left,
197 right,
198 span,
199 ..
200 } => self.infer_binary(operator, left, right, expected_ty, span),
201
202 Expression::Paren {
203 expression, span, ..
204 } => self.infer_paren(expression, span, expected_ty, parent_is_subexpression),
205
206 Expression::Unary {
207 operator,
208 expression,
209 span,
210 ..
211 } => self.infer_unary(operator, expression, expected_ty, span),
212
213 Expression::Const {
214 doc,
215 annotation,
216 ty: _,
217 expression,
218 span,
219 identifier,
220 identifier_span,
221 visibility,
222 } => self.infer_const_binding(
223 doc,
224 annotation,
225 expression,
226 identifier,
227 identifier_span,
228 visibility,
229 span,
230 ),
231
232 Expression::Loop { body, span, .. } => self.infer_loop(body, span, expected_ty),
233
234 Expression::While {
235 condition,
236 body,
237 span,
238 ..
239 } => self.infer_while(condition, body, span, expected_ty),
240
241 Expression::WhileLet {
242 pattern,
243 scrutinee,
244 body,
245 span,
246 ..
247 } => self.infer_while_let(pattern, scrutinee, body, span, expected_ty),
248
249 Expression::For {
250 binding,
251 iterable,
252 body,
253 span,
254 ..
255 } => self.infer_for(*binding, iterable, body, span, expected_ty),
256
257 Expression::Reference {
258 expression, span, ..
259 } => self.infer_reference(expression, span, expected_ty),
260
261 Expression::IndexedAccess {
262 expression,
263 index,
264 span,
265 ..
266 } => self.infer_indexed_access(expression, index, span, expected_ty),
267
268 Expression::Task {
269 expression, span, ..
270 } => {
271 if parent_is_subexpression && !self.scopes.is_value_context() {
274 self.sink
275 .push(diagnostics::infer::control_flow_in_expression("task", span));
276 }
277 self.infer_task(expression, span, expected_ty)
278 }
279
280 Expression::Defer {
281 expression, span, ..
282 } => {
283 if parent_is_subexpression && !self.scopes.is_value_context() {
284 self.sink
285 .push(diagnostics::infer::control_flow_in_expression(
286 "defer", span,
287 ));
288 }
289 self.infer_defer(expression, span, expected_ty)
290 }
291
292 Expression::Select { arms, span, .. } => self.infer_select(arms, span, expected_ty),
293
294 Expression::ModuleImport {
295 name,
296 name_span,
297 alias,
298 span,
299 } => Expression::ModuleImport {
300 name,
301 name_span,
302 alias,
303 span,
304 },
305
306 Expression::Range {
307 start,
308 end,
309 inclusive,
310 span,
311 ..
312 } => self.infer_range(start, end, inclusive, span, expected_ty),
313
314 Expression::Cast {
315 expression,
316 target_type,
317 span,
318 ..
319 } => self.infer_cast(expression, target_type, span, expected_ty),
320
321 Expression::Break { value, span } => {
322 self.infer_break(value, span, parent_is_subexpression)
323 }
324 Expression::Continue { span } => self.infer_continue(span, parent_is_subexpression),
325 Expression::RawGo { text } => Expression::RawGo { text },
326 Expression::NoOp => Expression::NoOp,
327 }
328 }
329
330 pub(super) fn with_value_context<F, R>(&mut self, f: F) -> R
331 where
332 F: FnOnce(&mut Self) -> R,
333 {
334 let prev_ctx = self.scopes.set_value_context();
335 let result = f(self);
336 self.scopes.restore_use_context(prev_ctx);
337 result
338 }
339}