1use std::panic::Location;
2
3use crate::{
4 check::{
5 env::Env,
6 member_lookup::MemberLookup,
7 scope::{NameResolution, NameResolutionSym},
8 scope_tree::ScopeTreeNode,
9 },
10 ir::{
11 binder::Binder,
12 classes::SymAggregate,
13 exprs::{
14 SymBinaryOp, SymByteLiteral, SymByteLiteralData, SymExpr, SymExprKind, SymLiteral,
15 SymMatchArm, SymPlaceExpr, SymPlaceExprKind,
16 },
17 functions::{SymFunction, SymInputOutput},
18 types::{SymGenericKind, SymGenericTerm, SymTy, SymTyKind, SymTyName},
19 variables::{FromVar, SymVariable},
20 },
21 prelude::CheckedSignature,
22 well_known,
23};
24use dada_ir_ast::{
25 ast::{
26 AstBinaryOp, AstExpr, AstExprKind, AstGenericTerm, Identifier, LiteralKind, PermissionOp,
27 SpanVec, SpannedBinaryOp, SpannedIdentifier, UnaryOp,
28 },
29 diagnostic::{Diagnostic, Err, Level, Reported},
30 span::{Span, Spanned},
31};
32use dada_parser::prelude::*;
33use dada_util::{FromImpls, boxed_async_fn};
34use serde::Serialize;
35
36use super::{
37 CheckExprInEnv, CheckTyInEnv,
38 debug::TaskDescription,
39 live_places::LivePlaces,
40 report::{
41 AwaitNonFuture, BadSubtermError, InvalidAssignmentType, InvalidReturnValue,
42 NumericTypeExpected, OperatorArgumentsMustHaveSameType, OperatorRequiresNumericType,
43 WhereClauseError,
44 },
45 temporaries::Temporary,
46};
47
48#[derive(Clone, Serialize)]
49pub(crate) struct ExprResult<'db> {
50 pub temporaries: Vec<Temporary<'db>>,
52
53 pub span: Span<'db>,
55
56 pub kind: ExprResultKind<'db>,
59}
60
61#[derive(Clone, Debug, FromImpls, Serialize)]
62pub(crate) enum ExprResultKind<'db> {
63 PlaceExpr(SymPlaceExpr<'db>),
65
66 Expr(SymExpr<'db>),
68
69 #[no_from_impl]
71 Method {
72 self_expr: SymExpr<'db>,
73 id_span: Span<'db>,
74 function: SymFunction<'db>,
75 generics: Option<SpanVec<'db, AstGenericTerm<'db>>>,
76 },
77
78 Other(NameResolution<'db>),
80}
81
82impl<'db> CheckExprInEnv<'db> for AstExpr<'db> {
83 type Output = ExprResult<'db>;
84
85 async fn check_in_env(&self, env: &mut Env<'db>, live_after: LivePlaces) -> Self::Output {
86 check_expr(self, env, live_after).await
87 }
88}
89
90#[boxed_async_fn]
91async fn check_expr<'db>(
92 expr: &AstExpr<'db>,
93 env: &mut Env<'db>,
94 live_after: LivePlaces,
95) -> ExprResult<'db> {
96 env.indent("check_expr", &[expr], async |env| {
97 let db = env.db();
98 let expr_span = expr.span;
99
100 match &*expr.kind {
101 AstExprKind::Literal(literal) => match literal.kind(db) {
102 LiteralKind::Integer => {
103 let ty = env.fresh_ty_inference_var(expr_span);
104 let bits = match str::parse(literal.text(db)) {
105 Ok(v) => v,
106 Err(e) => panic!("error: {e:?}"),
107 };
108 let sym_expr = SymExpr::new(
109 db,
110 expr_span,
111 ty,
112 SymExprKind::Primitive(SymLiteral::Integral { bits }),
113 );
114 env.spawn_require_my_numeric_type(
115 LivePlaces::fixme(),
116 ty,
117 &NumericTypeExpected::new(sym_expr, ty),
118 );
119 ExprResult {
120 temporaries: vec![],
121 span: expr_span,
122 kind: sym_expr.into(),
123 }
124 }
125
126 LiteralKind::String => {
127 let bytes = literal.text(db).as_bytes();
131 let byte_literal_expr = {
132 let pointer_struct = match well_known::pointer_struct(db) {
133 Ok(v) => v,
134 Err(reported) => return ExprResult::err(db, reported),
135 };
136 let data = SymByteLiteralData::new(db, bytes);
137 let byte_literal = SymByteLiteral::new(db, expr_span, data);
138 SymExpr::new(
139 db,
140 expr_span,
141 SymTy::named(db, pointer_struct.into(), vec![SymTy::u8(db).into()]),
142 SymExprKind::ByteLiteral(byte_literal),
143 )
144 };
145
146 let len_literal_expr = {
148 let value = bytes.len() as u64;
149 SymExpr::new(
150 db,
151 expr_span,
152 SymTy::u32(db),
153 SymExprKind::Primitive(SymLiteral::Integral { bits: value }),
154 )
155 };
156
157 let mut temporaries = vec![];
159 let ctor_call_expr = {
160 let literal_fn = match well_known::string_literal_fn(db) {
161 Ok(v) => v,
162 Err(reported) => return ExprResult::err(db, reported),
163 };
164 SymExpr::new(
165 db,
166 expr_span,
167 SymTy::string(db),
168 SymExprKind::Call {
169 function: literal_fn,
170 substitution: vec![],
171 arg_temps: vec![
172 byte_literal_expr.into_temporary_var(db, &mut temporaries),
173 len_literal_expr.into_temporary_var(db, &mut temporaries),
174 ],
175 },
176 )
177 };
178 ExprResult {
179 temporaries,
180 span: expr_span,
181 kind: ctor_call_expr.into(),
182 }
183 }
184
185 LiteralKind::Boolean => {
186 let bits = match &literal.text(db)[..] {
187 "true" => 1,
188 "false" => 0,
189 t => panic!("unrecognized boolean literal {t:?}"),
190 };
191 ExprResult {
192 temporaries: vec![],
193 span: expr_span,
194 kind: SymExpr::new(
195 db,
196 expr_span,
197 SymTy::boolean(db),
198 SymExprKind::Primitive(SymLiteral::Integral { bits }),
199 )
200 .into(),
201 }
202 }
203 },
204
205 AstExprKind::Tuple(span_vec) => {
206 let mut temporaries = vec![];
207 let mut exprs = vec![];
208 for element in &span_vec.values {
209 exprs.push(
210 element
211 .check_in_env(env, LivePlaces::fixme())
212 .await
213 .into_expr(env, &mut temporaries),
214 );
215 }
216
217 let ty = SymTy::new(
218 db,
219 SymTyKind::Named(
220 SymTyName::Tuple { arity: exprs.len() },
221 exprs.iter().map(|e| e.ty(db).into()).collect(),
222 ),
223 );
224
225 ExprResult {
226 temporaries,
227 span: expr_span,
228 kind: ExprResultKind::Expr(SymExpr::new(
229 db,
230 expr_span,
231 ty,
232 SymExprKind::Tuple(exprs),
233 )),
234 }
235 }
236
237 AstExprKind::BinaryOp(span_op, lhs, rhs) => {
238 let span_op: SpannedBinaryOp<'db> = *span_op;
239 match span_op.op {
240 AstBinaryOp::Add | AstBinaryOp::Sub | AstBinaryOp::Mul | AstBinaryOp::Div => {
241 let mut temporaries: Vec<Temporary<'db>> = vec![];
242 let lhs: SymExpr<'db> = lhs
243 .check_in_env(env, LivePlaces::fixme())
244 .await
245 .into_expr(env, &mut temporaries);
246 let rhs: SymExpr<'db> = rhs
247 .check_in_env(env, LivePlaces::fixme())
248 .await
249 .into_expr(env, &mut temporaries);
250
251 env.spawn_require_numeric_type(
255 lhs.ty(db),
256 &OperatorRequiresNumericType::new(span_op, lhs),
257 );
258 env.spawn_require_numeric_type(
259 rhs.ty(db),
260 &OperatorRequiresNumericType::new(span_op, rhs),
261 );
262 env.spawn_if_not_never(&[lhs.ty(db), rhs.ty(db)], async move |env| {
263 env.spawn_require_equal_types(
264 live_after,
265 lhs.ty(db),
266 rhs.ty(db),
267 &OperatorArgumentsMustHaveSameType::new(span_op, lhs, rhs),
268 );
269 });
270
271 ExprResult::from_expr(
277 env.db(),
278 SymExpr::new(
279 db,
280 expr_span,
281 lhs.ty(db),
282 SymExprKind::BinaryOp(
283 SymBinaryOp::try_from(span_op.op).expect("invalid binary op"),
284 lhs,
285 rhs,
286 ),
287 ),
288 temporaries,
289 )
290 }
291
292 AstBinaryOp::AndAnd => {
293 let mut temporaries: Vec<Temporary<'db>> = vec![];
294 let lhs: SymExpr<'db> = lhs
295 .check_in_env(env, LivePlaces::fixme())
296 .await
297 .into_expr(env, &mut temporaries);
298 let rhs: SymExpr<'db> = rhs
299 .check_in_env(env, live_after)
300 .await
301 .into_expr(env, &mut temporaries);
302 env.require_expr_has_bool_ty(LivePlaces::fixme(), lhs);
303 env.require_expr_has_bool_ty(live_after, rhs);
304
305 ExprResult::from_expr(
308 env.db(),
309 SymExpr::if_then_else(
310 db,
311 expr_span,
312 lhs,
313 SymExpr::if_then_else(
314 db,
315 expr_span,
316 rhs,
317 SymExpr::true_literal(db, expr_span),
318 SymExpr::false_literal(db, expr_span),
319 ),
320 SymExpr::false_literal(db, expr_span),
321 ),
322 temporaries,
323 )
324 }
325
326 AstBinaryOp::OrOr => {
327 let mut temporaries: Vec<Temporary<'db>> = vec![];
328 let lhs: SymExpr<'db> = lhs
329 .check_in_env(env, LivePlaces::fixme())
330 .await
331 .into_expr(env, &mut temporaries);
332 let rhs: SymExpr<'db> = rhs
333 .check_in_env(env, live_after)
334 .await
335 .into_expr(env, &mut temporaries);
336
337 env.require_expr_has_bool_ty(LivePlaces::fixme(), lhs);
338 env.require_expr_has_bool_ty(live_after, rhs);
339
340 ExprResult::from_expr(
343 env.db(),
344 SymExpr::if_then_else(
345 db,
346 expr_span,
347 lhs,
348 SymExpr::true_literal(db, expr_span),
349 SymExpr::if_then_else(
350 db,
351 expr_span,
352 rhs,
353 SymExpr::true_literal(db, expr_span),
354 SymExpr::false_literal(db, expr_span),
355 ),
356 ),
357 temporaries,
358 )
359 }
360
361 AstBinaryOp::GreaterThan
362 | AstBinaryOp::LessThan
363 | AstBinaryOp::GreaterEqual
364 | AstBinaryOp::LessEqual
365 | AstBinaryOp::EqualEqual => {
366 let mut temporaries: Vec<Temporary<'db>> = vec![];
367 let lhs: SymExpr<'db> = lhs
368 .check_in_env(env, LivePlaces::fixme())
369 .await
370 .into_expr(env, &mut temporaries);
371 let rhs: SymExpr<'db> = rhs
372 .check_in_env(env, LivePlaces::fixme())
373 .await
374 .into_expr(env, &mut temporaries);
375
376 env.spawn_require_numeric_type(
380 lhs.ty(db),
381 &OperatorRequiresNumericType::new(span_op, lhs),
382 );
383 env.spawn_require_numeric_type(
384 rhs.ty(db),
385 &OperatorRequiresNumericType::new(span_op, rhs),
386 );
387 env.spawn_if_not_never(&[lhs.ty(db), rhs.ty(db)], async move |env| {
388 env.spawn_require_equal_types(
389 LivePlaces::fixme(),
390 lhs.ty(db),
391 rhs.ty(db),
392 &OperatorArgumentsMustHaveSameType::new(span_op, lhs, rhs),
393 );
394 });
395
396 ExprResult::from_expr(
402 env.db(),
403 SymExpr::new(
404 db,
405 expr_span,
406 SymTy::boolean(db),
407 SymExprKind::BinaryOp(
408 SymBinaryOp::try_from(span_op.op).expect("invalid binary op"),
409 lhs,
410 rhs,
411 ),
412 ),
413 temporaries,
414 )
415 }
416
417 AstBinaryOp::Assign => {
418 let mut temporaries: Vec<Temporary<'db>> = vec![];
419 let place: SymPlaceExpr<'db> = lhs
420 .check_in_env(env, LivePlaces::fixme())
421 .await
422 .into_place_expr(env, &mut temporaries);
423 let value: SymExpr<'db> = rhs
424 .check_in_env(env, LivePlaces::fixme())
425 .await
426 .into_expr(env, &mut temporaries);
427
428 env.spawn_require_assignable_type(
432 LivePlaces::fixme(),
433 value.ty(db),
434 place.ty(db),
435 &InvalidAssignmentType::new(place, value),
436 );
437
438 ExprResult::from_expr(
439 env.db(),
440 SymExpr::new(
441 db,
442 expr_span,
443 SymTy::unit(db),
444 SymExprKind::Assign { place, value },
445 ),
446 temporaries,
447 )
448 }
449 }
450 }
451
452 AstExprKind::Id(SpannedIdentifier { span: id_span, id }) => {
453 match env.scope.resolve_name(db, *id, *id_span) {
454 Err(reported) => ExprResult::err(db, reported),
455 Ok(res) => ExprResult::from_name_resolution(env, res, expr_span).await,
456 }
457 }
458
459 AstExprKind::DotId(owner, id) => {
460 let mut owner_result = owner.check_in_env(env, live_after).await;
461 match owner_result.kind {
462 ExprResultKind::PlaceExpr(_) | ExprResultKind::Expr(_) => {
463 MemberLookup::new(env)
464 .lookup_member(owner_result, *id)
465 .await
466 }
467
468 ExprResultKind::Other(name_resolution) => {
469 match name_resolution.resolve_relative_id(db, *id) {
470 Err(reported) => ExprResult::err(db, reported),
472
473 Ok(Ok(r)) => ExprResult::from_name_resolution(env, r, expr_span).await,
475
476 Ok(Err(name_resolution)) => {
478 owner_result.kind = name_resolution.into();
479 MemberLookup::new(env)
480 .lookup_member(owner_result, *id)
481 .await
482 }
483 }
484 }
485
486 ExprResultKind::Method {
487 self_expr: owner,
488 function: method,
489 ..
490 } => ExprResult::err(
491 db,
492 report_missing_call_to_method(db, owner.span(db), method),
493 ),
494 }
495 }
496
497 AstExprKind::SquareBracketOp(owner, square_bracket_args) => {
498 let owner_result = owner.check_in_env(env, LivePlaces::fixme()).await;
499 match owner_result.kind {
500 ExprResultKind::Method {
501 self_expr: owner,
502 function: method,
503 generics: None,
504 id_span,
505 } => {
506 let ast_terms = square_bracket_args.parse_as_generics(db);
507
508 ExprResult {
509 kind: ExprResultKind::Method {
510 self_expr: owner,
511 function: method,
512 generics: Some(ast_terms),
513 id_span,
514 },
515 ..owner_result
516 }
517 }
518
519 ExprResultKind::PlaceExpr(_) | ExprResultKind::Expr(_) => ExprResult::err(
520 db,
521 report_not_implemented(db, expr_span, "indexing expressions"),
522 ),
523
524 ExprResultKind::Method {
529 self_expr: owner,
530 function: method,
531 generics: Some(_),
532 ..
533 } => ExprResult::err(
534 db,
535 report_missing_call_to_method(db, owner.span(db), method),
536 ),
537
538 ExprResultKind::Other(name_resolution) => {
539 let generics = square_bracket_args.parse_as_generics(db);
540 match name_resolution
541 .resolve_relative_generic_args(env, &generics)
542 .await
543 {
544 Ok(name_resolution) => ExprResult {
545 temporaries: owner_result.temporaries,
546 span: expr_span,
547 kind: name_resolution.into(),
548 },
549 Err(r) => ExprResult::err(db, r),
550 }
551 }
552 }
553 }
554
555 AstExprKind::ParenthesisOp(owner, ast_args) => {
556 let owner_result = owner.check_in_env(env, live_after).await;
557 match owner_result {
558 ExprResult {
559 temporaries,
560 span: expr_span,
561 kind:
562 ExprResultKind::Method {
563 self_expr,
564 id_span,
565 function,
566 generics,
567 },
568 } => {
569 check_method_call(
570 env,
571 live_after,
572 id_span,
573 expr_span,
574 function,
575 Some(self_expr),
576 ast_args,
577 generics,
578 temporaries,
579 )
580 .await
581 }
582
583 ExprResult {
584 temporaries,
585 span: function_span,
586 kind:
587 ExprResultKind::Other(NameResolution {
588 generics,
589 sym: NameResolutionSym::SymFunction(sym),
590 ..
591 }),
592 } => {
593 check_function_call(
594 env,
595 live_after,
596 function_span,
597 expr_span,
598 sym,
599 ast_args,
600 generics,
601 temporaries,
602 )
603 .await
604 }
605
606 ExprResult {
609 temporaries,
610 span: class_span,
611 kind:
612 ExprResultKind::Other(
613 name_resolution @ NameResolution {
614 sym: NameResolutionSym::SymAggregate(class_sym),
615 ..
616 },
617 ),
618 } => {
619 check_class_call(
620 env,
621 live_after,
622 class_span,
623 expr_span,
624 name_resolution,
625 class_sym,
626 ast_args,
627 temporaries,
628 )
629 .await
630 }
631
632 ExprResult {
633 span: owner_span, ..
634 } => {
635 ExprResult::err(db, report_not_callable(db, owner_span))
637 }
638 }
639 }
640
641 AstExprKind::Constructor(_ast_path, _span_vec) => todo!(),
642 AstExprKind::Return(ast_expr) => {
643 let mut temporaries = vec![];
644
645 let return_expr = if let Some(ast_expr) = ast_expr {
646 ast_expr
647 .check_in_env(env, LivePlaces::none(env))
648 .await
649 .into_expr(env, &mut temporaries)
650 } else {
651 SymExpr::new(db, expr_span, SymTy::unit(db), SymExprKind::Tuple(vec![]))
653 };
654
655 let Some(expected_return_ty) = env.return_ty else {
656 return ExprResult::err(
657 db,
658 env.report(
659 Diagnostic::error(
660 db,
661 expr_span,
662 "unexpected `return` statement".to_string(),
663 )
664 .label(
665 db,
666 Level::Error,
667 expr_span,
668 "I did not expect to see a `return` statement here".to_string(),
669 ),
670 ),
671 );
672 };
673
674 env.spawn_require_assignable_type(
675 LivePlaces::none(env),
676 return_expr.ty(db),
677 expected_return_ty,
678 &InvalidReturnValue::new(return_expr, expected_return_ty),
679 );
680
681 ExprResult {
682 temporaries,
683 span: expr_span,
684 kind: SymExpr::new(
685 db,
686 expr_span,
687 SymTy::never(db),
688 SymExprKind::Return(return_expr),
689 )
690 .into(),
691 }
692 }
693
694 AstExprKind::Await {
695 future,
696 await_keyword,
697 } => {
698 let await_span = *await_keyword;
699
700 let mut temporaries = vec![];
701
702 let future_expr = future
703 .check_in_env(env, live_after)
704 .await
705 .into_expr(env, &mut temporaries);
706 let future_ty = future_expr.ty(db);
707
708 let awaited_ty = env.fresh_ty_inference_var(await_span);
709
710 env.spawn_require_future_type(
711 live_after,
712 future_ty,
713 awaited_ty,
714 &AwaitNonFuture::new(await_span, future_expr),
715 );
716
717 ExprResult {
718 temporaries,
719 span: expr_span,
720 kind: SymExpr::new(
721 db,
722 expr_span,
723 awaited_ty,
724 SymExprKind::Await {
725 future: future_expr,
726 await_keyword: await_span,
727 },
728 )
729 .into(),
730 }
731 }
732 AstExprKind::UnaryOp(spanned_unary_op, ast_expr) => match spanned_unary_op.op {
733 UnaryOp::Not => {
734 let mut temporaries = vec![];
735 let operand = ast_expr
736 .check_in_env(env, live_after)
737 .await
738 .into_expr(env, &mut temporaries);
739 env.require_expr_has_bool_ty(live_after, operand);
740
741 ExprResult {
742 temporaries,
743 span: expr_span,
744 kind: SymExpr::new(
745 db,
746 expr_span,
747 SymTy::boolean(db),
748 SymExprKind::Not {
749 operand,
750 op_span: spanned_unary_op.span,
751 },
752 )
753 .into(),
754 }
755 }
756 UnaryOp::Negate => todo!(),
757 },
758
759 AstExprKind::Block(ast_block) => ExprResult {
760 temporaries: vec![],
761 span: expr_span,
762 kind: ast_block.check_in_env(env, live_after).await.into(),
763 },
764
765 AstExprKind::If(ast_arms) => {
766 let mut arms = vec![];
767 let mut has_else = false;
768 for arm in ast_arms {
769 let condition = if let Some(c) = &arm.condition {
770 let expr = c
771 .check_in_env(env, LivePlaces::fixme())
772 .await
773 .into_expr_with_enclosed_temporaries(env);
774 env.require_expr_has_bool_ty(LivePlaces::fixme(), expr);
775 Some(expr)
776 } else {
777 has_else = true;
778 None
779 };
780
781 let body = arm.result.check_in_env(env, live_after).await;
782
783 arms.push(SymMatchArm { condition, body });
784 }
785
786 let if_ty = if !has_else {
787 SymTy::unit(db)
788 } else {
789 env.fresh_ty_inference_var(expr_span)
790 };
791
792 for arm in &arms {
793 env.spawn_require_assignable_type(
794 live_after,
795 arm.body.ty(db),
796 if_ty,
797 &BadSubtermError::new(arm.body.span(db), arm.body.ty(db), if_ty),
798 );
799 }
800
801 ExprResult {
802 temporaries: vec![],
803 span: expr_span,
804 kind: SymExpr::new(db, expr_span, if_ty, SymExprKind::Match { arms }).into(),
805 }
806 }
807
808 AstExprKind::PermissionOp { value, op } => {
809 let mut temporaries = vec![];
810 let value_result = value.check_in_env(env, live_after).await;
811 let place_expr = value_result.into_place_expr(env, &mut temporaries);
812 let sym_place = place_expr.into_sym_place(db);
813 ExprResult {
814 temporaries,
815 span: expr_span,
816 kind: SymExpr::new(
817 db,
818 expr_span,
819 match op {
820 PermissionOp::Mutate => place_expr.ty(db).mutable(db, sym_place),
821 PermissionOp::Reference => place_expr.ty(db).referenced(db, sym_place),
822 PermissionOp::Give => place_expr.ty(db),
823 PermissionOp::Share => place_expr.ty(db).shared(db),
824 },
825 SymExprKind::PermissionOp(*op, place_expr),
826 )
827 .into(),
828 }
829 }
830 }
831 })
832 .await
833}
834
835#[boxed_async_fn]
836async fn check_class_call<'db>(
837 env: &mut Env<'db>,
838 live_after: LivePlaces,
839 class_span: Span<'db>,
840 expr_span: Span<'db>,
841 name_resolution: NameResolution<'db>,
842 class_sym: SymAggregate<'db>,
843 ast_args: &SpanVec<'db, AstExpr<'db>>,
844 temporaries: Vec<Temporary<'db>>,
845) -> ExprResult<'db> {
846 let db = env.db();
847
848 let new_ident = SpannedIdentifier {
849 span: class_span,
850 id: Identifier::new_ident(db),
851 };
852
853 let (generics, new_function) = match name_resolution.resolve_relative_id(db, new_ident) {
854 Ok(Ok(NameResolution {
855 generics,
856 sym: NameResolutionSym::SymFunction(m),
857 })) => (generics, m),
858 Ok(r) => return ExprResult::err(db, report_no_new_method(db, class_span, class_sym, r)),
859 Err(reported) => return ExprResult::err(db, reported),
860 };
861
862 check_function_call(
863 env,
864 live_after,
865 class_span,
866 expr_span,
867 new_function,
868 ast_args,
869 generics,
870 temporaries,
871 )
872 .await
873}
874
875fn report_no_new_method<'db>(
876 db: &'db dyn crate::Db,
877 class_span: Span<'db>,
878 class_sym: SymAggregate<'db>,
879 resolution: Result<NameResolution<'db>, NameResolution<'db>>,
880) -> Reported {
881 let mut diag = Diagnostic::error(
882 db,
883 class_span,
884 format!("the class `{class_sym}` has no `new` method"),
885 )
886 .label(
887 db,
888 Level::Error,
889 class_span,
890 format!("I could not find a `new` method on the class `{class_sym}`"),
891 );
892
893 match resolution {
894 Ok(name_resolution) => {
895 diag = diag.child(
896 Diagnostic::new(
897 db,
898 Level::Note,
899 class_sym.name_span(db),
900 "calling a class is equivalent to calling `new`, but `new` is not a method"
901 .to_string(),
902 )
903 .label(
904 db,
905 Level::Note,
906 name_resolution.span(db).unwrap(),
907 format!(
908 "I found a class member named `new` but it is {}, not a method",
909 name_resolution.categorize(db)
910 ),
911 ),
912 );
913 }
914 Err(_) => {
915 diag = diag.child(
916 Diagnostic::new(
917 db,
918 Level::Note,
919 class_sym.name_span(db),
920 format!(
921 "calling a class is equivalent to calling `new`, but `{class_sym}` does not define a `new` method"
922 ),
923 )
924 .label(
925 db,
926 Level::Note,
927 class_sym.name_span(db),
928 "I could not find any class member named `new`".to_string(),
929 ),
930 );
931 }
932 }
933
934 diag.report(db)
935}
936
937#[boxed_async_fn]
938async fn check_function_call<'db>(
939 env: &mut Env<'db>,
940 live_after: LivePlaces,
941 function_span: Span<'db>,
942 expr_span: Span<'db>,
943 function: SymFunction<'db>,
944 ast_args: &SpanVec<'db, AstExpr<'db>>,
945 generics: Vec<SymGenericTerm<'db>>,
946 temporaries: Vec<Temporary<'db>>,
947) -> ExprResult<'db> {
948 let db = env.db();
949
950 env.log("check_function_call", &[&function]);
951 env.log("generics", &[&generics]);
952
953 let signature = match function.checked_signature(db) {
955 Ok(signature) => signature,
956 Err(reported) => {
957 for ast_arg in ast_args {
958 let _ = ast_arg.check_in_env(env, LivePlaces::fixme()).await;
959 }
960 return ExprResult::err(db, reported);
961 }
962 };
963 let input_output = signature.input_output(db);
964
965 env.log("input_output", &[&input_output]);
966
967 let expected_generics = function.transitive_generic_parameters(db);
969 env.log("expected_generics", &[&expected_generics]);
970 let mut substitution = generics.clone();
971 substitution.extend(
972 expected_generics[generics.len()..]
973 .iter()
974 .map(|&var| env.fresh_inference_var_term(var.kind(db), function_span)),
975 );
976
977 check_call_common(
978 env,
979 live_after,
980 function,
981 expr_span,
982 function_span,
983 input_output,
984 substitution,
985 ast_args,
986 None,
987 temporaries,
988 )
989 .await
990}
991
992#[allow(clippy::too_many_arguments)]
996#[boxed_async_fn]
997async fn check_method_call<'db>(
998 env: &mut Env<'db>,
999 live_after: LivePlaces,
1000 id_span: Span<'db>,
1001 expr_span: Span<'db>,
1002 function: SymFunction<'db>,
1003 self_expr: Option<SymExpr<'db>>,
1004 ast_args: &[AstExpr<'db>],
1005 generics: Option<SpanVec<'db, AstGenericTerm<'db>>>,
1006 temporaries: Vec<Temporary<'db>>,
1007) -> ExprResult<'db> {
1008 let db = env.db();
1009
1010 let signature = match function.checked_signature(db) {
1012 Ok(signature) => signature,
1013 Err(reported) => {
1014 for &generic in generics.iter().flatten() {
1015 let _ = generic.check_in_env(env).await;
1016 }
1017 for ast_arg in ast_args {
1018 let _ = ast_arg.check_in_env(env, LivePlaces::fixme()).await;
1019 }
1020 return ExprResult::err(db, reported);
1021 }
1022 };
1023 let input_output = signature.input_output(db);
1024
1025 let substitution = match generics {
1027 None => {
1028 env.existential_substitution(id_span, &input_output.variables)
1030 }
1031
1032 Some(generics) => {
1033 let function_generics = &signature.symbols(db).generic_variables;
1041 assert!(input_output.variables.ends_with(function_generics));
1042 let outer_variables =
1043 &input_output.variables[0..input_output.variables.len() - function_generics.len()];
1044 let mut substitution: Vec<SymGenericTerm<'_>> =
1045 env.existential_substitution(id_span, outer_variables);
1046
1047 if function_generics.len() != generics.len() {
1049 return ExprResult::err(
1050 db,
1051 env.report(
1052 Diagnostic::error(
1053 db,
1054 id_span,
1055 format!(
1056 "expected {expected} generic arguments, but found {found}",
1057 expected = function_generics.len(),
1058 found = generics.len()
1059 ),
1060 )
1061 .label(
1062 db,
1063 Level::Error,
1064 id_span,
1065 format!(
1066 "{found} generic arguments were provided",
1067 found = generics.len()
1068 ),
1069 )
1070 .label(
1071 db,
1072 Level::Error,
1073 function.name_span(db),
1074 format!(
1075 "the function `{name}` is declared with {expected} generic arguments",
1076 name = function.name(db),
1077 expected = function_generics.len(),
1078 ),
1079 ),
1080 ),
1081 );
1082 }
1083
1084 for (&ast_generic_term, &var) in generics.iter().zip(function_generics.iter()) {
1087 let generic_term = ast_generic_term.check_in_env(env).await;
1088 if !generic_term.has_kind(db, var.kind(db)) {
1089 return ExprResult::err(
1090 db,
1091 env.report(
1092 Diagnostic::error(
1093 db,
1094 ast_generic_term.span(db),
1095 format!(
1096 "expected `{expected_kind}`, found `{found_kind}`",
1097 expected_kind = var.kind(db),
1098 found_kind = generic_term.kind().unwrap(),
1099 ),
1100 )
1101 .label(
1102 db,
1103 Level::Error,
1104 id_span,
1105 format!(
1106 "this is a `{found_kind}`",
1107 found_kind = generic_term.kind().unwrap(),
1108 ),
1109 )
1110 .label(
1111 db,
1112 Level::Info,
1113 var.span(db),
1114 format!(
1115 "I expected to find a `{expected_kind}`",
1116 expected_kind = var.kind(db),
1117 ),
1118 ),
1119 ),
1120 );
1121 }
1122 substitution.push(generic_term);
1123 }
1124
1125 substitution
1126 }
1127 };
1128
1129 check_call_common(
1130 env,
1131 live_after,
1132 function,
1133 expr_span,
1134 id_span,
1135 input_output,
1136 substitution,
1137 ast_args,
1138 self_expr,
1139 temporaries,
1140 )
1141 .await
1142}
1143
1144#[allow(clippy::too_many_arguments)]
1145#[boxed_async_fn]
1146async fn check_call_common<'db>(
1147 env: &mut Env<'db>,
1148 _live_after: LivePlaces,
1149 function: SymFunction<'db>,
1150 expr_span: Span<'db>,
1151 callee_span: Span<'db>,
1152 input_output: &Binder<'db, Binder<'db, SymInputOutput<'db>>>,
1153 substitution: Vec<SymGenericTerm<'db>>,
1154 ast_args: &[AstExpr<'db>],
1155 self_expr: Option<SymExpr<'db>>,
1156 mut temporaries: Vec<Temporary<'db>>,
1157) -> ExprResult<'db> {
1158 let db = env.db();
1159
1160 env.log("check_call_common", &[]);
1161 env.log("substitution", &[&substitution]);
1162
1163 let input_output = input_output.substitute(db, &substitution);
1165
1166 let self_args: usize = self_expr.is_some() as usize;
1168 let expected_inputs = input_output.bound_value.input_tys.len();
1169 let found_inputs = self_args + ast_args.len();
1170 if found_inputs != expected_inputs {
1171 let function_name = function.name(db);
1172 return ExprResult::err(
1173 db,
1174 env.report(
1175 Diagnostic::error(
1176 db,
1177 callee_span,
1178 format!("expected {expected_inputs} arguments, found {found_inputs}"),
1179 )
1180 .label(
1181 db,
1182 Level::Error,
1183 callee_span,
1184 format!("I expected `{function_name}` to take {expected_inputs} arguments but I found {found_inputs}",),
1185 )
1186 .label(
1187 db,
1188 Level::Info,
1189 function.name_span(db),
1190 format!("`{function_name}` defined here"),
1191 )
1192 ),
1193 );
1194 }
1195
1196 let arg_temp_span = |i: usize| {
1198 if i < self_args {
1199 self_expr.unwrap().span(db)
1200 } else {
1201 ast_args
1202 .get(i - self_args)
1203 .map(|a| a.span)
1204 .unwrap_or(callee_span)
1205 }
1206 };
1207 let arg_temp_symbols = (0..expected_inputs)
1208 .map(|i| SymVariable::new(db, SymGenericKind::Place, None, arg_temp_span(i)))
1209 .collect::<Vec<_>>();
1210 let arg_temp_terms = arg_temp_symbols
1211 .iter()
1212 .map(|&sym| SymGenericTerm::var(db, sym))
1213 .collect::<Vec<_>>();
1214
1215 let input_output: SymInputOutput<'_> = input_output.substitute(db, &arg_temp_terms);
1217
1218 env.log("arg_temp_symbols", &[&arg_temp_symbols]);
1219 env.log("arg_temp_terms", &[&arg_temp_terms]);
1220 env.log("input_output", &[&input_output]);
1221
1222 let check_arg = async |i: usize| -> ExprResult<'db> {
1224 let mut env = env.fork(|log| log.spawn(Location::caller(), TaskDescription::CheckArg(i)));
1225 let mut arg_temporaries = vec![];
1226 let expr = if i < self_args {
1227 self_expr.unwrap()
1228 } else {
1229 let ast_arg = &ast_args[i - self_args];
1230 ast_arg
1231 .check_in_env(&mut env, LivePlaces::fixme())
1232 .await
1233 .into_expr(&mut env, &mut arg_temporaries)
1234 };
1235 env.spawn_require_assignable_type(
1236 LivePlaces::fixme(),
1237 expr.ty(db),
1238 input_output.input_tys[i],
1239 &BadSubtermError::new(expr.span(db), expr.ty(db), input_output.input_tys[i]),
1240 );
1241 ExprResult::from_expr(env.db(), expr, arg_temporaries)
1242 };
1243
1244 for where_clause in input_output.where_clauses {
1246 env.spawn_require_where_clause(
1247 where_clause,
1248 &WhereClauseError::new(callee_span, where_clause),
1249 );
1250 }
1251
1252 let mut arg_exprs = vec![];
1254 arg_exprs.extend(self_expr);
1255 for arg_result in futures::future::join_all((0..found_inputs).map(check_arg)).await {
1256 arg_exprs.push(arg_result.into_expr(env, &mut temporaries));
1257 }
1258
1259 let mut call_expr = SymExpr::new(
1266 db,
1267 expr_span,
1268 input_output.output_ty,
1269 SymExprKind::Call {
1270 function,
1271 substitution,
1272 arg_temps: arg_temp_symbols.clone(),
1273 },
1274 );
1275 for (arg_temp_symbol, arg_expr) in arg_temp_symbols
1276 .into_iter()
1277 .rev()
1278 .zip(arg_exprs.into_iter().rev())
1279 {
1280 call_expr = SymExpr::new(
1281 db,
1282 call_expr.span(db),
1283 call_expr.ty(db),
1284 SymExprKind::LetIn {
1285 lv: arg_temp_symbol,
1286 ty: arg_expr.ty(db),
1287 initializer: Some(arg_expr),
1288 body: call_expr,
1289 },
1290 );
1291 }
1292
1293 ExprResult::from_expr(env.db(), call_expr, temporaries)
1295}
1296
1297impl<'db> Err<'db> for ExprResult<'db> {
1298 fn err(db: &'db dyn dada_ir_ast::Db, r: Reported) -> Self {
1299 Self {
1300 temporaries: vec![],
1301 span: r.span(db),
1302 kind: ExprResultKind::PlaceExpr(SymPlaceExpr::err(db, r)),
1303 }
1304 }
1305}
1306
1307impl<'db> ExprResult<'db> {
1308 pub async fn from_name_resolution(
1310 env: &mut Env<'db>,
1311 res: NameResolution<'db>,
1312 span: Span<'db>,
1313 ) -> Self {
1314 let db = env.db();
1315 match res.sym {
1316 NameResolutionSym::SymVariable(var) if var.kind(db) == SymGenericKind::Place => {
1317 let ty = env.variable_ty(var).await;
1318 let place_expr = SymPlaceExpr::new(db, span, ty, SymPlaceExprKind::Var(var));
1319 Self {
1320 temporaries: vec![],
1321 span,
1322 kind: ExprResultKind::PlaceExpr(place_expr),
1323 }
1324 }
1325
1326 NameResolutionSym::SymFunction(_)
1328 | NameResolutionSym::SymModule(_)
1329 | NameResolutionSym::SymAggregate(_)
1330 | NameResolutionSym::SymPrimitive(_)
1331 | NameResolutionSym::SymVariable(..) => Self {
1332 temporaries: vec![],
1333 span,
1334 kind: ExprResultKind::Other(res),
1335 },
1336 }
1337 }
1338
1339 pub fn from_place_expr(
1340 db: &'db dyn crate::Db,
1341 expr: SymPlaceExpr<'db>,
1342 temporaries: Vec<Temporary<'db>>,
1343 ) -> Self {
1344 Self {
1345 temporaries,
1346 span: expr.span(db),
1347 kind: ExprResultKind::PlaceExpr(expr),
1348 }
1349 }
1350
1351 pub fn from_expr(
1352 db: &'db dyn crate::Db,
1353 expr: SymExpr<'db>,
1354 temporaries: Vec<Temporary<'db>>,
1355 ) -> Self {
1356 Self {
1357 temporaries,
1358 span: expr.span(db),
1359 kind: ExprResultKind::Expr(expr),
1360 }
1361 }
1362
1363 pub fn into_expr_with_enclosed_temporaries(self, env: &mut Env<'db>) -> SymExpr<'db> {
1365 let db = env.db();
1366 let mut temporaries = vec![];
1367 let mut expr = self.into_expr(env, &mut temporaries);
1368 for temporary in temporaries.into_iter().rev() {
1369 expr = SymExpr::new(
1370 db,
1371 expr.span(db),
1372 expr.ty(db),
1373 SymExprKind::LetIn {
1374 lv: temporary.lv,
1375 ty: temporary.ty,
1376 initializer: temporary.initializer,
1377 body: expr,
1378 },
1379 );
1380 }
1381
1382 expr
1383 }
1384
1385 pub fn ty(&self, env: &mut Env<'db>) -> SymTy<'db> {
1388 let db = env.db();
1389 match &self.kind {
1390 &ExprResultKind::PlaceExpr(place_expr) => place_expr.ty(db),
1391 &ExprResultKind::Expr(expr) => expr.ty(db),
1392 ExprResultKind::Other(name_resolution) => {
1393 SymTy::err(db, report_non_expr(db, self.span, name_resolution))
1394 }
1395 &ExprResultKind::Method {
1396 self_expr: owner,
1397 function: method,
1398 ..
1399 } => SymTy::err(
1400 db,
1401 report_missing_call_to_method(db, owner.span(db), method),
1402 ),
1403 }
1404 }
1405
1406 pub fn into_place_expr(
1407 self,
1408 env: &mut Env<'db>,
1409 temporaries: &mut Vec<Temporary<'db>>,
1410 ) -> SymPlaceExpr<'db> {
1411 let db = env.db();
1412 temporaries.extend(self.temporaries);
1413 match self.kind {
1414 ExprResultKind::PlaceExpr(place_expr) => place_expr,
1415
1416 ExprResultKind::Expr(expr) => expr.into_temporary(db, temporaries),
1418
1419 ExprResultKind::Other(name_resolution) => {
1420 let reported = report_non_expr(db, self.span, &name_resolution);
1421 SymPlaceExpr::err(db, reported)
1422 }
1423
1424 ExprResultKind::Method {
1425 self_expr: owner,
1426 function: method,
1427 ..
1428 } => SymPlaceExpr::err(
1429 db,
1430 report_missing_call_to_method(db, owner.span(db), method),
1431 ),
1432 }
1433 }
1434
1435 pub fn into_expr(
1436 self,
1437 env: &mut Env<'db>,
1438 temporaries: &mut Vec<Temporary<'db>>,
1439 ) -> SymExpr<'db> {
1440 let db = env.db();
1441 temporaries.extend(self.temporaries);
1442 match self.kind {
1443 ExprResultKind::Expr(expr) => expr,
1444 ExprResultKind::PlaceExpr(place_expr) => {
1445 let sym_place = place_expr.into_sym_place(db);
1446 SymExpr::new(
1447 db,
1448 place_expr.span(db),
1449 place_expr.ty(db).referenced(db, sym_place),
1450 SymExprKind::PermissionOp(PermissionOp::Reference, place_expr),
1451 )
1452 }
1453
1454 ExprResultKind::Other(name_resolution) => {
1455 SymExpr::err(db, report_non_expr(db, self.span, &name_resolution))
1456 }
1457 ExprResultKind::Method {
1458 self_expr: owner,
1459 function: method,
1460 ..
1461 } => SymExpr::err(
1462 db,
1463 report_missing_call_to_method(db, owner.span(db), method),
1464 ),
1465 }
1466 }
1467}
1468
1469fn report_not_implemented<'db>(db: &'db dyn crate::Db, span: Span<'db>, what: &str) -> Reported {
1470 Diagnostic::error(db, span, "not implemented yet :(".to_string())
1471 .label(
1472 db,
1473 Level::Error,
1474 span,
1475 format!("sorry, but {what} have not been implemented yet :(",),
1476 )
1477 .report(db)
1478}
1479
1480fn report_non_expr<'db>(
1481 db: &'db dyn crate::Db,
1482 owner_span: Span<'db>,
1483 name_resolution: &NameResolution<'db>,
1484) -> Reported {
1485 Diagnostic::error(db, owner_span, "expected an expression".to_string())
1486 .label(
1487 db,
1488 Level::Error,
1489 owner_span,
1490 format!(
1491 "I expected to find an expression but I found {}",
1492 name_resolution.categorize(db),
1493 ),
1494 )
1495 .report(db)
1496}
1497
1498fn report_missing_call_to_method<'db>(
1499 db: &'db dyn crate::Db,
1500 owner_span: Span<'db>,
1501 method: SymFunction<'db>,
1502) -> Reported {
1503 Diagnostic::error(db, owner_span, "missing call to method".to_string())
1504 .label(
1505 db,
1506 Level::Error,
1507 owner_span,
1508 format!(
1509 "`{}` is a method but you don't appear to be calling it",
1510 method.name(db),
1511 ),
1512 )
1513 .label(db, Level::Help, owner_span.at_end(), "maybe add `()` here?")
1514 .report(db)
1515}
1516
1517fn report_not_callable<'db>(db: &'db dyn crate::Db, owner_span: Span<'db>) -> Reported {
1518 Diagnostic::error(db, owner_span, "not callable".to_string())
1519 .label(
1520 db,
1521 Level::Error,
1522 owner_span,
1523 "this is not something you can call".to_string(),
1524 )
1525 .report(db)
1526}