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 crate::checker::infer::InferCtx;
20
21impl InferCtx<'_, '_> {
22 pub fn infer_expression(&mut self, expression: Expression, expected_ty: &Type) -> Expression {
23 let parent_is_subexpression = self.scopes.set_in_subexpression(true);
26
27 let result = self.infer_expression_inner(expression, expected_ty, parent_is_subexpression);
28
29 self.scopes.set_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 spread,
87 type_args,
88 span,
89 ..
90 } => {
91 let is_panic = matches!(&*expression, Expression::Identifier { value, .. } if value == "panic");
92 let result = self.infer_function_call(
93 expression,
94 call_args,
95 spread,
96 type_args,
97 span,
98 expected_ty,
99 );
100 if parent_is_subexpression && is_panic {
101 self.sink
102 .push(diagnostics::infer::never_call_in_expression(span));
103 }
104 result
105 }
106
107 Expression::If {
108 condition,
109 consequence,
110 alternative,
111 span,
112 ..
113 } => self.infer_if(condition, consequence, alternative, span, expected_ty),
114
115 Expression::IfLet { .. } => {
116 unreachable!("IfLet should be desugared to Match before type inference")
117 }
118
119 Expression::Match {
120 subject,
121 arms,
122 origin,
123 span,
124 ..
125 } => self.infer_match(subject, arms, origin, span, expected_ty),
126
127 Expression::Tuple { elements, span, .. } => {
128 self.infer_tuple(elements, span, expected_ty)
129 }
130
131 Expression::StructCall {
132 name,
133 field_assignments,
134 spread,
135 span,
136 ..
137 } => self.infer_struct_call(name, field_assignments, spread, span, expected_ty),
138
139 Expression::DotAccess {
140 expression,
141 member,
142 span,
143 ..
144 } => self.infer_dot_access_or_qualified_path(expression, member, span, expected_ty),
145
146 Expression::Enum { .. } => expression,
147
148 Expression::Struct { .. } => self.infer_struct_definition(expression),
149
150 Expression::TypeAlias { .. } => self.infer_type_alias_definition(expression),
151
152 Expression::VariableDeclaration { .. } => expression,
153
154 Expression::ImplBlock {
155 annotation,
156 ty: _,
157 methods,
158 receiver_name,
159 generics,
160 span,
161 } => self.infer_impl_block(annotation, methods, receiver_name, generics, span),
162
163 Expression::Interface { .. } => self.infer_interface(expression),
164
165 Expression::Assignment {
166 target,
167 value,
168 compound_operator,
169 span,
170 } => self.infer_assignment(target, value, compound_operator, span),
171
172 Expression::Return {
173 expression, span, ..
174 } => self.infer_return_statement(expression, span, parent_is_subexpression),
175
176 Expression::Propagate {
177 expression, span, ..
178 } => {
179 if parent_is_subexpression {
180 self.check_failure_propagation_in_subexpression(&expression, span);
181 }
182 self.infer_propagate(expression, span, expected_ty)
183 }
184
185 Expression::TryBlock {
186 items,
187 try_keyword_span,
188 span,
189 ..
190 } => self.infer_try_block(items, try_keyword_span, span, expected_ty),
191
192 Expression::RecoverBlock {
193 items,
194 recover_keyword_span,
195 span,
196 ..
197 } => self.infer_recover_block(items, recover_keyword_span, span, expected_ty),
198
199 Expression::Binary {
200 operator,
201 left,
202 right,
203 span,
204 ..
205 } => self.infer_binary(operator, left, right, expected_ty, span),
206
207 Expression::Paren {
208 expression, span, ..
209 } => self.infer_paren(expression, span, expected_ty, parent_is_subexpression),
210
211 Expression::Unary {
212 operator,
213 expression,
214 span,
215 ..
216 } => self.infer_unary(operator, expression, expected_ty, span),
217
218 Expression::Const {
219 doc,
220 annotation,
221 ty: _,
222 expression,
223 span,
224 identifier,
225 identifier_span,
226 visibility,
227 } => self.infer_const_binding(
228 doc,
229 annotation,
230 expression,
231 identifier,
232 identifier_span,
233 visibility,
234 span,
235 ),
236
237 Expression::Loop { body, span, .. } => self.infer_loop(body, span, expected_ty),
238
239 Expression::While {
240 condition,
241 body,
242 span,
243 ..
244 } => self.infer_while(condition, body, span, expected_ty),
245
246 Expression::WhileLet {
247 pattern,
248 scrutinee,
249 body,
250 span,
251 ..
252 } => self.infer_while_let(pattern, scrutinee, body, span, expected_ty),
253
254 Expression::For {
255 binding,
256 iterable,
257 body,
258 span,
259 ..
260 } => self.infer_for(*binding, iterable, body, span, expected_ty),
261
262 Expression::Reference {
263 expression, span, ..
264 } => self.infer_reference(expression, span, expected_ty),
265
266 Expression::IndexedAccess {
267 expression,
268 index,
269 span,
270 from_colon_syntax,
271 ..
272 } => {
273 if from_colon_syntax {
274 self.infer_colon_subscript(expression, index, span)
275 } else {
276 self.infer_indexed_access(expression, index, span, expected_ty)
277 }
278 }
279
280 Expression::Task {
281 expression, span, ..
282 } => {
283 if parent_is_subexpression && !self.scopes.is_value_context() {
286 self.sink
287 .push(diagnostics::infer::control_flow_in_expression("task", span));
288 }
289 self.infer_task(expression, span, expected_ty)
290 }
291
292 Expression::Defer {
293 expression, span, ..
294 } => {
295 if parent_is_subexpression && !self.scopes.is_value_context() {
296 self.sink
297 .push(diagnostics::infer::control_flow_in_expression(
298 "defer", span,
299 ));
300 }
301 self.infer_defer(expression, span, expected_ty)
302 }
303
304 Expression::Select { arms, span, .. } => self.infer_select(arms, span, expected_ty),
305
306 Expression::ModuleImport {
307 name,
308 name_span,
309 alias,
310 span,
311 } => Expression::ModuleImport {
312 name,
313 name_span,
314 alias,
315 span,
316 },
317
318 Expression::Range {
319 start,
320 end,
321 inclusive,
322 span,
323 ..
324 } => self.infer_range(start, end, inclusive, span, expected_ty),
325
326 Expression::Cast {
327 expression,
328 target_type,
329 span,
330 ..
331 } => self.infer_cast(expression, target_type, span, expected_ty),
332
333 Expression::Break { value, span } => {
334 self.infer_break(value, span, parent_is_subexpression)
335 }
336 Expression::Continue { span } => self.infer_continue(span, parent_is_subexpression),
337 Expression::RawGo { text } => Expression::RawGo { text },
338 Expression::NoOp => Expression::NoOp,
339 }
340 }
341
342 pub(super) fn with_value_context<F, R>(&mut self, f: F) -> R
343 where
344 F: FnOnce(&mut Self) -> R,
345 {
346 let prev_ctx = self.scopes.set_value_context();
347 let result = f(self);
348 self.scopes.restore_use_context(prev_ctx);
349 result
350 }
351}