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