1use crate::{CompilerState, VariableSymbol, VariableType, type_checking::scope_state::ScopeState};
18
19use super::*;
20
21use leo_ast::*;
22use leo_errors::{TypeCheckerError, TypeCheckerWarning};
23use leo_span::{Span, Symbol};
24
25use indexmap::{IndexMap, IndexSet};
26use std::ops::Deref;
27
28pub struct TypeCheckingVisitor<'a> {
29 pub state: &'a mut CompilerState,
30 pub scope_state: ScopeState,
32 pub async_function_input_types: IndexMap<Location, Vec<Type>>,
34 pub async_function_callers: IndexMap<Location, IndexSet<Location>>,
36 pub used_structs: IndexSet<Vec<Symbol>>,
38 pub limits: TypeCheckingInput,
40 pub conditional_scopes: Vec<IndexSet<Symbol>>,
42 pub async_block_id: Option<NodeID>,
44}
45
46impl TypeCheckingVisitor<'_> {
47 pub fn in_scope<T>(&mut self, id: NodeID, func: impl FnOnce(&mut Self) -> T) -> T {
48 self.state.symbol_table.enter_scope(Some(id));
49 let result = func(self);
50 self.state.symbol_table.enter_parent();
51 result
52 }
53
54 pub fn in_conditional_scope<T>(&mut self, func: impl FnOnce(&mut Self) -> T) -> T {
55 self.conditional_scopes.push(Default::default());
56 let result = func(self);
57 self.conditional_scopes.pop();
58 result
59 }
60
61 pub fn insert_symbol_conditional_scope(&mut self, symbol: Symbol) {
62 self.conditional_scopes.last_mut().expect("A conditional scope must be present.").insert(symbol);
63 }
64
65 pub fn symbol_in_conditional_scope(&mut self, symbol: Symbol) -> bool {
66 self.conditional_scopes.last().map(|set| set.contains(&symbol)).unwrap_or(false)
67 }
68
69 pub fn emit_err(&self, err: TypeCheckerError) {
71 self.state.handler.emit_err(err);
72 }
73
74 pub fn emit_warning(&mut self, warning: TypeCheckerWarning) {
76 if self.state.warnings.insert(warning.clone().into()) {
77 self.state.handler.emit_warning(warning.into());
78 }
79 }
80
81 pub fn check_eq_types(&self, t1: &Option<Type>, t2: &Option<Type>, span: Span) {
83 match (t1, t2) {
84 (Some(t1), Some(t2)) if !t1.eq_flat_relaxed(t2) => {
85 self.emit_err(TypeCheckerError::type_should_be(t1, t2, span))
86 }
87 (Some(type_), None) | (None, Some(type_)) => {
88 self.emit_err(TypeCheckerError::type_should_be("no type", type_, span))
89 }
90 _ => {}
91 }
92 }
93
94 pub fn assert_and_return_type(&mut self, actual: Type, expected: &Option<Type>, span: Span) -> Type {
97 if expected.is_some() && !matches!(expected, Some(Type::Err)) {
99 self.check_eq_types(&Some(actual.clone()), expected, span);
100 }
101 actual
102 }
103
104 pub fn maybe_assert_type(&mut self, actual: &Type, expected: &Option<Type>, span: Span) {
105 if let Some(expected) = expected {
106 self.assert_type(actual, expected, span);
107 }
108 }
109
110 pub fn assert_type(&mut self, actual: &Type, expected: &Type, span: Span) {
111 if actual != &Type::Err && !actual.can_coerce_to(expected) {
112 self.emit_err(TypeCheckerError::type_should_be2(actual, format!("type `{expected}`"), span));
114 }
115 }
116
117 pub fn unwrap_optional_type(&self, expected: &Option<Type>) -> Option<Type> {
120 match expected {
121 Some(Type::Optional(opt_type)) => Some(*opt_type.inner.clone()),
122 other => other.clone(),
123 }
124 }
125
126 pub fn wrap_if_optional(&self, actual: Type, destination: &Option<Type>) -> Type {
129 match (actual, destination) {
130 (actual_type, Some(Type::Optional(opt_type))) if !matches!(actual_type, Type::Optional(_)) => {
132 if actual_type.can_coerce_to(&opt_type.inner) {
134 Type::Optional(OptionalType { inner: Box::new(actual_type) })
135 } else {
136 actual_type
137 }
138 }
139 (actual_type, _) => actual_type,
140 }
141 }
142
143 pub fn assert_int_type(&self, type_: &Type, span: Span) {
144 if !matches!(type_, Type::Err | Type::Integer(_)) {
145 self.emit_err(TypeCheckerError::type_should_be2(type_, "an integer", span));
146 }
147 }
148
149 pub fn assert_unsigned_type(&self, type_: &Type, span: Span) {
150 if !matches!(
151 type_,
152 Type::Err
153 | Type::Integer(IntegerType::U8)
154 | Type::Integer(IntegerType::U16)
155 | Type::Integer(IntegerType::U32)
156 | Type::Integer(IntegerType::U64)
157 | Type::Integer(IntegerType::U128)
158 ) {
159 self.emit_err(TypeCheckerError::type_should_be2(type_, "an unsigned integer", span));
160 }
161 }
162
163 pub fn assert_bool_int_type(&self, type_: &Type, span: Span) {
164 if !matches!(
165 type_,
166 Type::Err
167 | Type::Boolean
168 | Type::Integer(IntegerType::U8)
169 | Type::Integer(IntegerType::U16)
170 | Type::Integer(IntegerType::U32)
171 | Type::Integer(IntegerType::U64)
172 | Type::Integer(IntegerType::U128)
173 | Type::Integer(IntegerType::I8)
174 | Type::Integer(IntegerType::I16)
175 | Type::Integer(IntegerType::I32)
176 | Type::Integer(IntegerType::I64)
177 | Type::Integer(IntegerType::I128)
178 ) {
179 self.emit_err(TypeCheckerError::type_should_be2(type_, "a bool or integer", span));
180 }
181 }
182
183 pub fn assert_field_int_type(&self, type_: &Type, span: Span) {
184 if !matches!(
185 type_,
186 Type::Err
187 | Type::Field
188 | Type::Integer(IntegerType::U8)
189 | Type::Integer(IntegerType::U16)
190 | Type::Integer(IntegerType::U32)
191 | Type::Integer(IntegerType::U64)
192 | Type::Integer(IntegerType::U128)
193 | Type::Integer(IntegerType::I8)
194 | Type::Integer(IntegerType::I16)
195 | Type::Integer(IntegerType::I32)
196 | Type::Integer(IntegerType::I64)
197 | Type::Integer(IntegerType::I128)
198 ) {
199 self.emit_err(TypeCheckerError::type_should_be2(type_, "a field or integer", span));
200 }
201 }
202
203 pub fn assert_field_group_int_type(&self, type_: &Type, span: Span) {
204 if !matches!(type_, Type::Err | Type::Field | Type::Group | Type::Integer(_)) {
205 self.emit_err(TypeCheckerError::type_should_be2(type_, "a field, group, or integer", span));
206 }
207 }
208
209 pub fn get_core_constant(&self, type_: &Type, constant: &Identifier) -> Option<CoreConstant> {
211 if let Type::Identifier(ident) = type_ {
212 match CoreConstant::from_symbols(ident.name, constant.name) {
214 None => {
215 self.emit_err(TypeCheckerError::invalid_core_constant(ident.name, constant.name, ident.span()));
217 }
218 Some(core_constant) => return Some(core_constant),
219 }
220 }
221 None
222 }
223
224 pub fn get_core_function_call(&self, struct_: &Identifier, function: &Identifier) -> Option<CoreFunction> {
227 match CoreFunction::from_symbols(struct_.name, function.name) {
229 None => {
230 self.emit_err(TypeCheckerError::invalid_core_function(struct_.name, function.name, struct_.span()));
232 None
233 }
234 Some(core_instruction) => Some(core_instruction),
235 }
236 }
237
238 pub fn check_core_function_call(
242 &mut self,
243 core_function: CoreFunction,
244 arguments: &[(Type, &Expression)],
245 function_span: Span,
246 ) -> Type {
247 if arguments.len() != core_function.num_args() {
249 self.emit_err(TypeCheckerError::incorrect_num_args_to_call(
250 core_function.num_args(),
251 arguments.len(),
252 function_span,
253 ));
254 return Type::Err;
255 }
256
257 let assert_not_mapping_tuple_unit = |type_: &Type, span: Span| {
258 if matches!(type_, Type::Mapping(_) | Type::Tuple(_) | Type::Unit) {
259 self.emit_err(TypeCheckerError::type_should_be2(type_, "anything but a mapping, tuple, or unit", span));
260 }
261 };
262
263 let assert_pedersen_64_bit_input = |type_: &Type, span: Span| {
267 if !matches!(
268 type_,
269 Type::Integer(IntegerType::U8)
270 | Type::Integer(IntegerType::U16)
271 | Type::Integer(IntegerType::U32)
272 | Type::Integer(IntegerType::I8)
273 | Type::Integer(IntegerType::I16)
274 | Type::Integer(IntegerType::I32)
275 | Type::Boolean
276 | Type::Err
277 ) {
278 self.emit_err(TypeCheckerError::type_should_be2(
279 type_,
280 "an integer of less than 64 bits or a bool",
281 span,
282 ));
283 }
284 };
285
286 let assert_pedersen_128_bit_input = |type_: &Type, span: Span| {
293 if !matches!(
294 type_,
295 Type::Integer(IntegerType::U8)
296 | Type::Integer(IntegerType::U16)
297 | Type::Integer(IntegerType::U32)
298 | Type::Integer(IntegerType::U64)
299 | Type::Integer(IntegerType::I8)
300 | Type::Integer(IntegerType::I16)
301 | Type::Integer(IntegerType::I32)
302 | Type::Integer(IntegerType::I64)
303 | Type::Boolean
304 | Type::Err
305 ) {
306 self.emit_err(TypeCheckerError::type_should_be2(
307 type_,
308 "an integer of less than 128 bits or a bool",
309 span,
310 ));
311 }
312 };
313
314 let program_id_regex = regex::Regex::new(r"^[a-zA-Z][a-zA-Z0-9_]*\.aleo$").unwrap();
316
317 match core_function {
319 CoreFunction::BHP256CommitToAddress
320 | CoreFunction::BHP512CommitToAddress
321 | CoreFunction::BHP768CommitToAddress
322 | CoreFunction::BHP1024CommitToAddress => {
323 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
324 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
325 Type::Address
326 }
327 CoreFunction::BHP256CommitToField
328 | CoreFunction::BHP512CommitToField
329 | CoreFunction::BHP768CommitToField
330 | CoreFunction::BHP1024CommitToField => {
331 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
332 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
333 Type::Field
334 }
335 CoreFunction::BHP256CommitToGroup
336 | CoreFunction::BHP512CommitToGroup
337 | CoreFunction::BHP768CommitToGroup
338 | CoreFunction::BHP1024CommitToGroup => {
339 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
340 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
341 Type::Group
342 }
343 CoreFunction::BHP256HashToAddress
344 | CoreFunction::BHP512HashToAddress
345 | CoreFunction::BHP768HashToAddress
346 | CoreFunction::BHP1024HashToAddress
347 | CoreFunction::Keccak256HashToAddress
348 | CoreFunction::Keccak384HashToAddress
349 | CoreFunction::Keccak512HashToAddress
350 | CoreFunction::Poseidon2HashToAddress
351 | CoreFunction::Poseidon4HashToAddress
352 | CoreFunction::Poseidon8HashToAddress
353 | CoreFunction::SHA3_256HashToAddress
354 | CoreFunction::SHA3_384HashToAddress
355 | CoreFunction::SHA3_512HashToAddress => {
356 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
357 Type::Address
358 }
359 CoreFunction::BHP256HashToField
360 | CoreFunction::BHP512HashToField
361 | CoreFunction::BHP768HashToField
362 | CoreFunction::BHP1024HashToField
363 | CoreFunction::Keccak256HashToField
364 | CoreFunction::Keccak384HashToField
365 | CoreFunction::Keccak512HashToField
366 | CoreFunction::Poseidon2HashToField
367 | CoreFunction::Poseidon4HashToField
368 | CoreFunction::Poseidon8HashToField
369 | CoreFunction::SHA3_256HashToField
370 | CoreFunction::SHA3_384HashToField
371 | CoreFunction::SHA3_512HashToField => {
372 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
373 Type::Field
374 }
375 CoreFunction::BHP256HashToGroup
376 | CoreFunction::BHP512HashToGroup
377 | CoreFunction::BHP768HashToGroup
378 | CoreFunction::BHP1024HashToGroup
379 | CoreFunction::Keccak256HashToGroup
380 | CoreFunction::Keccak384HashToGroup
381 | CoreFunction::Keccak512HashToGroup
382 | CoreFunction::Poseidon2HashToGroup
383 | CoreFunction::Poseidon4HashToGroup
384 | CoreFunction::Poseidon8HashToGroup
385 | CoreFunction::SHA3_256HashToGroup
386 | CoreFunction::SHA3_384HashToGroup
387 | CoreFunction::SHA3_512HashToGroup => {
388 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
389 Type::Group
390 }
391 CoreFunction::BHP256HashToI8
392 | CoreFunction::BHP512HashToI8
393 | CoreFunction::BHP768HashToI8
394 | CoreFunction::BHP1024HashToI8
395 | CoreFunction::Keccak256HashToI8
396 | CoreFunction::Keccak384HashToI8
397 | CoreFunction::Keccak512HashToI8
398 | CoreFunction::Poseidon2HashToI8
399 | CoreFunction::Poseidon4HashToI8
400 | CoreFunction::Poseidon8HashToI8
401 | CoreFunction::SHA3_256HashToI8
402 | CoreFunction::SHA3_384HashToI8
403 | CoreFunction::SHA3_512HashToI8 => {
404 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
405 Type::Integer(IntegerType::I8)
406 }
407 CoreFunction::BHP256HashToI16
408 | CoreFunction::BHP512HashToI16
409 | CoreFunction::BHP768HashToI16
410 | CoreFunction::BHP1024HashToI16
411 | CoreFunction::Keccak256HashToI16
412 | CoreFunction::Keccak384HashToI16
413 | CoreFunction::Keccak512HashToI16
414 | CoreFunction::Poseidon2HashToI16
415 | CoreFunction::Poseidon4HashToI16
416 | CoreFunction::Poseidon8HashToI16
417 | CoreFunction::SHA3_256HashToI16
418 | CoreFunction::SHA3_384HashToI16
419 | CoreFunction::SHA3_512HashToI16 => {
420 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
421 Type::Integer(IntegerType::I16)
422 }
423 CoreFunction::BHP256HashToI32
424 | CoreFunction::BHP512HashToI32
425 | CoreFunction::BHP768HashToI32
426 | CoreFunction::BHP1024HashToI32
427 | CoreFunction::Keccak256HashToI32
428 | CoreFunction::Keccak384HashToI32
429 | CoreFunction::Keccak512HashToI32
430 | CoreFunction::Poseidon2HashToI32
431 | CoreFunction::Poseidon4HashToI32
432 | CoreFunction::Poseidon8HashToI32
433 | CoreFunction::SHA3_256HashToI32
434 | CoreFunction::SHA3_384HashToI32
435 | CoreFunction::SHA3_512HashToI32 => {
436 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
437 Type::Integer(IntegerType::I32)
438 }
439 CoreFunction::BHP256HashToI64
440 | CoreFunction::BHP512HashToI64
441 | CoreFunction::BHP768HashToI64
442 | CoreFunction::BHP1024HashToI64
443 | CoreFunction::Keccak256HashToI64
444 | CoreFunction::Keccak384HashToI64
445 | CoreFunction::Keccak512HashToI64
446 | CoreFunction::Poseidon2HashToI64
447 | CoreFunction::Poseidon4HashToI64
448 | CoreFunction::Poseidon8HashToI64
449 | CoreFunction::SHA3_256HashToI64
450 | CoreFunction::SHA3_384HashToI64
451 | CoreFunction::SHA3_512HashToI64 => {
452 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
453 Type::Integer(IntegerType::I64)
454 }
455 CoreFunction::BHP256HashToI128
456 | CoreFunction::BHP512HashToI128
457 | CoreFunction::BHP768HashToI128
458 | CoreFunction::BHP1024HashToI128
459 | CoreFunction::Keccak256HashToI128
460 | CoreFunction::Keccak384HashToI128
461 | CoreFunction::Keccak512HashToI128
462 | CoreFunction::Poseidon2HashToI128
463 | CoreFunction::Poseidon4HashToI128
464 | CoreFunction::Poseidon8HashToI128
465 | CoreFunction::SHA3_256HashToI128
466 | CoreFunction::SHA3_384HashToI128
467 | CoreFunction::SHA3_512HashToI128 => {
468 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
469 Type::Integer(IntegerType::I128)
470 }
471 CoreFunction::BHP256HashToU8
472 | CoreFunction::BHP512HashToU8
473 | CoreFunction::BHP768HashToU8
474 | CoreFunction::BHP1024HashToU8
475 | CoreFunction::Keccak256HashToU8
476 | CoreFunction::Keccak384HashToU8
477 | CoreFunction::Keccak512HashToU8
478 | CoreFunction::Poseidon2HashToU8
479 | CoreFunction::Poseidon4HashToU8
480 | CoreFunction::Poseidon8HashToU8
481 | CoreFunction::SHA3_256HashToU8
482 | CoreFunction::SHA3_384HashToU8
483 | CoreFunction::SHA3_512HashToU8 => {
484 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
485 Type::Integer(IntegerType::U8)
486 }
487 CoreFunction::BHP256HashToU16
488 | CoreFunction::BHP512HashToU16
489 | CoreFunction::BHP768HashToU16
490 | CoreFunction::BHP1024HashToU16
491 | CoreFunction::Keccak256HashToU16
492 | CoreFunction::Keccak384HashToU16
493 | CoreFunction::Keccak512HashToU16
494 | CoreFunction::Poseidon2HashToU16
495 | CoreFunction::Poseidon4HashToU16
496 | CoreFunction::Poseidon8HashToU16
497 | CoreFunction::SHA3_256HashToU16
498 | CoreFunction::SHA3_384HashToU16
499 | CoreFunction::SHA3_512HashToU16 => {
500 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
501 Type::Integer(IntegerType::U16)
502 }
503 CoreFunction::BHP256HashToU32
504 | CoreFunction::BHP512HashToU32
505 | CoreFunction::BHP768HashToU32
506 | CoreFunction::BHP1024HashToU32
507 | CoreFunction::Keccak256HashToU32
508 | CoreFunction::Keccak384HashToU32
509 | CoreFunction::Keccak512HashToU32
510 | CoreFunction::Poseidon2HashToU32
511 | CoreFunction::Poseidon4HashToU32
512 | CoreFunction::Poseidon8HashToU32
513 | CoreFunction::SHA3_256HashToU32
514 | CoreFunction::SHA3_384HashToU32
515 | CoreFunction::SHA3_512HashToU32 => {
516 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
517 Type::Integer(IntegerType::U32)
518 }
519 CoreFunction::BHP256HashToU64
520 | CoreFunction::BHP512HashToU64
521 | CoreFunction::BHP768HashToU64
522 | CoreFunction::BHP1024HashToU64
523 | CoreFunction::Keccak256HashToU64
524 | CoreFunction::Keccak384HashToU64
525 | CoreFunction::Keccak512HashToU64
526 | CoreFunction::Poseidon2HashToU64
527 | CoreFunction::Poseidon4HashToU64
528 | CoreFunction::Poseidon8HashToU64
529 | CoreFunction::SHA3_256HashToU64
530 | CoreFunction::SHA3_384HashToU64
531 | CoreFunction::SHA3_512HashToU64 => {
532 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
533 Type::Integer(IntegerType::U64)
534 }
535 CoreFunction::BHP256HashToU128
536 | CoreFunction::BHP512HashToU128
537 | CoreFunction::BHP768HashToU128
538 | CoreFunction::BHP1024HashToU128
539 | CoreFunction::Keccak256HashToU128
540 | CoreFunction::Keccak384HashToU128
541 | CoreFunction::Keccak512HashToU128
542 | CoreFunction::Poseidon2HashToU128
543 | CoreFunction::Poseidon4HashToU128
544 | CoreFunction::Poseidon8HashToU128
545 | CoreFunction::SHA3_256HashToU128
546 | CoreFunction::SHA3_384HashToU128
547 | CoreFunction::SHA3_512HashToU128 => {
548 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
549 Type::Integer(IntegerType::U128)
550 }
551 CoreFunction::BHP256HashToScalar
552 | CoreFunction::BHP512HashToScalar
553 | CoreFunction::BHP768HashToScalar
554 | CoreFunction::BHP1024HashToScalar
555 | CoreFunction::Keccak256HashToScalar
556 | CoreFunction::Keccak384HashToScalar
557 | CoreFunction::Keccak512HashToScalar
558 | CoreFunction::Poseidon2HashToScalar
559 | CoreFunction::Poseidon4HashToScalar
560 | CoreFunction::Poseidon8HashToScalar
561 | CoreFunction::SHA3_256HashToScalar
562 | CoreFunction::SHA3_384HashToScalar
563 | CoreFunction::SHA3_512HashToScalar => {
564 assert_not_mapping_tuple_unit(&arguments[0].0, arguments[0].1.span());
565 Type::Scalar
566 }
567 CoreFunction::Pedersen64CommitToAddress => {
568 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
569 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
571 Type::Address
572 }
573 CoreFunction::Pedersen64CommitToField => {
574 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
575 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
577 Type::Field
578 }
579 CoreFunction::Pedersen64CommitToGroup => {
580 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
581 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
583 Type::Group
584 }
585 CoreFunction::Pedersen64HashToAddress => {
586 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
587 Type::Address
588 }
589 CoreFunction::Pedersen64HashToField => {
590 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
591 Type::Field
592 }
593 CoreFunction::Pedersen64HashToGroup => {
594 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
595 Type::Group
596 }
597 CoreFunction::Pedersen64HashToI8 => {
598 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
599 Type::Integer(IntegerType::I8)
600 }
601 CoreFunction::Pedersen64HashToI16 => {
602 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
603 Type::Integer(IntegerType::I16)
604 }
605 CoreFunction::Pedersen64HashToI32 => {
606 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
607 Type::Integer(IntegerType::I32)
608 }
609 CoreFunction::Pedersen64HashToI64 => {
610 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
611 Type::Integer(IntegerType::I64)
612 }
613 CoreFunction::Pedersen64HashToI128 => {
614 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
615 Type::Integer(IntegerType::I128)
616 }
617 CoreFunction::Pedersen64HashToU8 => {
618 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
619 Type::Integer(IntegerType::U8)
620 }
621 CoreFunction::Pedersen64HashToU16 => {
622 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
623 Type::Integer(IntegerType::U16)
624 }
625 CoreFunction::Pedersen64HashToU32 => {
626 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
627 Type::Integer(IntegerType::U32)
628 }
629 CoreFunction::Pedersen64HashToU64 => {
630 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
631 Type::Integer(IntegerType::U64)
632 }
633 CoreFunction::Pedersen64HashToU128 => {
634 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
635 Type::Integer(IntegerType::U128)
636 }
637 CoreFunction::Pedersen64HashToScalar => {
638 assert_pedersen_64_bit_input(&arguments[0].0, arguments[0].1.span());
639 Type::Scalar
640 }
641 CoreFunction::Pedersen128CommitToAddress => {
642 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
643 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
644 Type::Address
645 }
646 CoreFunction::Pedersen128CommitToField => {
647 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
648 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
649 Type::Field
650 }
651 CoreFunction::Pedersen128CommitToGroup => {
652 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
653 self.assert_type(&arguments[1].0, &Type::Scalar, arguments[1].1.span());
654 Type::Group
655 }
656 CoreFunction::Pedersen128HashToAddress => {
657 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
659 Type::Address
660 }
661 CoreFunction::Pedersen128HashToField => {
662 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
663 Type::Field
664 }
665 CoreFunction::Pedersen128HashToGroup => {
666 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
667 Type::Group
668 }
669 CoreFunction::Pedersen128HashToI8 => {
670 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
671 Type::Integer(IntegerType::I8)
672 }
673 CoreFunction::Pedersen128HashToI16 => {
674 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
675 Type::Integer(IntegerType::I16)
676 }
677 CoreFunction::Pedersen128HashToI32 => {
678 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
679 Type::Integer(IntegerType::I32)
680 }
681 CoreFunction::Pedersen128HashToI64 => {
682 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
683 Type::Integer(IntegerType::I64)
684 }
685 CoreFunction::Pedersen128HashToI128 => {
686 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
687 Type::Integer(IntegerType::I128)
688 }
689 CoreFunction::Pedersen128HashToU8 => {
690 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
691 Type::Integer(IntegerType::U8)
692 }
693 CoreFunction::Pedersen128HashToU16 => {
694 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
695 Type::Integer(IntegerType::U16)
696 }
697 CoreFunction::Pedersen128HashToU32 => {
698 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
699 Type::Integer(IntegerType::U32)
700 }
701 CoreFunction::Pedersen128HashToU64 => {
702 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
703 Type::Integer(IntegerType::U64)
704 }
705 CoreFunction::Pedersen128HashToU128 => {
706 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
707 Type::Integer(IntegerType::U128)
708 }
709 CoreFunction::Pedersen128HashToScalar => {
710 assert_pedersen_128_bit_input(&arguments[0].0, arguments[0].1.span());
711 Type::Scalar
712 }
713 CoreFunction::MappingGet => {
714 self.check_access_allowed("Mapping::get", true, function_span);
716 self.assert_mapping_type(&arguments[0].0, arguments[0].1.span());
718 let Type::Mapping(mapping_type) = &arguments[0].0 else {
719 return Type::Err;
721 };
722
723 self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1.span());
724
725 mapping_type.value.deref().clone()
726 }
727 CoreFunction::MappingGetOrUse => {
728 self.check_access_allowed("Mapping::get_or_use", true, function_span);
730 self.assert_mapping_type(&arguments[0].0, arguments[0].1.span());
732
733 let Type::Mapping(mapping_type) = &arguments[0].0 else {
734 return Type::Err;
736 };
737
738 self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1.span());
740 self.assert_type(&arguments[2].0, &mapping_type.value, arguments[2].1.span());
742
743 mapping_type.value.deref().clone()
744 }
745 CoreFunction::MappingSet => {
746 self.check_access_allowed("Mapping::set", true, function_span);
748 self.assert_mapping_type(&arguments[0].0, arguments[0].1.span());
750
751 let Type::Mapping(mapping_type) = &arguments[0].0 else {
752 return Type::Err;
754 };
755
756 self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1.span());
758 self.assert_type(&arguments[2].0, &mapping_type.value, arguments[2].1.span());
760
761 Type::Unit
762 }
763 CoreFunction::MappingRemove => {
764 self.check_access_allowed("Mapping::remove", true, function_span);
766 self.assert_mapping_type(&arguments[0].0, arguments[0].1.span());
768
769 let Type::Mapping(mapping_type) = &arguments[0].0 else {
770 return Type::Err;
772 };
773
774 if mapping_type.program != self.scope_state.program_name.unwrap() {
776 self.state
777 .handler
778 .emit_err(TypeCheckerError::cannot_modify_external_mapping("remove", function_span));
779 }
780
781 self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1.span());
783
784 Type::Unit
785 }
786 CoreFunction::MappingContains => {
787 self.check_access_allowed("Mapping::contains", true, function_span);
789 self.assert_mapping_type(&arguments[0].0, arguments[0].1.span());
791
792 let Type::Mapping(mapping_type) = &arguments[0].0 else {
793 return Type::Err;
795 };
796
797 self.assert_type(&arguments[1].0, &mapping_type.key, arguments[1].1.span());
799
800 Type::Boolean
801 }
802 CoreFunction::OptionalUnwrap => {
803 self.assert_optional_type(&arguments[0].0, arguments[0].1.span());
805
806 match &arguments[0].0 {
807 Type::Optional(opt) => opt.inner.deref().clone(),
808 _ => Type::Err,
809 }
810 }
811 CoreFunction::OptionalUnwrapOr => {
812 unreachable!("we should have handled separately outside `check_core_function_call`.")
813 }
814 CoreFunction::GroupToXCoordinate | CoreFunction::GroupToYCoordinate => {
815 self.assert_type(&arguments[0].0, &Type::Group, arguments[0].1.span());
817 Type::Field
818 }
819 CoreFunction::ChaChaRandAddress => Type::Address,
820 CoreFunction::ChaChaRandBool => Type::Boolean,
821 CoreFunction::ChaChaRandField => Type::Field,
822 CoreFunction::ChaChaRandGroup => Type::Group,
823 CoreFunction::ChaChaRandI8 => Type::Integer(IntegerType::I8),
824 CoreFunction::ChaChaRandI16 => Type::Integer(IntegerType::I16),
825 CoreFunction::ChaChaRandI32 => Type::Integer(IntegerType::I32),
826 CoreFunction::ChaChaRandI64 => Type::Integer(IntegerType::I64),
827 CoreFunction::ChaChaRandI128 => Type::Integer(IntegerType::I128),
828 CoreFunction::ChaChaRandScalar => Type::Scalar,
829 CoreFunction::ChaChaRandU8 => Type::Integer(IntegerType::U8),
830 CoreFunction::ChaChaRandU16 => Type::Integer(IntegerType::U16),
831 CoreFunction::ChaChaRandU32 => Type::Integer(IntegerType::U32),
832 CoreFunction::ChaChaRandU64 => Type::Integer(IntegerType::U64),
833 CoreFunction::ChaChaRandU128 => Type::Integer(IntegerType::U128),
834 CoreFunction::SignatureVerify => {
835 assert_not_mapping_tuple_unit(&arguments[2].0, arguments[2].1.span());
838
839 self.assert_type(&arguments[0].0, &Type::Signature, arguments[0].1.span());
841 self.assert_type(&arguments[1].0, &Type::Address, arguments[1].1.span());
843 Type::Boolean
844 }
845 CoreFunction::FutureAwait => Type::Unit,
846 CoreFunction::ProgramChecksum => {
847 let (type_, expression) = &arguments[0];
849 let span = expression.span();
850 match expression {
852 Expression::Literal(Literal { variant: LiteralVariant::Address(s), .. })
853 if program_id_regex.is_match(s) => {}
854 _ => {
855 self.emit_err(TypeCheckerError::custom(
856 "`Program::checksum` must be called on a program ID, e.g. `foo.aleo`",
857 span,
858 ));
859 }
860 }
861 self.assert_type(type_, &Type::Address, span);
863 Type::Array(ArrayType::new(
865 Type::Integer(IntegerType::U8),
866 Expression::Literal(Literal::integer(
867 IntegerType::U8,
868 "32".to_string(),
869 Default::default(),
870 Default::default(),
871 )),
872 ))
873 }
874 CoreFunction::ProgramEdition => {
875 let (type_, expression) = &arguments[0];
877 let span = expression.span();
878 match expression {
880 Expression::Literal(Literal { variant: LiteralVariant::Address(s), .. })
881 if program_id_regex.is_match(s) => {}
882 _ => {
883 self.emit_err(TypeCheckerError::custom(
884 "`Program::edition` must be called on a program ID, e.g. `foo.aleo`",
885 span,
886 ));
887 }
888 }
889 self.assert_type(type_, &Type::Address, span);
891 Type::Integer(IntegerType::U16)
893 }
894 CoreFunction::ProgramOwner => {
895 let (type_, expression) = &arguments[0];
897 let span = expression.span();
898 match expression {
900 Expression::Literal(Literal { variant: LiteralVariant::Address(s), .. })
901 if program_id_regex.is_match(s) => {}
902 _ => {
903 self.emit_err(TypeCheckerError::custom(
904 "`Program::program_owner` must be called on a program ID, e.g. `foo.aleo`",
905 span,
906 ));
907 }
908 }
909 self.assert_type(type_, &Type::Address, span);
911 Type::Address
913 }
914 CoreFunction::CheatCodePrintMapping => {
915 self.assert_mapping_type(&arguments[0].0, arguments[0].1.span());
916 Type::Unit
917 }
918 CoreFunction::CheatCodeSetBlockHeight => {
919 self.assert_type(&arguments[0].0, &Type::Integer(IntegerType::U32), arguments[0].1.span());
920 Type::Unit
921 }
922 }
923 }
924
925 pub fn assert_member_is_not_record(&mut self, span: Span, parent: Symbol, type_: &Type) {
927 match type_ {
928 Type::Composite(struct_)
929 if self
930 .lookup_struct(struct_.program.or(self.scope_state.program_name), &struct_.path.absolute_path())
931 .is_some_and(|struct_| struct_.is_record) =>
932 {
933 self.emit_err(TypeCheckerError::struct_or_record_cannot_contain_record(
934 parent,
935 struct_.path.clone(),
936 span,
937 ))
938 }
939 Type::Tuple(tuple_type) => {
940 for type_ in tuple_type.elements().iter() {
941 self.assert_member_is_not_record(span, parent, type_)
942 }
943 }
944 _ => {} }
946 }
947
948 pub fn assert_type_is_valid(&mut self, type_: &Type, span: Span) {
950 match type_ {
951 Type::Unit => {
953 self.emit_err(TypeCheckerError::unit_type_only_return(span));
954 }
955 Type::String => {
957 self.emit_err(TypeCheckerError::strings_are_not_supported(span));
958 }
959 Type::Composite(struct_)
961 if self
962 .lookup_struct(struct_.program.or(self.scope_state.program_name), &struct_.path.absolute_path())
963 .is_none() =>
964 {
965 self.emit_err(TypeCheckerError::undefined_type(struct_.path.clone(), span));
966 }
967 Type::Tuple(tuple_type) => {
969 for type_ in tuple_type.elements().iter() {
970 self.assert_type_is_valid(type_, span);
971 }
972 }
973 Type::Mapping(mapping_type) => {
975 self.assert_type_is_valid(&mapping_type.key, span);
976 self.assert_type_is_valid(&mapping_type.value, span);
977 }
978 Type::Array(array_type) => {
980 if let Some(length) = array_type.length.as_u32() {
983 if length == 0 {
984 self.emit_err(TypeCheckerError::array_empty(span));
985 } else if length > self.limits.max_array_elements as u32 {
986 self.emit_err(TypeCheckerError::array_too_large(length, self.limits.max_array_elements, span));
987 }
988 } else if let Expression::Literal(_) = &*array_type.length {
989 self.emit_err(TypeCheckerError::array_too_large_for_u32(span));
991 }
992 match array_type.element_type() {
996 Type::Future(_) => self.emit_err(TypeCheckerError::array_element_cannot_be_future(span)),
998 Type::Tuple(_) => self.emit_err(TypeCheckerError::array_element_cannot_be_tuple(span)),
1000 Type::Composite(struct_type) => {
1002 if let Some(struct_) = self.lookup_struct(
1004 struct_type.program.or(self.scope_state.program_name),
1005 &struct_type.path.absolute_path(),
1006 ) {
1007 if struct_.is_record {
1009 self.emit_err(TypeCheckerError::array_element_cannot_be_record(span));
1010 }
1011 }
1012 }
1013 _ => {} }
1015 self.assert_type_is_valid(array_type.element_type(), span);
1016 }
1017 Type::Optional(OptionalType { inner }) => {
1018 match &**inner {
1019 Type::Composite(struct_type) => {
1020 if let Some(struct_) = self.lookup_struct(
1022 struct_type.program.or(self.scope_state.program_name),
1023 &struct_type.path.absolute_path(),
1024 ) {
1025 if struct_.is_record {
1027 self.emit_err(TypeCheckerError::optional_wrapping_of_records_unsupported(inner, span));
1028 }
1029 }
1030 }
1031 Type::Future(_)
1032 | Type::Identifier(_)
1033 | Type::Mapping(_)
1034 | Type::Optional(_)
1035 | Type::String
1036 | Type::Signature
1037 | Type::Tuple(_) => {
1038 self.emit_err(TypeCheckerError::optional_wrapping_unsupported(inner, span));
1039 }
1040 _ => self.assert_type_is_valid(inner, span),
1041 }
1042 }
1043 _ => {} }
1045 }
1046
1047 pub fn assert_mapping_type(&self, type_: &Type, span: Span) {
1049 if type_ != &Type::Err && !matches!(type_, Type::Mapping(_)) {
1050 self.emit_err(TypeCheckerError::type_should_be2(type_, "a mapping", span));
1051 }
1052 }
1053
1054 pub fn assert_optional_type(&self, type_: &Type, span: Span) {
1056 if type_ != &Type::Err && !matches!(type_, Type::Optional(_)) {
1057 self.emit_err(TypeCheckerError::type_should_be2(type_, "an optional", span));
1058 }
1059 }
1060
1061 pub fn contains_optional_type(&mut self, ty: &Type) -> bool {
1062 let mut visited_paths = IndexSet::<Vec<Symbol>>::new();
1063 self.contains_optional_type_inner(ty, &mut visited_paths)
1064 }
1065
1066 fn contains_optional_type_inner(&mut self, ty: &Type, visited_paths: &mut IndexSet<Vec<Symbol>>) -> bool {
1067 match ty {
1068 Type::Optional(_) => true,
1069
1070 Type::Tuple(tuple) => tuple.elements.iter().any(|e| self.contains_optional_type_inner(e, visited_paths)),
1071
1072 Type::Array(array) => self.contains_optional_type_inner(&array.element_type, visited_paths),
1073
1074 Type::Composite(struct_type) => {
1075 let path = struct_type.path.absolute_path();
1076
1077 if !visited_paths.insert(path.clone()) {
1079 return false;
1080 }
1081
1082 if let Some(comp) = self.lookup_struct(struct_type.program.or(self.scope_state.program_name), &path) {
1083 comp.members
1084 .iter()
1085 .any(|Member { type_, .. }| self.contains_optional_type_inner(type_, visited_paths))
1086 } else {
1087 false
1088 }
1089 }
1090
1091 _ => false,
1092 }
1093 }
1094
1095 pub fn assert_array_type(&self, type_: &Type, span: Span) {
1096 if type_ != &Type::Err && !matches!(type_, Type::Array(_)) {
1097 self.emit_err(TypeCheckerError::type_should_be2(type_, "an array", span));
1098 }
1099 }
1100
1101 pub fn check_function_signature(&mut self, function: &Function, is_stub: bool) {
1103 let function_path = self
1104 .scope_state
1105 .module_name
1106 .iter()
1107 .cloned()
1108 .chain(std::iter::once(function.identifier.name))
1109 .collect::<Vec<Symbol>>();
1110
1111 self.scope_state.variant = Some(function.variant);
1112
1113 let mut inferred_inputs: Vec<Type> = Vec::new();
1114
1115 if self.scope_state.variant == Some(Variant::AsyncFunction) && !self.scope_state.is_stub {
1116 if !function.output.is_empty() {
1118 self.emit_err(TypeCheckerError::async_function_cannot_return_value(function.span()));
1119 }
1120
1121 let mut caller_finalizers = self
1124 .async_function_callers
1125 .get(&Location::new(self.scope_state.program_name.unwrap(), function_path))
1126 .map(|callers| {
1127 callers
1128 .iter()
1129 .flat_map(|caller| {
1130 let caller = Location::new(caller.program, caller.path.clone());
1131 self.state.symbol_table.lookup_function(&caller)
1132 })
1133 .flat_map(|fn_symbol| fn_symbol.finalizer.clone())
1134 })
1135 .into_iter()
1136 .flatten();
1137
1138 if let Some(first) = caller_finalizers.next() {
1139 inferred_inputs = first.inferred_inputs.clone();
1140
1141 for finalizer in caller_finalizers {
1144 assert_eq!(inferred_inputs.len(), finalizer.inferred_inputs.len());
1145 for (t1, t2) in inferred_inputs.iter_mut().zip(finalizer.inferred_inputs.iter()) {
1146 Self::merge_types(t1, t2);
1147 }
1148 }
1149 } else {
1150 self.emit_warning(TypeCheckerWarning::async_function_is_never_called_by_transition_function(
1151 function.identifier.name,
1152 function.span(),
1153 ));
1154 }
1155 }
1156
1157 if self.scope_state.variant != Some(Variant::Inline) && !function.const_parameters.is_empty() {
1160 self.emit_err(TypeCheckerError::only_inline_can_have_const_generics(function.identifier.span()));
1161 }
1162
1163 for const_param in &function.const_parameters {
1164 self.visit_type(const_param.type_());
1165
1166 if !matches!(
1168 const_param.type_(),
1169 Type::Boolean | Type::Integer(_) | Type::Address | Type::Scalar | Type::Group | Type::Field
1170 ) {
1171 self.emit_err(TypeCheckerError::bad_const_generic_type(const_param.type_(), const_param.span()));
1172 }
1173
1174 if let Err(err) = self.state.symbol_table.insert_variable(
1176 self.scope_state.program_name.unwrap(),
1177 &[const_param.identifier().name],
1178 VariableSymbol {
1179 type_: const_param.type_().clone(),
1180 span: const_param.identifier.span(),
1181 declaration: VariableType::ConstParameter,
1182 },
1183 ) {
1184 self.state.handler.emit_err(err);
1185 }
1186
1187 self.state.type_table.insert(const_param.identifier().id(), const_param.type_().clone());
1189 }
1190
1191 for (i, input) in function.input.iter().enumerate() {
1193 self.visit_type(input.type_());
1194
1195 let table_type = inferred_inputs.get(i).unwrap_or_else(|| input.type_());
1197
1198 self.assert_type_is_valid(table_type, input.span());
1200
1201 if matches!(table_type, Type::Tuple(_)) {
1203 self.emit_err(TypeCheckerError::function_cannot_take_tuple_as_input(input.span()))
1204 }
1205
1206 if self.contains_optional_type(table_type)
1208 && matches!(function.variant, Variant::Transition | Variant::AsyncTransition | Variant::Function)
1209 {
1210 self.emit_err(TypeCheckerError::function_cannot_take_option_as_input(
1211 input.identifier,
1212 table_type,
1213 input.span(),
1214 ))
1215 }
1216
1217 if let Type::Composite(struct_) = table_type {
1219 if !function.variant.is_transition() {
1221 if let Some(elem) = self
1222 .lookup_struct(struct_.program.or(self.scope_state.program_name), &struct_.path.absolute_path())
1223 {
1224 if elem.is_record {
1225 self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(input.span()))
1226 }
1227 } else {
1228 self.emit_err(TypeCheckerError::undefined_type(struct_.path.clone(), input.span()));
1229 }
1230 }
1231 }
1232
1233 match self.scope_state.variant.unwrap() {
1235 Variant::Transition | Variant::AsyncTransition if input.mode() == Mode::Constant => {
1237 self.emit_err(TypeCheckerError::transition_function_inputs_cannot_be_const(input.span()))
1238 }
1239 Variant::Function | Variant::Inline if input.mode() != Mode::None => {
1241 self.emit_err(TypeCheckerError::regular_function_inputs_cannot_have_modes(input.span()))
1242 }
1243 Variant::AsyncFunction if matches!(input.mode(), Mode::Constant | Mode::Private) => {
1245 self.emit_err(TypeCheckerError::async_function_input_must_be_public(input.span()));
1246 }
1247 _ => {} }
1249
1250 if matches!(table_type, Type::Future(..)) {
1251 if !matches!(self.scope_state.variant, Some(Variant::AsyncFunction)) {
1253 self.emit_err(TypeCheckerError::no_future_parameters(input.span()));
1254 }
1255 }
1256
1257 if !is_stub {
1258 if let Err(err) = self.state.symbol_table.insert_variable(
1260 self.scope_state.program_name.unwrap(),
1261 &[input.identifier().name],
1262 VariableSymbol {
1263 type_: table_type.clone(),
1264 span: input.identifier.span(),
1265 declaration: VariableType::Input(input.mode()),
1266 },
1267 ) {
1268 self.state.handler.emit_err(err);
1269 }
1270
1271 self.state.type_table.insert(input.identifier().id(), table_type.clone());
1273 }
1274 }
1275
1276 function.output.iter().enumerate().for_each(|(index, function_output)| {
1279 self.visit_type(&function_output.type_);
1280
1281 if let Type::Composite(struct_) = function_output.type_.clone() {
1284 if let Some(val) =
1285 self.lookup_struct(struct_.program.or(self.scope_state.program_name), &struct_.path.absolute_path())
1286 {
1287 if val.is_record && !function.variant.is_transition() {
1288 self.emit_err(TypeCheckerError::function_cannot_input_or_output_a_record(function_output.span));
1289 }
1290 }
1291 }
1292
1293 self.assert_type_is_valid(&function_output.type_, function_output.span);
1295
1296 if matches!(&function_output.type_, Type::Tuple(_)) {
1298 self.emit_err(TypeCheckerError::nested_tuple_type(function_output.span))
1299 }
1300
1301 if self.contains_optional_type(&function_output.type_)
1303 && matches!(function.variant, Variant::Transition | Variant::AsyncTransition | Variant::Function)
1304 {
1305 self.emit_err(TypeCheckerError::function_cannot_return_option_as_output(
1306 &function_output.type_,
1307 function_output.span(),
1308 ))
1309 }
1310
1311 if function_output.mode == Mode::Constant {
1314 self.emit_err(TypeCheckerError::cannot_have_constant_output_mode(function_output.span));
1315 }
1316 if self.scope_state.variant == Some(Variant::AsyncTransition)
1318 && ((index < function.output.len() - 1 && matches!(function_output.type_, Type::Future(_)))
1319 || (index == function.output.len() - 1 && !matches!(function_output.type_, Type::Future(_))))
1320 {
1321 self.emit_err(TypeCheckerError::async_transition_invalid_output(function_output.span));
1322 }
1323 if !matches!(self.scope_state.variant, Some(Variant::AsyncTransition) | Some(Variant::Script))
1325 && matches!(function_output.type_, Type::Future(_))
1326 {
1327 self.emit_err(TypeCheckerError::only_async_transition_can_return_future(function_output.span));
1328 }
1329 });
1330
1331 self.visit_type(&function.output_type);
1332 }
1333
1334 fn merge_types(lhs: &mut Type, rhs: &Type) {
1340 if let Type::Future(f1) = lhs {
1341 if let Type::Future(f2) = rhs {
1342 for (i, type_) in f2.inputs.iter().enumerate() {
1343 if let Some(lhs_type) = f1.inputs.get_mut(i) {
1344 Self::merge_types(lhs_type, type_);
1345 } else {
1346 f1.inputs.push(Type::Err);
1347 }
1348 }
1349 } else {
1350 *lhs = Type::Err;
1351 }
1352 } else if !lhs.eq_user(rhs) {
1353 *lhs = Type::Err;
1354 }
1355 }
1356
1357 pub fn lookup_struct(&mut self, program: Option<Symbol>, name: &[Symbol]) -> Option<Composite> {
1359 let record_comp =
1360 program.and_then(|prog| self.state.symbol_table.lookup_record(&Location::new(prog, name.to_vec())));
1361 let comp = record_comp.or_else(|| self.state.symbol_table.lookup_struct(name));
1362 if let Some(s) = comp {
1364 if !s.is_record || program == self.scope_state.program_name {
1366 self.used_structs.insert(name.to_vec());
1367 }
1368 }
1369 comp.cloned()
1370 }
1371
1372 pub fn insert_variable(&mut self, inferred_type: Option<Type>, name: &Identifier, type_: Type, span: Span) {
1374 self.insert_symbol_conditional_scope(name.name);
1375
1376 let is_future = match &type_ {
1377 Type::Future(..) => true,
1378 Type::Tuple(tuple_type) if matches!(tuple_type.elements().last(), Some(Type::Future(..))) => true,
1379 _ => false,
1380 };
1381
1382 if is_future {
1383 if let Some(call_location) = &self.scope_state.call_location {
1386 self.scope_state.futures.insert(name.name, call_location.clone());
1387 }
1388 }
1389
1390 let ty = match (is_future, inferred_type) {
1391 (false, _) => type_,
1392 (true, Some(inferred)) => inferred,
1393 (true, None) => unreachable!("Type checking guarantees the inferred type is present"),
1394 };
1395
1396 if let Err(err) = self.state.symbol_table.insert_variable(
1398 self.scope_state.program_name.unwrap(),
1399 &[name.name],
1400 VariableSymbol { type_: ty.clone(), span, declaration: VariableType::Mut },
1401 ) {
1402 self.state.handler.emit_err(err);
1403 }
1404 }
1405
1406 pub fn check_access_allowed(&mut self, name: &str, finalize_op: bool, span: Span) {
1410 if self.scope_state.variant == Some(Variant::AsyncFunction) && !finalize_op {
1412 self.state.handler.emit_err(TypeCheckerError::invalid_operation_inside_finalize(name, span));
1413 }
1414 else if self.async_block_id.is_some() && !finalize_op {
1416 self.state.handler.emit_err(TypeCheckerError::invalid_operation_inside_async_block(name, span));
1417 }
1418 else if !matches!(self.scope_state.variant, Some(Variant::AsyncFunction) | Some(Variant::Script))
1420 && self.async_block_id.is_none()
1421 && finalize_op
1422 {
1423 self.state.handler.emit_err(TypeCheckerError::invalid_operation_outside_finalize(name, span));
1424 }
1425 }
1426
1427 pub fn is_external_record(&self, ty: &Type) -> bool {
1428 if let Type::Composite(typ) = &ty {
1429 let this_program = self.scope_state.program_name.unwrap();
1430 let program = typ.program.unwrap_or(this_program);
1431 program != this_program
1432 && self
1433 .state
1434 .symbol_table
1435 .lookup_record(&Location::new(program, typ.path.absolute_path().to_vec()))
1436 .is_some()
1437 } else {
1438 false
1439 }
1440 }
1441
1442 pub fn parse_integer_literal<I: FromStrRadix>(&self, raw_string: &str, span: Span, type_string: &str) {
1443 let string = raw_string.replace('_', "");
1444 if I::from_str_by_radix(&string).is_err() {
1445 self.state.handler.emit_err(TypeCheckerError::invalid_int_value(string, type_string, span));
1446 }
1447 }
1448
1449 pub fn emit_inference_failure_error(&self, ty: &mut Type, expr: &Expression) {
1452 self.emit_err(TypeCheckerError::could_not_determine_type(expr.clone(), expr.span()));
1453 *ty = Type::Err;
1454 self.state.type_table.insert(expr.id(), Type::Err);
1455 }
1456
1457 pub fn check_numeric_literal(&self, input: &Literal, ty: &Type) -> bool {
1460 if let Literal { variant: LiteralVariant::Unsuffixed(s), .. } = input {
1461 let span = input.span();
1462 let has_nondecimal_prefix =
1463 |s: &str| ["0x", "0o", "0b", "-0x", "-0o", "-0b"].iter().any(|p| s.starts_with(p));
1464
1465 macro_rules! parse_int {
1466 ($t:ty, $name:expr) => {
1467 self.parse_integer_literal::<$t>(s, span, $name)
1468 };
1469 }
1470
1471 match ty {
1472 Type::Integer(kind) => match kind {
1473 IntegerType::U8 => parse_int!(u8, "u8"),
1474 IntegerType::U16 => parse_int!(u16, "u16"),
1475 IntegerType::U32 => parse_int!(u32, "u32"),
1476 IntegerType::U64 => parse_int!(u64, "u64"),
1477 IntegerType::U128 => parse_int!(u128, "u128"),
1478 IntegerType::I8 => parse_int!(i8, "i8"),
1479 IntegerType::I16 => parse_int!(i16, "i16"),
1480 IntegerType::I32 => parse_int!(i32, "i32"),
1481 IntegerType::I64 => parse_int!(i64, "i64"),
1482 IntegerType::I128 => parse_int!(i128, "i128"),
1483 },
1484 Type::Group => {
1485 if has_nondecimal_prefix(s) {
1486 self.emit_err(TypeCheckerError::hexbin_literal_nonintegers(span));
1488 return false;
1489 } else {
1490 let trimmed = s.trim_start_matches('-').trim_start_matches('0');
1491 if !trimmed.is_empty()
1492 && format!("{trimmed}group")
1493 .parse::<snarkvm::prelude::Group<snarkvm::prelude::TestnetV0>>()
1494 .is_err()
1495 {
1496 self.emit_err(TypeCheckerError::invalid_int_value(trimmed, "group", span));
1497 return false;
1498 }
1499 }
1500 }
1501 Type::Field | Type::Scalar => {
1502 if has_nondecimal_prefix(s) {
1503 self.emit_err(TypeCheckerError::hexbin_literal_nonintegers(span));
1505 return false;
1506 }
1507 }
1508 _ => {
1509 }
1511 }
1512 }
1513 true
1514 }
1515}