erg_compiler/
declare.rs

1use std::mem;
2
3use erg_common::consts::PYTHON_MODE;
4use erg_common::error::Location;
5use erg_common::pathutil::NormalizedPathBuf;
6use erg_common::traits::{Locational, Runnable, Stream};
7use erg_common::{fn_name, log, set, Str, Triple};
8
9use erg_parser::ast::{self, AscriptionKind, DefId, Identifier, TypeAppArgsKind, VarName, AST};
10use erg_parser::build_ast::ASTBuildable;
11use erg_parser::desugar::Desugarer;
12
13use crate::context::instantiate::TyVarCache;
14use crate::context::{ClassDefType, Context, MethodContext, MethodPair, TraitImpl};
15use crate::lower::GenericASTLowerer;
16use crate::ty::constructors::{list_t, mono, mono_q, mono_q_tp, poly, v_enum};
17use crate::ty::free::{Constraint, HasLevel};
18use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
19use crate::ty::{HasType, TyParam, Type, Visibility};
20
21use crate::compile::AccessKind;
22use crate::error::{LowerError, LowerErrors, LowerResult};
23use crate::hir::HIR;
24use crate::varinfo::{Mutability, VarInfo, VarKind};
25use crate::{feature_error, hir};
26
27impl<A: ASTBuildable> GenericASTLowerer<A> {
28    fn declare_var(
29        &mut self,
30        sig: ast::VarSignature,
31        mut body: ast::DefBody,
32    ) -> LowerResult<hir::Def> {
33        log!(info "entered {}({sig})", fn_name!());
34        if body.block.len() > 1 {
35            return Err(LowerErrors::from(LowerError::declare_error(
36                self.cfg().input.clone(),
37                line!() as usize,
38                body.block.loc(),
39                self.module.context.caused_by(),
40            )));
41        }
42        let opt_spec_t = if let Some(t_spec) = &sig.t_spec {
43            let t = match self.module.context.instantiate_typespec(&t_spec.t_spec) {
44                Ok(t) => t,
45                Err((t, es)) => {
46                    self.errs.extend(es);
47                    t
48                }
49            };
50            t.lift();
51            Some(self.module.context.generalize_t(t))
52        } else {
53            None
54        };
55        let rhs = body.block.remove(0);
56        let chunk = self.declare_chunk(rhs, true)?;
57        let py_name = match &chunk {
58            hir::Expr::TypeAsc(tasc) => {
59                if let hir::Expr::Accessor(acc) = tasc.expr.as_ref() {
60                    acc.local_name().map(Str::rc)
61                } else {
62                    None
63                }
64            }
65            hir::Expr::Accessor(hir::Accessor::Ident(ident)) => ident.vi.py_name.clone(),
66            _ => sig.escaped(),
67        };
68        let found_body_t = chunk.ref_t();
69        let ident = match &sig.pat {
70            ast::VarPattern::Ident(ident) => ident,
71            ast::VarPattern::Discard(token) => {
72                return Err(LowerErrors::from(LowerError::declare_error(
73                    self.cfg().input.clone(),
74                    line!() as usize,
75                    token.loc(),
76                    self.module.context.caused_by(),
77                )));
78            }
79            _ => unreachable!(),
80        };
81        let id = body.id;
82        if let Some(spec_t) = opt_spec_t {
83            self.module
84                .context
85                .sub_unify(found_body_t, &spec_t, &sig, None)?;
86        }
87        if let Some(py_name) = &py_name {
88            self.declare_instance(ident, found_body_t, py_name.clone())?;
89        } else {
90            self.module
91                .context
92                .assign_var_sig(&sig, found_body_t, id, Some(&chunk), None)?;
93        }
94        let mut ident = hir::Identifier::bare(ident.clone());
95        let t = match found_body_t {
96            Type::ClassType => {
97                let t = mono(format!("{}{}", self.module.context.path(), ident.raw));
98                v_enum(set! { ValueObj::builtin_class(t) })
99            }
100            Type::TraitType => {
101                let t = mono(format!("{}{}", self.module.context.path(), ident.raw));
102                v_enum(set! { ValueObj::builtin_trait(t) })
103            }
104            _ => found_body_t.clone(),
105        };
106        // Typ = 'typ': ClassType
107        // => 'typ': {<type Typ>}
108        if let hir::Expr::TypeAsc(hir::TypeAscription { expr, .. }) = &chunk {
109            if let hir::Expr::Accessor(acc) = expr.as_ref() {
110                if let Some(name) = acc.local_name() {
111                    let name = VarName::from_str(Str::rc(name));
112                    if let Some(vi) = self.module.context.get_mut_current_scope_var(&name) {
113                        vi.t = t.clone();
114                    }
115                }
116            }
117        }
118        ident.vi.t = t;
119        ident.vi.py_name = py_name;
120        ident.vi.def_loc = self.module.context.absolutize(ident.raw.name.loc());
121        let t_spec = if let Some(ts) = sig.t_spec {
122            let spec_t = match self.module.context.instantiate_typespec(&ts.t_spec) {
123                Ok(t) => t,
124                Err((t, es)) => {
125                    self.errs.extend(es);
126                    t
127                }
128            };
129            let expr = self.fake_lower_expr(*ts.t_spec_as_expr.clone())?;
130            Some(hir::TypeSpecWithOp::new(*ts, expr, spec_t))
131        } else {
132            None
133        };
134        let sig = hir::VarSignature::new(ident, t_spec);
135        let body = hir::DefBody::new(body.op, hir::Block::new(vec![chunk]), body.id);
136        Ok(hir::Def::new(hir::Signature::Var(sig), body))
137    }
138
139    /// allowed: alias, import, const functions (e.g. Class)
140    fn declare_def(&mut self, def: ast::Def) -> LowerResult<hir::Def> {
141        log!(info "entered {}({})", fn_name!(), def.sig);
142        let name = if let Some(name) = def.sig.name_as_str() {
143            name.clone()
144        } else {
145            Str::ever("<lambda>")
146        };
147        if self
148            .module
149            .context
150            .registered_info(&name, def.sig.is_const())
151            .is_some_and(|(_, vi)| {
152                !vi.kind.is_builtin()
153                    && vi.def_loc
154                        != self.module.context.absolutize(
155                            def.sig
156                                .ident()
157                                .map_or(Location::Unknown, |ident| ident.loc()),
158                        )
159            })
160        {
161            return Err(LowerErrors::from(LowerError::reassign_error(
162                self.cfg().input.clone(),
163                line!() as usize,
164                def.sig.loc(),
165                self.module.context.caused_by(),
166                &name,
167            )));
168        }
169        #[allow(clippy::let_and_return)]
170        let res = match def.sig {
171            ast::Signature::Subr(sig) => {
172                return Err(LowerErrors::from(LowerError::declare_error(
173                    self.cfg().input.clone(),
174                    line!() as usize,
175                    sig.loc(),
176                    self.module.context.caused_by(),
177                )));
178            }
179            ast::Signature::Var(sig) => self.declare_var(sig, def.body),
180        };
181        // self.pop_append_errs();
182        res
183    }
184
185    fn fake_lower_literal(&self, lit: ast::Literal) -> LowerResult<hir::Literal> {
186        let loc = lit.loc();
187        let lit = hir::Literal::try_from(lit.token).map_err(|_| {
188            LowerError::invalid_literal(
189                self.cfg.input.clone(),
190                line!() as usize,
191                loc,
192                self.module.context.caused_by(),
193            )
194        })?;
195        Ok(lit)
196    }
197
198    fn fake_lower_acc(&self, acc: ast::Accessor) -> LowerResult<hir::Accessor> {
199        // TypeApp is lowered in `fake_lower_expr`
200        match acc {
201            ast::Accessor::Ident(ident) => {
202                // to resolve `py_name`
203                let vi = self
204                    .module
205                    .context
206                    .rec_get_var_info(&ident, AccessKind::Name, self.input(), &self.module.context)
207                    .unwrap_or_default();
208                let ident = hir::Identifier::new(ident, None, vi);
209                let acc = hir::Accessor::Ident(ident);
210                Ok(acc)
211            }
212            ast::Accessor::Attr(attr) => {
213                let obj = self.fake_lower_expr(*attr.obj)?;
214                let mut ident = hir::Identifier::bare(attr.ident);
215                if let Ok(ctxs) = self
216                    .module
217                    .context
218                    .get_singular_ctxs_by_hir_expr(&obj, &self.module.context)
219                {
220                    for ctx in ctxs {
221                        if let Triple::Ok(vi) = ctx.rec_get_var_info(
222                            &ident.raw,
223                            AccessKind::UnboundAttr,
224                            self.input(),
225                            &self.module.context,
226                        ) {
227                            ident.vi = vi;
228                            break;
229                        }
230                    }
231                }
232                Ok(obj.attr(ident))
233            }
234            other => Err(LowerErrors::from(LowerError::declare_error(
235                self.cfg().input.clone(),
236                line!() as usize,
237                other.loc(),
238                self.module.context.caused_by(),
239            ))),
240        }
241    }
242
243    fn fake_lower_args(&self, args: ast::Args) -> LowerResult<hir::Args> {
244        let (pos_args_, var_args_, kw_args_, kw_var_, paren) = args.deconstruct();
245        let mut pos_args = vec![];
246        for arg in pos_args_.into_iter() {
247            let arg = self.fake_lower_expr(arg.expr)?;
248            pos_args.push(hir::PosArg::new(arg));
249        }
250        let var_args = match var_args_ {
251            Some(var_args) => {
252                let var_args = self.fake_lower_expr(var_args.expr)?;
253                Some(hir::PosArg::new(var_args))
254            }
255            None => None,
256        };
257        let mut kw_args = vec![];
258        for kw_arg in kw_args_.into_iter() {
259            let expr = self.fake_lower_expr(kw_arg.expr)?;
260            kw_args.push(hir::KwArg::new(kw_arg.keyword, expr));
261        }
262        let kw_var = match kw_var_ {
263            Some(kw_var) => {
264                let kw_var = self.fake_lower_expr(kw_var.expr)?;
265                Some(hir::PosArg::new(kw_var))
266            }
267            None => None,
268        };
269        let args = hir::Args::new(pos_args, var_args, kw_args, kw_var, paren);
270        Ok(args)
271    }
272
273    fn fake_lower_call(&self, mut call: ast::Call) -> LowerResult<hir::Call> {
274        let obj = self.fake_lower_expr(*call.obj)?;
275        if call
276            .attr_name
277            .as_ref()
278            .is_some_and(|attr| attr.inspect() == "__Tuple_getitem__")
279        {
280            call.attr_name
281                .as_mut()
282                .unwrap()
283                .name
284                .rename("__getitem__".into());
285        }
286        let attr_name = call.attr_name.map(hir::Identifier::bare);
287        let args = self.fake_lower_args(call.args)?;
288        Ok(hir::Call::new(obj, attr_name, args))
289    }
290
291    fn fake_lower_binop(&self, binop: ast::BinOp) -> LowerResult<hir::BinOp> {
292        let mut args = binop.args.into_iter();
293        let lhs = self.fake_lower_expr(*args.next().unwrap())?;
294        let rhs = self.fake_lower_expr(*args.next().unwrap())?;
295        Ok(hir::BinOp::new(binop.op, lhs, rhs, VarInfo::default()))
296    }
297
298    fn fake_lower_unaryop(&self, unaryop: ast::UnaryOp) -> LowerResult<hir::UnaryOp> {
299        let mut args = unaryop.args.into_iter();
300        let expr = self.fake_lower_expr(*args.next().unwrap())?;
301        Ok(hir::UnaryOp::new(unaryop.op, expr, VarInfo::default()))
302    }
303
304    fn fake_lower_list(&self, arr: ast::List) -> LowerResult<hir::List> {
305        match arr {
306            ast::List::WithLength(lis) => {
307                let len = self.fake_lower_expr(*lis.len)?;
308                let elem = self.fake_lower_expr(lis.elem.expr)?;
309                Ok(hir::List::WithLength(hir::ListWithLength::new(
310                    lis.l_sqbr,
311                    lis.r_sqbr,
312                    Type::Failure,
313                    elem,
314                    Some(len),
315                )))
316            }
317            ast::List::Normal(lis) => {
318                let mut elems = Vec::new();
319                let (elems_, ..) = lis.elems.deconstruct();
320                for elem in elems_.into_iter() {
321                    let elem = self.fake_lower_expr(elem.expr)?;
322                    elems.push(hir::PosArg::new(elem));
323                }
324                let elems = hir::Args::new(elems, None, vec![], None, None);
325                let t = list_t(Type::Failure, TyParam::value(elems.len()));
326                Ok(hir::List::Normal(hir::NormalList::new(
327                    lis.l_sqbr, lis.r_sqbr, t, elems,
328                )))
329            }
330            other => Err(LowerErrors::from(LowerError::declare_error(
331                self.cfg().input.clone(),
332                line!() as usize,
333                other.loc(),
334                self.module.context.caused_by(),
335            ))),
336        }
337    }
338
339    fn fake_lower_tuple(&self, tup: ast::Tuple) -> LowerResult<hir::Tuple> {
340        match tup {
341            ast::Tuple::Normal(tup) => {
342                let mut elems = Vec::new();
343                let (elems_, _, _, _, paren) = tup.elems.deconstruct();
344                for elem in elems_.into_iter() {
345                    let elem = self.fake_lower_expr(elem.expr)?;
346                    elems.push(hir::PosArg::new(elem));
347                }
348                let elems = hir::Args::pos_only(elems, paren);
349                Ok(hir::Tuple::Normal(hir::NormalTuple::new(elems)))
350            }
351        }
352    }
353
354    fn fake_lower_signature(&self, sig: ast::Signature) -> LowerResult<hir::Signature> {
355        match sig {
356            ast::Signature::Var(var) => {
357                let Some(ident) = var.ident().cloned() else {
358                    return Err(LowerErrors::from(LowerError::declare_error(
359                        self.cfg().input.clone(),
360                        line!() as usize,
361                        var.loc(),
362                        self.module.context.caused_by(),
363                    )));
364                };
365                let ident = hir::Identifier::bare(ident);
366                let t_spec = if let Some(ts) = var.t_spec {
367                    let expr = self.fake_lower_expr(*ts.t_spec_as_expr.clone())?;
368                    Some(hir::TypeSpecWithOp::new(*ts, expr, Type::Failure))
369                } else {
370                    None
371                };
372                let sig = hir::VarSignature::new(ident, t_spec);
373                Ok(hir::Signature::Var(sig))
374            }
375            ast::Signature::Subr(subr) => {
376                let mut decorators = set! {};
377                for decorator in subr.decorators.into_iter() {
378                    let decorator = self.fake_lower_expr(decorator.0)?;
379                    decorators.insert(decorator);
380                }
381                let ident = hir::Identifier::bare(subr.ident);
382                let params = self.fake_lower_params(subr.params)?;
383                let ret_t_spec = if let Some(ts) = subr.return_t_spec {
384                    let spec_t = self
385                        .module
386                        .context
387                        .instantiate_typespec(&ts.t_spec)
388                        .map_err(|(_, es)| es)?;
389                    let expr = self.fake_lower_expr(*ts.t_spec_as_expr.clone())?;
390                    Some(hir::TypeSpecWithOp::new(*ts, expr, spec_t))
391                } else {
392                    None
393                };
394                let sig = hir::SubrSignature::new(
395                    decorators,
396                    ident,
397                    subr.bounds,
398                    params,
399                    ret_t_spec,
400                    vec![],
401                );
402                Ok(hir::Signature::Subr(sig))
403            }
404        }
405    }
406
407    fn fake_lower_def(&self, def: ast::Def) -> LowerResult<hir::Def> {
408        let sig = self.fake_lower_signature(def.sig)?;
409        let block = self.fake_lower_block(def.body.block)?;
410        let body = hir::DefBody::new(def.body.op, block, def.body.id);
411        Ok(hir::Def::new(sig, body))
412    }
413
414    fn fake_lower_record(&self, rec: ast::Record) -> LowerResult<hir::Record> {
415        let rec = match rec {
416            ast::Record::Normal(rec) => rec,
417            ast::Record::Mixed(mixed) => Desugarer::desugar_shortened_record_inner(mixed),
418        };
419        let mut elems = Vec::new();
420        for elem in rec.attrs.into_iter() {
421            let elem = self.fake_lower_def(elem)?;
422            elems.push(elem);
423        }
424        let attrs = hir::RecordAttrs::new(elems);
425        Ok(hir::Record::new(rec.l_brace, rec.r_brace, attrs))
426    }
427
428    fn fake_lower_set(&self, set: ast::Set) -> LowerResult<hir::Set> {
429        match set {
430            ast::Set::Normal(set) => {
431                let mut elems = Vec::new();
432                let (elems_, ..) = set.elems.deconstruct();
433                for elem in elems_.into_iter() {
434                    let elem = self.fake_lower_expr(elem.expr)?;
435                    elems.push(hir::PosArg::new(elem));
436                }
437                let elems = hir::Args::pos_only(elems, None);
438                Ok(hir::Set::Normal(hir::NormalSet::new(
439                    set.l_brace,
440                    set.r_brace,
441                    Type::Failure,
442                    elems,
443                )))
444            }
445            ast::Set::WithLength(set) => {
446                let len = self.fake_lower_expr(*set.len)?;
447                let elem = self.fake_lower_expr(set.elem.expr)?;
448                Ok(hir::Set::WithLength(hir::SetWithLength::new(
449                    set.l_brace,
450                    set.r_brace,
451                    Type::Failure,
452                    len,
453                    elem,
454                )))
455            }
456            // TODO:
457            ast::Set::Comprehension(set) => Ok(hir::Set::Normal(hir::NormalSet::new(
458                set.l_brace,
459                set.r_brace,
460                Type::Failure,
461                hir::Args::empty(),
462            ))),
463        }
464    }
465
466    fn fake_lower_dict(&self, dict: ast::Dict) -> LowerResult<hir::Dict> {
467        match dict {
468            ast::Dict::Normal(dict) => {
469                let mut kvs = Vec::new();
470                for elem in dict.kvs.into_iter() {
471                    let key = self.fake_lower_expr(elem.key)?;
472                    let val = self.fake_lower_expr(elem.value)?;
473                    kvs.push(hir::KeyValue::new(key, val));
474                }
475                let tys = erg_common::dict::Dict::new();
476                Ok(hir::Dict::Normal(hir::NormalDict::new(
477                    dict.l_brace,
478                    dict.r_brace,
479                    tys,
480                    kvs,
481                )))
482            }
483            other => Err(LowerErrors::from(LowerError::declare_error(
484                self.cfg().input.clone(),
485                line!() as usize,
486                other.loc(),
487                self.module.context.caused_by(),
488            ))),
489        }
490    }
491
492    fn fake_lower_params(&self, params: ast::Params) -> LowerResult<hir::Params> {
493        let (non_defaults_, var_params_, defaults_, kw_var_, guards_, parens) =
494            params.deconstruct();
495        let mut non_defaults = vec![];
496        for non_default_ in non_defaults_.into_iter() {
497            let t_spec_as_expr = non_default_
498                .t_spec
499                .as_ref()
500                .map(|t_spec| self.fake_lower_expr(*t_spec.t_spec_as_expr.clone()))
501                .transpose()?;
502            let non_default = hir::NonDefaultParamSignature::new(
503                non_default_,
504                VarInfo::default(),
505                t_spec_as_expr,
506            );
507            non_defaults.push(non_default);
508        }
509        let var_params = if let Some(var_params) = var_params_ {
510            let t_spec_as_expr = var_params
511                .t_spec
512                .as_ref()
513                .map(|t_spec| self.fake_lower_expr(*t_spec.t_spec_as_expr.clone()))
514                .transpose()?;
515            Some(Box::new(hir::NonDefaultParamSignature::new(
516                *var_params,
517                VarInfo::default(),
518                t_spec_as_expr,
519            )))
520        } else {
521            None
522        };
523        let mut defaults = vec![];
524        for default_ in defaults_.into_iter() {
525            let t_spec_as_expr = default_
526                .sig
527                .t_spec
528                .as_ref()
529                .map(|t_spec| self.fake_lower_expr(*t_spec.t_spec_as_expr.clone()))
530                .transpose()?;
531            let default_val = self.fake_lower_expr(default_.default_val)?;
532            let sig = hir::NonDefaultParamSignature::new(
533                default_.sig,
534                VarInfo::default(),
535                t_spec_as_expr,
536            );
537            let default = hir::DefaultParamSignature::new(sig, default_val);
538            defaults.push(default);
539        }
540        let kw_var = if let Some(kw_var) = kw_var_ {
541            let t_spec_as_expr = kw_var
542                .t_spec
543                .as_ref()
544                .map(|t_spec| self.fake_lower_expr(*t_spec.t_spec_as_expr.clone()))
545                .transpose()?;
546            Some(Box::new(hir::NonDefaultParamSignature::new(
547                *kw_var,
548                VarInfo::default(),
549                t_spec_as_expr,
550            )))
551        } else {
552            None
553        };
554        let mut guards = vec![];
555        for guard in guards_.into_iter() {
556            let guard = match guard {
557                ast::GuardClause::Condition(cond) => {
558                    hir::GuardClause::Condition(self.fake_lower_expr(cond)?)
559                }
560                ast::GuardClause::Bind(bind) => hir::GuardClause::Bind(self.fake_lower_def(bind)?),
561            };
562            guards.push(guard);
563        }
564        Ok(hir::Params::new(
565            non_defaults,
566            var_params,
567            defaults,
568            kw_var,
569            guards,
570            parens,
571        ))
572    }
573
574    fn fake_lower_block(&self, block: ast::Block) -> LowerResult<hir::Block> {
575        let mut chunks = vec![];
576        for chunk in block.into_iter() {
577            let chunk = self.fake_lower_expr(chunk)?;
578            chunks.push(chunk);
579        }
580        Ok(hir::Block::new(chunks))
581    }
582
583    fn fake_lower_lambda(&self, lambda: ast::Lambda) -> LowerResult<hir::Lambda> {
584        let params = self.fake_lower_params(lambda.sig.params)?;
585        let return_t_spec = lambda.sig.return_t_spec.map(|t_spec| t_spec.t_spec);
586        let body = self.fake_lower_block(lambda.body)?;
587        Ok(hir::Lambda::new(
588            lambda.id.0,
589            params,
590            lambda.op,
591            return_t_spec,
592            vec![],
593            body,
594            Type::Failure,
595        ))
596    }
597
598    fn fake_lower_dummy(&self, dummy: ast::Dummy) -> LowerResult<hir::Dummy> {
599        let mut dummy_ = vec![];
600        for elem in dummy.into_iter() {
601            let elem = self.fake_lower_expr(elem)?;
602            dummy_.push(elem);
603        }
604        Ok(hir::Dummy::new(dummy_))
605    }
606
607    fn fake_lower_type_asc(&self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
608        let expr = self.fake_lower_expr(*tasc.expr)?;
609        let t_spec_as_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr.clone())?;
610        let spec_t = self
611            .module
612            .context
613            .instantiate_typespec(&tasc.t_spec.t_spec)
614            .map_err(|(_, es)| es)?;
615        let spec = hir::TypeSpecWithOp::new(tasc.t_spec, t_spec_as_expr, spec_t);
616        Ok(hir::TypeAscription::new(expr, spec))
617    }
618
619    fn fake_lower_compound(&self, compound: ast::Compound) -> LowerResult<hir::Block> {
620        let mut chunks = vec![];
621        for chunk in compound.into_iter() {
622            let chunk = self.fake_lower_expr(chunk)?;
623            chunks.push(chunk);
624        }
625        Ok(hir::Block::new(chunks))
626    }
627
628    pub(crate) fn fake_lower_expr(&self, expr: ast::Expr) -> LowerResult<hir::Expr> {
629        match expr {
630            ast::Expr::Literal(lit) => Ok(hir::Expr::Literal(self.fake_lower_literal(lit)?)),
631            ast::Expr::BinOp(binop) => Ok(hir::Expr::BinOp(self.fake_lower_binop(binop)?)),
632            ast::Expr::UnaryOp(unop) => Ok(hir::Expr::UnaryOp(self.fake_lower_unaryop(unop)?)),
633            ast::Expr::List(lis) => Ok(hir::Expr::List(self.fake_lower_list(lis)?)),
634            ast::Expr::Tuple(tup) => Ok(hir::Expr::Tuple(self.fake_lower_tuple(tup)?)),
635            ast::Expr::Record(rec) => Ok(hir::Expr::Record(self.fake_lower_record(rec)?)),
636            ast::Expr::Set(set) => Ok(hir::Expr::Set(self.fake_lower_set(set)?)),
637            ast::Expr::Dict(dict) => Ok(hir::Expr::Dict(self.fake_lower_dict(dict)?)),
638            ast::Expr::Accessor(ast::Accessor::TypeApp(tapp)) => self.fake_lower_expr(*tapp.obj),
639            ast::Expr::Accessor(acc) => Ok(hir::Expr::Accessor(self.fake_lower_acc(acc)?)),
640            ast::Expr::Call(call) => Ok(hir::Expr::Call(self.fake_lower_call(call)?)),
641            ast::Expr::Lambda(lambda) => Ok(hir::Expr::Lambda(self.fake_lower_lambda(lambda)?)),
642            ast::Expr::Compound(compound) => {
643                Ok(hir::Expr::Compound(self.fake_lower_compound(compound)?))
644            }
645            ast::Expr::Dummy(dummy) => Ok(hir::Expr::Dummy(self.fake_lower_dummy(dummy)?)),
646            ast::Expr::TypeAscription(tasc) => {
647                Ok(hir::Expr::TypeAsc(self.fake_lower_type_asc(tasc)?))
648            }
649            other => Err(LowerErrors::from(LowerError::declare_error(
650                self.cfg().input.clone(),
651                line!() as usize,
652                other.loc(),
653                self.module.context.caused_by(),
654            ))),
655        }
656    }
657
658    fn declare_ident(&mut self, tasc: ast::TypeAscription) -> LowerResult<hir::TypeAscription> {
659        log!(info "entered {}({})", fn_name!(), tasc);
660        let kind = tasc.kind();
661        match *tasc.expr {
662            ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
663                let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
664                let t = match self
665                    .module
666                    .context
667                    .instantiate_typespec(&tasc.t_spec.t_spec)
668                {
669                    Ok(t) => t,
670                    Err((t, es)) => {
671                        self.errs.extend(es);
672                        t
673                    }
674                };
675                t.lift();
676                let t = self.module.context.generalize_t(t);
677                match kind {
678                    AscriptionKind::TypeOf | AscriptionKind::AsCast => {
679                        self.declare_instance(&ident, &t, py_name.clone())?;
680                    }
681                    AscriptionKind::SubtypeOf => {
682                        self.declare_subtype(&ident, &t)?;
683                    }
684                    _ => {
685                        log!(err "supertype ascription is not supported yet");
686                    }
687                }
688                let muty = Mutability::from(&ident.inspect()[..]);
689                let vis = self.module.context.instantiate_vis_modifier(&ident.vis)?;
690                let vi = VarInfo::new(
691                    t,
692                    muty,
693                    Visibility::new(vis, self.module.context.name.clone()),
694                    VarKind::Declared,
695                    None,
696                    self.module.context.kind.clone(),
697                    Some(py_name),
698                    self.module.context.absolutize(ident.name.loc()),
699                );
700                let ident = hir::Identifier::new(ident, None, vi);
701                let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr.clone())?;
702                let t_spec = hir::TypeSpecWithOp::new(tasc.t_spec, t_spec_expr, Type::Failure);
703                Ok(hir::Expr::Accessor(hir::Accessor::Ident(ident)).type_asc(t_spec))
704            }
705            ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
706                let py_name = Str::rc(attr.ident.inspect().trim_end_matches('!'));
707                let mut tv_cache = if let Ok(call) = ast::Call::try_from(*attr.obj.clone()) {
708                    let ast::Expr::Accessor(ast::Accessor::Ident(ident)) = *call.obj else {
709                        return feature_error!(
710                            LowerErrors,
711                            LowerError,
712                            &self.module.context,
713                            call.obj.loc(),
714                            "complex polymorphic type declaration"
715                        );
716                    };
717                    self.module.context.get_tv_ctx(&ident, &call.args)
718                } else {
719                    TyVarCache::new(self.module.context.level, &self.module.context)
720                };
721                let t = match self
722                    .module
723                    .context
724                    .instantiate_typespec_with_tv_cache(&tasc.t_spec.t_spec, &mut tv_cache)
725                {
726                    Ok(t) => t,
727                    Err((t, es)) => {
728                        self.errs.extend(es);
729                        t
730                    }
731                };
732                let impl_trait = if let ast::Expr::Accessor(ast::Accessor::TypeApp(tapp)) =
733                    attr.obj.as_ref()
734                {
735                    match &tapp.type_args.args {
736                        TypeAppArgsKind::SubtypeOf(typ) => {
737                            let trait_ = match self
738                                .module
739                                .context
740                                .instantiate_typespec_with_tv_cache(&typ.t_spec, &mut tv_cache)
741                            {
742                                Ok(t) => t,
743                                Err((t, es)) => {
744                                    self.errs.extend(es);
745                                    t
746                                }
747                            };
748                            if !self.module.context.is_trait(&trait_) {
749                                return Err(LowerErrors::from(LowerError::type_mismatch_error(
750                                    self.cfg().input.clone(),
751                                    line!() as usize,
752                                    typ.loc(),
753                                    self.module.context.caused_by(),
754                                    "SuperTrait",
755                                    None,
756                                    &Type::TraitType,
757                                    &Type::ClassType,
758                                    None,
759                                    None,
760                                )));
761                            }
762                            Some(trait_)
763                        }
764                        TypeAppArgsKind::Args(args) => {
765                            log!(err "{args}");
766                            None
767                        }
768                    }
769                } else {
770                    None
771                };
772                let ctx = self.module.context.get_mut_singular_ctx_and_t(
773                    attr.obj.as_ref(),
774                    &self.module.context.name.clone(),
775                )?;
776                let class = ctx.typ.clone();
777                let ctx = if let Some(impl_trait) = impl_trait {
778                    match ctx
779                        .methods_list
780                        .iter_mut()
781                        .find(|ctx| ctx.typ.is_impl_of(&impl_trait))
782                    {
783                        Some(impl_ctx) => impl_ctx,
784                        None => {
785                            let impl_ctx = Context::methods(
786                                Some(impl_trait.clone()),
787                                self.cfg.copy(),
788                                ctx.shared.clone(),
789                                0,
790                                ctx.level,
791                            );
792                            ctx.super_traits.push(impl_trait.clone());
793                            let declared_in = NormalizedPathBuf::from(ctx.module_path());
794                            let declared_in = declared_in.exists().then_some(declared_in);
795                            if let Some(mut impls) =
796                                ctx.trait_impls().get_mut(&impl_trait.qual_name())
797                            {
798                                impls.insert(TraitImpl::new(
799                                    class.clone(),
800                                    impl_trait.clone(),
801                                    declared_in,
802                                ));
803                            } else {
804                                ctx.trait_impls().register(
805                                    impl_trait.qual_name(),
806                                    set! { TraitImpl::new(class.clone(), impl_trait.clone(), declared_in) },
807                                );
808                            }
809                            ctx.methods_list.push(MethodContext::new(
810                                DefId(0),
811                                ClassDefType::impl_trait(class.clone(), impl_trait),
812                                impl_ctx,
813                            ));
814                            &mut ctx.methods_list.iter_mut().last().unwrap().ctx
815                        }
816                    }
817                } else {
818                    ctx
819                };
820                let vi = ctx.assign_var_sig(
821                    &ast::VarSignature::new(ast::VarPattern::Ident(attr.ident.clone()), None),
822                    &t,
823                    ast::DefId(0),
824                    None,
825                    Some(py_name.clone()),
826                )?;
827                if let Some(types) = self
828                    .module
829                    .context
830                    .method_to_classes
831                    .get_mut(attr.ident.inspect())
832                {
833                    types.push(MethodPair::new(class, vi.clone()));
834                } else {
835                    self.module.context.method_to_classes.insert(
836                        attr.ident.inspect().clone(),
837                        vec![MethodPair::new(class, vi.clone())],
838                    );
839                }
840                let obj = self.fake_lower_expr(*attr.obj)?;
841                let muty = Mutability::from(&attr.ident.inspect()[..]);
842                let vis = self
843                    .module
844                    .context
845                    .instantiate_vis_modifier(&attr.ident.vis)?;
846                let vi = VarInfo::new(
847                    t,
848                    muty,
849                    Visibility::new(vis, self.module.context.name.clone()),
850                    VarKind::Declared,
851                    None,
852                    self.module.context.kind.clone(),
853                    Some(py_name),
854                    self.module.context.absolutize(attr.ident.name.loc()),
855                );
856                let ident = hir::Identifier::new(attr.ident, None, vi);
857                let attr = obj.attr_expr(ident);
858                let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr.clone())?;
859                let t_spec = hir::TypeSpecWithOp::new(tasc.t_spec, t_spec_expr, Type::Failure);
860                Ok(attr.type_asc(t_spec))
861            }
862            ast::Expr::Call(call) => {
863                let ast::Expr::Accessor(ast::Accessor::Ident(ident)) = *call.obj else {
864                    return feature_error!(
865                        LowerErrors,
866                        LowerError,
867                        &self.module.context,
868                        call.obj.loc(),
869                        "complex polymorphic type declaration"
870                    );
871                };
872                let py_name = Str::rc(ident.inspect().trim_end_matches('!'));
873                let mut tv_cache = self.module.context.get_tv_ctx(&ident, &call.args);
874                let t = match self
875                    .module
876                    .context
877                    .instantiate_typespec_with_tv_cache(&tasc.t_spec.t_spec, &mut tv_cache)
878                {
879                    Ok(t) => t,
880                    Err((t, es)) => {
881                        self.errs.extend(es);
882                        t
883                    }
884                };
885                match kind {
886                    AscriptionKind::TypeOf | AscriptionKind::AsCast => {
887                        self.declare_instance(&ident, &t, py_name)?;
888                    }
889                    AscriptionKind::SubtypeOf => {
890                        self.declare_subtype(&ident, &t)?;
891                    }
892                    _ => {
893                        log!(err "supertype ascription is not supported yet");
894                    }
895                }
896                let acc = self.fake_lower_acc(ast::Accessor::Ident(ident))?;
897                let args = self.fake_lower_args(call.args)?;
898                let t_spec_expr = self.fake_lower_expr(*tasc.t_spec.t_spec_as_expr.clone())?;
899                let t_spec = hir::TypeSpecWithOp::new(tasc.t_spec, t_spec_expr, Type::Failure);
900                Ok(hir::Expr::Accessor(acc).call_expr(args).type_asc(t_spec))
901            }
902            other => Err(LowerErrors::from(LowerError::declare_error(
903                self.cfg().input.clone(),
904                line!() as usize,
905                other.loc(),
906                self.module.context.caused_by(),
907            ))),
908        }
909    }
910
911    fn declare_instance(
912        &mut self,
913        ident: &ast::Identifier,
914        t: &Type,
915        py_name: Str,
916    ) -> LowerResult<()> {
917        // .X = 'x': Type
918        if ident.is_raw() {
919            return Ok(());
920        }
921        // in case of:
922        // ```
923        // .Foo = 'foo': ClassType
924        // .Foo.
925        //     __call__: (T, U) -> .Foo
926        // .foo: (T, U) -> .Foo # ignore this definition
927        // ```
928        let mut type_as_function = false;
929        if PYTHON_MODE
930            && self
931                .module
932                .context
933                .registered_info(ident.inspect(), ident.is_const())
934                .is_some_and(|(_, vi)| {
935                    self.module.context.subtype_of(t, &Type::Type)
936                        || self.module.context.subtype_of(&vi.t, &Type::Type)
937                })
938        {
939            let typ = self.module.context.get_type_ctx(ident.inspect());
940            if typ.is_some_and(|ctx| ctx.has("__call__")) {
941                type_as_function = true;
942            }
943        }
944        if !type_as_function
945            && self
946                .module
947                .context
948                .registered_info(ident.inspect(), ident.is_const())
949                .is_some_and(|(_, vi)| {
950                    !vi.kind.is_builtin()
951                        && vi.def_loc != self.module.context.absolutize(ident.loc())
952                })
953        {
954            return Err(LowerErrors::from(LowerError::reassign_error(
955                self.cfg().input.clone(),
956                line!() as usize,
957                ident.loc(),
958                self.module.context.caused_by(),
959                ident.inspect(),
960            )));
961        }
962        let new_ident = if PYTHON_MODE {
963            let mut symbol = ident.name.clone().into_token();
964            symbol.content = py_name.clone();
965            Identifier::new(ident.vis.clone(), VarName::new(symbol))
966        } else {
967            ident.clone()
968        };
969        let (t, ty_obj) = match t {
970            Type::ClassType => {
971                let t = mono(format!("{}{ident}", self.module.context.path()));
972                let ty_obj = GenTypeObj::class(t.clone(), None, None, true);
973                let t = v_enum(set! { ValueObj::builtin_class(t) });
974                (t, Some(ty_obj))
975            }
976            Type::TraitType => {
977                let t = mono(format!("{}{ident}", self.module.context.path()));
978                let ty_obj = GenTypeObj::trait_(
979                    t.clone(),
980                    TypeObj::builtin_type(Type::Uninited),
981                    None,
982                    true,
983                );
984                let t = v_enum(set! { ValueObj::builtin_trait(t) });
985                (t, Some(ty_obj))
986            }
987            Type::Subr(subr) if subr.return_t.is_class_type() => {
988                let params = subr
989                    .non_default_params
990                    .iter()
991                    .map(|p| {
992                        let c = Constraint::new_type_of(p.typ().clone());
993                        if self.module.context.subtype_of(p.typ(), &Type::Type) {
994                            TyParam::t(mono_q(p.name().unwrap_or(&Str::ever("_")), c))
995                        } else {
996                            mono_q_tp(p.name().unwrap_or(&Str::ever("_")), c)
997                        }
998                    })
999                    .collect();
1000                let t = poly(format!("{}{ident}", self.module.context.path()), params);
1001                let ty_obj = GenTypeObj::class(t.clone(), None, None, true);
1002                let t = v_enum(set! { ValueObj::builtin_class(t) });
1003                (t, Some(ty_obj))
1004            }
1005            _ => (t.clone(), None),
1006        };
1007        self.module.context.assign_var_sig(
1008            &ast::VarSignature::new(ast::VarPattern::Ident(ident.clone()), None),
1009            &t,
1010            ast::DefId(0),
1011            None,
1012            Some(py_name),
1013        )?;
1014        if let Some(gen) = ty_obj {
1015            self.module
1016                .context
1017                .register_gen_type(&new_ident, gen, None)?;
1018        }
1019        Ok(())
1020    }
1021
1022    fn declare_subtype(&mut self, ident: &ast::Identifier, sup: &Type) -> LowerResult<()> {
1023        if ident.is_raw() {
1024            return Ok(());
1025        }
1026        let name = if PYTHON_MODE {
1027            self.module
1028                .context
1029                .erg_to_py_names
1030                .get(ident.inspect())
1031                .map_or(Str::ever("?"), |s| s.clone())
1032        } else {
1033            ident.inspect().clone()
1034        };
1035        if let Some(ctx) = self.module.context.rec_get_mut_type(&name) {
1036            let mut tmp = mem::take(ctx);
1037            let res = if self.module.context.is_class(sup) {
1038                tmp.register_base_class(&self.module.context, sup.clone())
1039            } else {
1040                let class = tmp.typ.clone();
1041                let imp = self.module.context.register_trait_impl(&class, sup, ident);
1042                imp.and(tmp.register_trait(&self.module.context, sup.clone()))
1043            };
1044            res.inspect_err(|_err| {
1045                let ctx = self.module.context.rec_get_mut_type(&name).unwrap();
1046                mem::swap(ctx, &mut tmp);
1047            })?;
1048            let ctx = self.module.context.rec_get_mut_type(&name).unwrap();
1049            mem::swap(ctx, &mut tmp);
1050            Ok(())
1051        } else {
1052            Err(LowerErrors::from(LowerError::no_var_error(
1053                self.cfg().input.clone(),
1054                line!() as usize,
1055                ident.loc(),
1056                self.module.context.caused_by(),
1057                ident.inspect(),
1058                self.module.context.get_similar_name(ident.inspect()),
1059            )))
1060        }
1061    }
1062
1063    fn declare_chunk(&mut self, expr: ast::Expr, allow_acc: bool) -> LowerResult<hir::Expr> {
1064        log!(info "entered {}", fn_name!());
1065        match expr {
1066            ast::Expr::Literal(lit) if lit.is_doc_comment() => {
1067                Ok(hir::Expr::Literal(self.lower_literal(lit, None)?))
1068            }
1069            ast::Expr::Accessor(acc) if allow_acc => Ok(hir::Expr::Accessor(
1070                self.lower_acc(acc, None).map_err(|(_, errs)| errs)?,
1071            )),
1072            ast::Expr::Def(def) => Ok(hir::Expr::Def(self.declare_def(def)?)),
1073            ast::Expr::TypeAscription(tasc) => Ok(hir::Expr::TypeAsc(self.declare_ident(tasc)?)),
1074            ast::Expr::Call(call)
1075                if call
1076                    .additional_operation()
1077                    .map(|op| op.is_import())
1078                    .unwrap_or(false) =>
1079            {
1080                Ok(hir::Expr::Call(
1081                    self.lower_call(call, None).map_err(|(_, errs)| errs)?,
1082                ))
1083            }
1084            ast::Expr::Compound(compound) => {
1085                let mut chunks = vec![];
1086                for chunk in compound.into_iter() {
1087                    let chunk = self.declare_chunk(chunk, true)?;
1088                    chunks.push(chunk);
1089                }
1090                Ok(hir::Expr::Compound(hir::Block::new(chunks)))
1091            }
1092            ast::Expr::Dummy(dummy) => {
1093                let mut dummy_ = vec![];
1094                for elem in dummy.into_iter() {
1095                    let elem = self.declare_chunk(elem, true)?;
1096                    dummy_.push(elem);
1097                }
1098                Ok(hir::Expr::Dummy(hir::Dummy::new(dummy_)))
1099            }
1100            ast::Expr::InlineModule(inline) => {
1101                let import = self
1102                    .lower_inline_module(inline, None)
1103                    .map_err(|(_, es)| es)?;
1104                Ok(hir::Expr::Call(import))
1105            }
1106            other => Err(LowerErrors::from(LowerError::declare_error(
1107                self.cfg().input.clone(),
1108                line!() as usize,
1109                other.loc(),
1110                self.module.context.caused_by(),
1111            ))),
1112        }
1113    }
1114
1115    fn pre_declare_chunk(&mut self, expr: &ast::Expr) {
1116        match expr {
1117            ast::Expr::TypeAscription(tasc) => {
1118                let _ = self.declare_ident(tasc.clone());
1119            }
1120            ast::Expr::Def(def) => {
1121                let _ = self.declare_def(def.clone());
1122            }
1123            ast::Expr::Compound(compound) => {
1124                for chunk in compound.iter() {
1125                    self.pre_declare_chunk(chunk);
1126                }
1127            }
1128            ast::Expr::Dummy(dummy) => {
1129                for elem in dummy.iter() {
1130                    self.pre_declare_chunk(elem);
1131                }
1132            }
1133            _ => {}
1134        }
1135    }
1136
1137    pub(crate) fn declare_module(&mut self, ast: AST) -> HIR {
1138        let mut module = hir::Module::with_capacity(ast.module.len());
1139        // Register const items speculatively
1140        for chunk in ast.module.iter() {
1141            self.pre_declare_chunk(chunk);
1142        }
1143        self.warns.clear();
1144        self.errs.clear();
1145        for chunk in ast.module.into_iter() {
1146            match self.declare_chunk(chunk, false) {
1147                Ok(chunk) => {
1148                    module.push(chunk);
1149                }
1150                Err(errs) => {
1151                    self.errs.extend(errs);
1152                }
1153            }
1154        }
1155        let hir = HIR::new(ast.name, module);
1156        self.lint(&hir, "declare");
1157        hir
1158    }
1159}