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