Skip to main content

dada_ir_sym/check/
fields.rs

1use dada_ir_ast::diagnostic::{Diagnostic, Err, Errors, Level, Reported};
2
3use crate::{
4    check::{env::Env, runtime::Runtime},
5    ir::{
6        binder::Binder, classes::SymField, populate::variable_decl_requires_default_perm,
7        types::SymTy,
8    },
9};
10
11use super::CheckTyInEnv;
12
13/// Check the type of a field.
14/// The returned type has two binders, the outer binder is the class,
15/// the inner binder is the `self` place.
16pub(crate) fn check_field<'db>(
17    db: &'db dyn crate::Db,
18    field: SymField<'db>,
19) -> Errors<Binder<'db, Binder<'db, SymTy<'db>>>> {
20    Runtime::execute(
21        db,
22        field.name_span(db),
23        "check_field",
24        &[&field],
25        async move |runtime| -> Errors<Binder<'db, Binder<'db, SymTy<'db>>>> {
26            let scope = field.into_scope(db);
27            let mut env = Env::new(runtime, scope);
28
29            let decl = field.source(db).variable(db);
30
31            // In fields, we don't permit something like `x: String`,
32            // user must write `x: my String`.
33            if variable_decl_requires_default_perm(db, decl, &env.scope) {
34                Diagnostic::new(
35                    db,
36                    Level::Error,
37                    decl.base_ty(db).span(db),
38                    "explicit permission required",
39                )
40                .report(db);
41            }
42
43            let ast_base_ty = decl.base_ty(db);
44            let sym_base_ty = ast_base_ty.check_in_env(&mut env).await;
45            let sym_ty = if let Some(ast_perm) = decl.perm(db) {
46                let sym_perm = ast_perm.check_in_env(&mut env).await;
47                SymTy::perm(db, sym_perm, sym_base_ty)
48            } else {
49                sym_base_ty
50            };
51
52            let bound_ty = env.into_scope().into_bound_value(db, sym_ty);
53            Ok(bound_ty)
54        },
55        |bound_ty| bound_ty,
56    )
57}
58
59pub(crate) fn field_err_ty<'db>(
60    db: &'db dyn crate::Db,
61    field: SymField<'db>,
62    reported: Reported,
63) -> Binder<'db, Binder<'db, SymTy<'db>>> {
64    let scope = field.into_scope(db);
65    scope.into_bound_value(db, SymTy::err(db, reported))
66}