erg_compiler/context/
inquire.rs

1// (type) getters & validators
2use std::option::Option; // conflicting to Type::Option
3use std::path::{Path, PathBuf};
4
5use erg_common::consts::{DEBUG_MODE, ERG_MODE, PYTHON_MODE};
6use erg_common::error::{ErrorCore, Location, SubMessage};
7use erg_common::io::Input;
8use erg_common::pathutil::NormalizedPathBuf;
9use erg_common::set::Set;
10use erg_common::traits::{Locational, NoTypeDisplay, Stream};
11use erg_common::triple::Triple;
12use erg_common::Str;
13use erg_common::{
14    dict, fmt_option, fmt_slice, get_hash, log, option_enum_unwrap, set, switch_lang,
15};
16use erg_common::{fmt_vec, levenshtein};
17
18use erg_parser::ast::{self, Identifier, VarName};
19use erg_parser::token::Token;
20
21use crate::ty::constructors::{anon, fn_met, free_var, func, mono, poly, proc, proj, ref_, subr_t};
22use crate::ty::free::{Constraint, FreeTyParam, FreeTyVar};
23use crate::ty::typaram::TyParam;
24use crate::ty::value::{GenTypeObj, TypeObj, ValueObj};
25use crate::ty::{
26    Field, GuardType, HasType, ParamTy, Predicate, RefinementType, SubrKind, SubrType, Type,
27    Visibility, VisibilityModifier,
28};
29use Type::*;
30
31use crate::context::instantiate_spec::ConstTemplate;
32use crate::context::{Context, RegistrationMode, TraitImpl, TyVarCache, Variance};
33use crate::error::{
34    binop_to_dname, ordinal_num, readable_name, unaryop_to_dname, FailableOption,
35    SingleTyCheckResult, TyCheckError, TyCheckErrors, TyCheckResult,
36};
37use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
38use crate::{feature_error, hir};
39use crate::{unreachable_error, AccessKind};
40use RegistrationMode::*;
41
42use super::eval::UndoableLinkedList;
43use super::instantiate_spec::ParamKind;
44use super::{ContextKind, MethodContext, MethodPair, TypeContext};
45
46#[derive(Debug, Clone, PartialEq, Eq, Hash)]
47pub enum SubstituteResult {
48    Ok,
49    __Call__(Type),
50    Coerced(Type),
51}
52
53impl Context {
54    /// Returns `true` if the module is being inspected, or has been inspected
55    pub(crate) fn mod_registered(&self, path: &NormalizedPathBuf) -> bool {
56        (self.shared.is_some() && self.promises().is_registered(path)) || self.mod_cached(path)
57    }
58
59    /// Returns `true` if the module has been inspected
60    pub(crate) fn mod_cached(&self, path: &Path) -> bool {
61        self.mod_cache().get(path).is_some() || self.py_mod_cache().get(path).is_some()
62    }
63
64    /// Get the context of the module. If it was in analysis, wait until analysis is complete and join the thread.
65    /// If you only want to know if the module is registered, use `mod_registered`.
66    pub(crate) fn get_mod_with_path(&self, path: &Path) -> Option<&Context> {
67        if self.module_path() == path {
68            return self.get_module();
69        }
70        let path = NormalizedPathBuf::from(path);
71        if let Some(ctx) = self.get_module_from_stack(&path) {
72            return Some(ctx);
73        }
74        if self.shared.is_some() && self.promises().is_registered(&path) && !self.mod_cached(&path)
75        {
76            self.promises().join(&path, &self.cfg);
77        }
78        self.opt_mod_cache()?
79            .raw_ref_ctx(&path)
80            .or_else(|| self.opt_py_mod_cache()?.raw_ref_ctx(&path))
81            .map(|mod_ctx| &mod_ctx.context)
82    }
83
84    /// if `name` is the name of the type, get the `__call__` method
85    pub(crate) fn get_current_scope_callable(&self, name: &VarName) -> Option<&VarInfo> {
86        #[cfg(feature = "py_compat")]
87        let search_name = self
88            .erg_to_py_names
89            .get(name.inspect())
90            .unwrap_or(name.inspect());
91        #[cfg(not(feature = "py_compat"))]
92        let search_name = name.inspect();
93        if let Some(ctx) = self.get_type_ctx(search_name) {
94            let __call__ = VarName::from_static("__call__");
95            if let Some(vi) = ctx.get_current_scope_non_param(&__call__) {
96                return Some(vi);
97            }
98            for methods in ctx.methods_list.iter() {
99                if let Some(vi) = methods.get_current_scope_non_param(&__call__) {
100                    return Some(vi);
101                }
102            }
103        }
104        self.get_current_scope_non_param(name)
105    }
106
107    pub(crate) fn get_current_scope_non_param(&self, name: &VarName) -> Option<&VarInfo> {
108        #[cfg(feature = "py_compat")]
109        let search_name = self
110            .erg_to_py_names
111            .get(name.inspect())
112            .unwrap_or(name.inspect());
113        #[cfg(not(feature = "py_compat"))]
114        let search_name = name.inspect();
115        self.locals
116            .get(search_name)
117            .or_else(|| self.decls.get(search_name))
118            .or_else(|| {
119                for methods in self.methods_list.iter() {
120                    if let Some(vi) = methods.get_current_scope_non_param(name) {
121                        return Some(vi);
122                    }
123                }
124                None
125            })
126            .or_else(|| {
127                self.tv_cache
128                    .as_ref()
129                    .and_then(|tv_cache| tv_cache.var_infos.get(search_name))
130            })
131    }
132
133    pub(crate) fn get_current_scope_var(&self, name: &VarName) -> Option<&VarInfo> {
134        #[cfg(feature = "py_compat")]
135        let search_name = self
136            .erg_to_py_names
137            .get(name.inspect())
138            .unwrap_or(name.inspect());
139        #[cfg(not(feature = "py_compat"))]
140        let search_name = name.inspect();
141        self.locals
142            .get(search_name)
143            .or_else(|| self.decls.get(search_name))
144            .or_else(|| {
145                self.params
146                    .iter()
147                    .find(|(opt_name, _)| {
148                        opt_name
149                            .as_ref()
150                            .map(|n| n.inspect() == search_name)
151                            .unwrap_or(false)
152                    })
153                    .map(|(_, vi)| vi)
154            })
155            .or_else(|| {
156                for methods in self.methods_list.iter() {
157                    if let Some(vi) = methods.get_current_scope_var(name) {
158                        return Some(vi);
159                    }
160                }
161                None
162            })
163            .or_else(|| {
164                self.tv_cache
165                    .as_ref()
166                    .and_then(|tv_cache| tv_cache.var_infos.get(search_name))
167            })
168    }
169
170    pub(crate) fn get_current_scope_attr(&self, name: &VarName) -> Option<&VarInfo> {
171        #[cfg(feature = "py_compat")]
172        let search_name = self
173            .erg_to_py_names
174            .get(name.inspect())
175            .unwrap_or(name.inspect());
176        #[cfg(not(feature = "py_compat"))]
177        let search_name = name.inspect();
178        self.locals
179            .get(search_name)
180            .or_else(|| self.decls.get(search_name))
181            .or_else(|| {
182                for methods in self.methods_list.iter() {
183                    if let Some(vi) = methods.get_current_scope_attr(name) {
184                        return Some(vi);
185                    }
186                }
187                None
188            })
189    }
190
191    pub(crate) fn get_method_context_of(&self, trait_: &Type) -> Option<&MethodContext> {
192        #[allow(clippy::manual_find)]
193        for methods in self.methods_list.iter() {
194            if methods.impl_of().is_some_and(|t| &t == trait_) {
195                return Some(methods);
196            }
197        }
198        None
199    }
200
201    pub(crate) fn get_mut_current_scope_var(&mut self, name: &VarName) -> Option<&mut VarInfo> {
202        #[cfg(feature = "py_compat")]
203        let search_name = self
204            .erg_to_py_names
205            .get(name.inspect())
206            .unwrap_or(name.inspect());
207        #[cfg(not(feature = "py_compat"))]
208        let search_name = name.inspect();
209        self.locals
210            .get_mut(search_name)
211            .or_else(|| self.decls.get_mut(search_name))
212            .or_else(|| {
213                self.params
214                    .iter_mut()
215                    .find(|(opt_name, _)| {
216                        opt_name
217                            .as_ref()
218                            .map(|n| n.inspect() == search_name)
219                            .unwrap_or(false)
220                    })
221                    .map(|(_, vi)| vi)
222            })
223            .or_else(|| {
224                for methods in self.methods_list.iter_mut() {
225                    if let Some(vi) = methods.get_mut_current_scope_var(name) {
226                        return Some(vi);
227                    }
228                }
229                None
230            })
231    }
232
233    pub(crate) fn get_var_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
234        #[cfg(feature = "py_compat")]
235        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
236        self.locals
237            .get_key_value(name)
238            .or_else(|| self.get_param_kv(name))
239            .or_else(|| self.decls.get_key_value(name))
240            .or_else(|| self.future_defined_locals.get_key_value(name))
241            .or_else(|| self.get_outer_scope().and_then(|ctx| ctx.get_var_kv(name)))
242    }
243
244    fn get_param_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
245        #[cfg(feature = "py_compat")]
246        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
247        self.params
248            .iter()
249            .find(|(opt_name, _)| {
250                opt_name
251                    .as_ref()
252                    .map(|n| &n.inspect()[..] == name)
253                    .unwrap_or(false)
254            })
255            .map(|(opt_name, vi)| (opt_name.as_ref().unwrap(), vi))
256    }
257
258    pub fn get_method_kv(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
259        #[cfg(feature = "py_compat")]
260        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
261        self.get_var_kv(name)
262            .or_else(|| {
263                for methods in self.methods_list.iter() {
264                    if let Some(vi) = methods.get_method_kv(name) {
265                        return Some(vi);
266                    }
267                }
268                None
269            })
270            .or_else(|| {
271                self.get_outer_scope()
272                    .and_then(|ctx| ctx.get_method_kv(name))
273            })
274    }
275
276    /// ```erg
277    /// get_singular_ctxs_by_hir_expr(1) == Err
278    /// get_singular_ctxs_by_hir_expr(Int) == [<type Int>, <type Type>, ...]
279    /// get_singular_ctxs_by_hir_expr(math) == [<module math>]
280    /// ```
281    pub fn get_singular_ctxs_by_hir_expr(
282        &self,
283        obj: &hir::Expr,
284        namespace: &Context,
285    ) -> SingleTyCheckResult<Vec<&Context>> {
286        match obj {
287            hir::Expr::Accessor(hir::Accessor::Ident(ident)) => {
288                // e.g. ident.t: {Int}
289                if let Ok(refine) = <&RefinementType>::try_from(ident.ref_t()) {
290                    if let Predicate::Equal { rhs, .. } = refine.pred.as_ref() {
291                        if let Ok(t) = <&Type>::try_from(rhs) {
292                            if let Some(ctxs) = self.get_nominal_super_type_ctxs(t) {
293                                return Ok(ctxs.into_iter().map(|ctx| &ctx.ctx).collect());
294                            }
295                        }
296                    }
297                }
298                self.get_singular_ctxs_by_ident(&ident.raw, namespace)
299            }
300            hir::Expr::Accessor(hir::Accessor::Attr(attr)) => {
301                // REVIEW: 両方singularとは限らない?
302                let mut ctxs = vec![];
303                for ctx in self.get_singular_ctxs_by_hir_expr(&attr.obj, namespace)? {
304                    ctxs.extend(ctx.get_singular_ctxs_by_ident(&attr.ident.raw, namespace)?);
305                }
306                Ok(ctxs)
307            }
308            hir::Expr::TypeAsc(tasc) => self.get_singular_ctxs_by_hir_expr(&tasc.expr, namespace),
309            // TODO: change error
310            _ => Err(TyCheckError::no_var_error(
311                self.cfg.input.clone(),
312                line!() as usize,
313                obj.loc(),
314                self.caused_by(),
315                &obj.to_string(),
316                None,
317            )),
318        }
319    }
320
321    pub(crate) fn get_singular_ctxs_by_ident(
322        &self,
323        ident: &ast::Identifier,
324        namespace: &Context,
325    ) -> SingleTyCheckResult<Vec<&Context>> {
326        self.get_mod(ident.inspect())
327            .map(|ctx| vec![ctx])
328            .or_else(|| {
329                let ctx = self.get_type_ctx(ident.inspect())?;
330                self.get_nominal_super_type_ctxs(&ctx.typ)
331                    .map(|ctxs| ctxs.into_iter().map(|ctx| &ctx.ctx).collect())
332            })
333            .or_else(|| self.rec_get_patch(ident.inspect()).map(|ctx| vec![ctx]))
334            .ok_or_else(|| {
335                let (similar_info, similar_name) =
336                    self.get_similar_name_and_info(ident.inspect()).unzip();
337                TyCheckError::detailed_no_var_error(
338                    self.cfg.input.clone(),
339                    line!() as usize,
340                    ident.loc(),
341                    namespace.name.to_string(),
342                    ident.inspect(),
343                    similar_name,
344                    similar_info,
345                )
346            })
347    }
348
349    #[allow(unused)]
350    pub(crate) fn get_mut_singular_ctxs_by_ident(
351        &mut self,
352        ident: &ast::Identifier,
353        namespace: &Str,
354    ) -> SingleTyCheckResult<&mut Context> {
355        self.get_mut_singular_ctxs_and_t_by_ident(ident, namespace)
356            .map(|ctx| &mut ctx.ctx)
357    }
358
359    pub(crate) fn get_mut_singular_ctxs_and_t_by_ident(
360        &mut self,
361        ident: &ast::Identifier,
362        namespace: &Str,
363    ) -> SingleTyCheckResult<&mut TypeContext> {
364        let err = TyCheckError::no_var_error(
365            self.cfg.input.clone(),
366            line!() as usize,
367            ident.loc(),
368            namespace.into(),
369            ident.inspect(),
370            self.get_similar_name(ident.inspect()),
371        );
372        self.rec_get_mut_type(ident.inspect()).ok_or(err)
373    }
374
375    pub(crate) fn get_singular_ctxs(
376        &self,
377        obj: &ast::Expr,
378        namespace: &Context,
379    ) -> SingleTyCheckResult<Vec<&Context>> {
380        match obj {
381            ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
382                self.get_singular_ctxs_by_ident(ident, namespace)
383            }
384            ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
385                let local_attr = ast::Expr::Accessor(ast::Accessor::Ident(attr.ident.clone()));
386                let mut ctxs = vec![];
387                // REVIEW: 両方singularとは限らない?
388                for ctx in self.get_singular_ctxs(&attr.obj, namespace)? {
389                    ctxs.extend(ctx.get_singular_ctxs(&local_attr, namespace)?);
390                }
391                Ok(ctxs)
392            }
393            ast::Expr::Accessor(ast::Accessor::TypeApp(tapp)) => {
394                self.get_singular_ctxs(&tapp.obj, namespace)
395            }
396            ast::Expr::Call(call) => self.get_singular_ctxs(&call.obj, namespace),
397            ast::Expr::TypeAscription(tasc) => self.get_singular_ctxs(&tasc.expr, namespace),
398            _ => Err(TyCheckError::no_var_error(
399                self.cfg.input.clone(),
400                line!() as usize,
401                obj.loc(),
402                self.caused_by(),
403                &obj.to_string(),
404                None,
405            )),
406        }
407    }
408
409    pub(crate) fn get_mut_singular_ctx_and_t(
410        &mut self,
411        obj: &ast::Expr,
412        namespace: &Str,
413    ) -> SingleTyCheckResult<&mut TypeContext> {
414        match obj {
415            ast::Expr::Accessor(ast::Accessor::Ident(ident)) => {
416                self.get_mut_singular_ctxs_and_t_by_ident(ident, namespace)
417            }
418            ast::Expr::Accessor(ast::Accessor::Attr(attr)) => {
419                // REVIEW: 両方singularとは限らない?
420                let ctx = self.get_mut_singular_ctx(&attr.obj, namespace)?;
421                let attr = ast::Expr::Accessor(ast::Accessor::Ident(attr.ident.clone()));
422                ctx.get_mut_singular_ctx_and_t(&attr, namespace)
423            }
424            ast::Expr::Accessor(ast::Accessor::TypeApp(tapp)) => {
425                self.get_mut_singular_ctx_and_t(&tapp.obj, namespace)
426            }
427            ast::Expr::Call(call) => self.get_mut_singular_ctx_and_t(&call.obj, namespace),
428            ast::Expr::TypeAscription(tasc) => {
429                self.get_mut_singular_ctx_and_t(&tasc.expr, namespace)
430            }
431            _ => Err(TyCheckError::no_var_error(
432                self.cfg.input.clone(),
433                line!() as usize,
434                obj.loc(),
435                self.caused_by(),
436                &obj.to_string(),
437                None,
438            )),
439        }
440    }
441
442    pub(crate) fn get_mut_singular_ctx(
443        &mut self,
444        obj: &ast::Expr,
445        namespace: &Str,
446    ) -> SingleTyCheckResult<&mut Context> {
447        self.get_mut_singular_ctx_and_t(obj, namespace)
448            .map(|ctx| &mut ctx.ctx)
449    }
450
451    fn get_match_call_t(
452        &self,
453        kind: SubrKind,
454        pos_args: &[hir::PosArg],
455        kw_args: &[hir::KwArg],
456    ) -> FailableOption<VarInfo> {
457        let mut errs = TyCheckErrors::empty();
458        if !kw_args.is_empty() {
459            // TODO: this error desc is not good
460            return Err((
461                None,
462                TyCheckErrors::from(TyCheckError::default_param_error(
463                    self.cfg.input.clone(),
464                    line!() as usize,
465                    kw_args[0].loc(),
466                    self.caused_by(),
467                    "match",
468                )),
469            ));
470        }
471        for pos_arg in pos_args.iter().skip(1) {
472            let t = pos_arg.expr.ref_t();
473            // Allow only anonymous functions to be passed as match arguments (for aesthetic reasons)
474            if !matches!(&pos_arg.expr, hir::Expr::Lambda(_)) {
475                return Err((
476                    None,
477                    TyCheckErrors::from(TyCheckError::type_mismatch_error(
478                        self.cfg.input.clone(),
479                        line!() as usize,
480                        pos_arg.loc(),
481                        self.caused_by(),
482                        "match",
483                        None,
484                        &mono("LambdaFunc"),
485                        t,
486                        self.get_candidates(t),
487                        self.get_simple_type_mismatch_hint(&mono("LambdaFunc"), t),
488                    )),
489                ));
490            }
491        }
492        let match_target_expr_t = pos_args[0].expr.ref_t();
493        // Never or T => T
494        let mut union_pat_t = Type::Never;
495        let mut arm_ts = vec![];
496        for (i, pos_arg) in pos_args.iter().skip(1).enumerate() {
497            let lambda = erg_common::enum_unwrap!(&pos_arg.expr, hir::Expr::Lambda); // already checked
498            if !lambda.params.defaults.is_empty() {
499                return Err((
500                    None,
501                    TyCheckErrors::from(TyCheckError::default_param_error(
502                        self.cfg.input.clone(),
503                        line!() as usize,
504                        pos_args[i + 1].loc(),
505                        self.caused_by(),
506                        "match",
507                    )),
508                ));
509            }
510            if lambda.params.len() != 1 {
511                return Err((
512                    None,
513                    TyCheckErrors::from(TyCheckError::param_error(
514                        self.cfg.input.clone(),
515                        line!() as usize,
516                        pos_args[i + 1].loc(),
517                        self.caused_by(),
518                        1,
519                        lambda.params.len(),
520                    )),
521                ));
522            }
523            let mut dummy_tv_cache = TyVarCache::new(self.level, self);
524            let rhs = match self.instantiate_param_sig_t(
525                &lambda.params.non_defaults[0].raw,
526                None,
527                &mut dummy_tv_cache,
528                Normal,
529                ParamKind::NonDefault,
530                false,
531            ) {
532                Ok(ty) => ty,
533                Err((ty, es)) => {
534                    errs.extend(es);
535                    ty
536                }
537            };
538            if lambda.params.non_defaults[0].raw.t_spec.is_none() && rhs.is_free_var() {
539                rhs.link(&Obj, None);
540            }
541            union_pat_t = self.union(&union_pat_t, &rhs);
542            arm_ts.push(rhs);
543        }
544        // NG: expr_t: Nat, union_pat_t: {1, 2}
545        // OK: expr_t: Int, union_pat_t: {1} or 'T
546        if let Err(err) = self.sub_unify(match_target_expr_t, &union_pat_t, &pos_args[0], None) {
547            if DEBUG_MODE {
548                eprintln!("match error: {err}");
549            }
550            errs.push(TyCheckError::match_error(
551                self.cfg.input.clone(),
552                line!() as usize,
553                pos_args[0].loc(),
554                self.caused_by(),
555                match_target_expr_t,
556                &union_pat_t,
557                arm_ts,
558            ));
559            return Err((None, errs));
560        }
561        let branch_ts = pos_args
562            .iter()
563            .skip(1)
564            .map(|a| ParamTy::Pos(a.expr.ref_t().clone()))
565            .collect::<Vec<_>>();
566        let Some(mut return_t) = branch_ts
567            .first()
568            .and_then(|branch| branch.typ().return_t().cloned())
569        else {
570            errs.push(TyCheckError::args_missing_error(
571                self.cfg.input.clone(),
572                line!() as usize,
573                pos_args[0].loc(),
574                "match",
575                self.caused_by(),
576                vec![Str::ever("obj")],
577            ));
578            return Err((None, errs));
579        };
580        for arg_t in branch_ts.iter().skip(1) {
581            return_t = self.union(&return_t, arg_t.typ().return_t().unwrap_or(&Type::Never));
582        }
583        let param_ty = ParamTy::Pos(match_target_expr_t.clone().into_ref());
584        let param_ts = [vec![param_ty], branch_ts.to_vec()].concat();
585        let t = if kind.is_func() {
586            func(param_ts, None, vec![], None, return_t)
587        } else {
588            proc(param_ts, None, vec![], None, return_t)
589        };
590        let vi = VarInfo {
591            t,
592            ..VarInfo::default()
593        };
594        if errs.is_empty() {
595            Ok(vi)
596        } else {
597            Err((Some(vi), errs))
598        }
599    }
600
601    pub(crate) fn rec_get_var_info(
602        &self,
603        ident: &Identifier,
604        acc_kind: AccessKind,
605        input: &Input,
606        namespace: &Context,
607    ) -> Triple<VarInfo, TyCheckError> {
608        if ident.inspect() == "Self" {
609            if let Some(self_t) = self.rec_get_self_t() {
610                return self.rec_get_var_info(
611                    &Identifier::auto(self_t.local_name()),
612                    acc_kind,
613                    input,
614                    namespace,
615                );
616            }
617        }
618        if let Some(vi) = self.get_current_scope_var(&ident.name) {
619            match self.validate_visibility(ident, vi, input, namespace) {
620                Ok(()) if acc_kind.matches(vi) => {
621                    return Triple::Ok(vi.clone());
622                }
623                Err(err) => {
624                    if !acc_kind.is_local() {
625                        return Triple::Err(err);
626                    }
627                }
628                _ => {}
629            }
630        } else if let Some((name, vi)) = self
631            .future_defined_locals
632            .get_key_value(&ident.inspect()[..])
633        {
634            if name.loc().is_real() && ident.loc() < name.loc() {
635                return Triple::Err(TyCheckError::access_before_def_error(
636                    input.clone(),
637                    line!() as usize,
638                    ident.loc(),
639                    namespace.name.to_string(),
640                    ident.inspect(),
641                    name.ln_begin().unwrap_or(0),
642                    self.get_similar_name(ident.inspect()),
643                ));
644            } else if ident.loc() == name.loc() {
645                return Triple::Ok(vi.clone());
646            }
647        } else if let Some((name, _vi)) = self.deleted_locals.get_key_value(&ident.inspect()[..]) {
648            return Triple::Err(TyCheckError::access_deleted_var_error(
649                input.clone(),
650                line!() as usize,
651                ident.loc(),
652                namespace.name.to_string(),
653                ident.inspect(),
654                name.ln_begin().unwrap_or(0),
655                self.get_similar_name(ident.inspect()),
656            ));
657        }
658        for method_ctx in self.methods_list.iter() {
659            match method_ctx.rec_get_var_info(ident, acc_kind, input, namespace) {
660                Triple::Ok(vi) => {
661                    return Triple::Ok(vi);
662                }
663                Triple::Err(e) => {
664                    return Triple::Err(e);
665                }
666                Triple::None => {}
667            }
668        }
669        if acc_kind.is_local() {
670            if let Some(parent) = self
671                .get_outer_scope()
672                .or_else(|| self.get_builtins_not_self())
673            {
674                return parent.rec_get_var_info(ident, acc_kind, input, namespace);
675            }
676        }
677        Triple::None
678    }
679
680    pub(crate) fn rec_get_mut_var_info(
681        &mut self,
682        ident: &Identifier,
683        acc_kind: AccessKind,
684    ) -> Option<&mut VarInfo> {
685        if let Some(vi) = self.get_current_scope_var(&ident.name) {
686            match self.validate_visibility(ident, vi, &self.cfg.input, self) {
687                Ok(()) if acc_kind.matches(vi) => {
688                    let vi = self.get_mut_current_scope_var(&ident.name).unwrap();
689                    return Some(vi);
690                }
691                Err(_err) => {
692                    if !acc_kind.is_local() {
693                        return None;
694                    }
695                }
696                _ => {}
697            }
698        }
699        if acc_kind.is_local() {
700            if let Some(parent) = self.get_mut_outer() {
701                return parent.rec_get_mut_var_info(ident, acc_kind);
702            }
703        } else {
704            for method_ctx in self.methods_list.iter_mut() {
705                if let Some(vi) = method_ctx.rec_get_mut_var_info(ident, acc_kind) {
706                    return Some(vi);
707                }
708            }
709        }
710        None
711    }
712
713    pub(crate) fn rec_get_decl_info(
714        &self,
715        ident: &Identifier,
716        acc_kind: AccessKind,
717        input: &Input,
718        namespace: &Context,
719    ) -> Triple<VarInfo, TyCheckError> {
720        if let Some(vi) = self
721            .decls
722            .get(&ident.inspect()[..])
723            .or_else(|| self.future_defined_locals.get(&ident.inspect()[..]))
724        {
725            match self.validate_visibility(ident, vi, input, namespace) {
726                Ok(()) if acc_kind.matches(vi) => {
727                    return Triple::Ok(vi.clone());
728                }
729                Err(err) => {
730                    if !acc_kind.is_local() {
731                        return Triple::Err(err);
732                    }
733                }
734                _ => {}
735            }
736        }
737        for method_ctx in self.methods_list.iter() {
738            match method_ctx.rec_get_decl_info(ident, acc_kind, input, namespace) {
739                Triple::Ok(vi) => {
740                    return Triple::Ok(vi);
741                }
742                Triple::Err(e) => {
743                    return Triple::Err(e);
744                }
745                Triple::None => {}
746            }
747        }
748        if acc_kind.is_local() {
749            if let Some(parent) = self
750                .get_outer_scope()
751                .or_else(|| self.get_builtins_not_self())
752            {
753                return parent.rec_get_decl_info(ident, acc_kind, input, namespace);
754            }
755        }
756        Triple::None
757    }
758
759    pub(crate) fn get_current_param_or_decl(&self, name: &str) -> Option<VarInfo> {
760        #[cfg(feature = "py_compat")]
761        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
762        if let Some(vi) = self
763            .params
764            .iter()
765            .find(|(var_name, _)| var_name.as_ref().is_some_and(|n| n.inspect() == name))
766            .map(|(_, vi)| vi)
767            .or_else(|| self.decls.get(name))
768        {
769            return Some(vi.clone());
770        }
771        for method_ctx in self.methods_list.iter() {
772            if let Some(vi) = method_ctx.get_current_param_or_decl(name) {
773                return Some(vi);
774            }
775        }
776        None
777    }
778
779    pub(crate) fn get_attr_info(
780        &self,
781        obj: &hir::Expr,
782        ident: &Identifier,
783        input: &Input,
784        namespace: &Context,
785        expect: Option<&Type>,
786    ) -> Triple<VarInfo, TyCheckError> {
787        // get_attr_info(?T, aaa) == None
788        // => ?T(<: Structural({ .aaa = ?U }))
789        if PYTHON_MODE
790            && obj
791                .var_info()
792                .is_some_and(|vi| vi.is_ambiguously_typed_parameter())
793        {
794            let constraint = expect.map_or(Constraint::new_type_of(Type), |t| {
795                Constraint::new_subtype_of(t.clone())
796            });
797            let t = free_var(self.level, constraint);
798            if let Some(fv) = obj.ref_t().as_free() {
799                if let Some((_sub, sup)) = fv.get_subsup() {
800                    let vis = self
801                        .instantiate_vis_modifier(&ident.vis)
802                        .unwrap_or(VisibilityModifier::Public);
803                    let structural = Type::Record(
804                        dict! { Field::new(vis, ident.inspect().clone()) => t.clone() },
805                    )
806                    .structuralize();
807                    let intersection = self.intersection(&sup, &structural);
808                    if intersection != Never {
809                        obj.ref_t().update_super(intersection, None, true);
810                    }
811                }
812            }
813            let muty = Mutability::from(&ident.inspect()[..]);
814            let vi = VarInfo::new(
815                t,
816                muty,
817                Visibility::DUMMY_PUBLIC,
818                VarKind::Builtin,
819                None,
820                ContextKind::Dummy,
821                None,
822                AbsLocation::unknown(),
823            );
824            return Triple::Ok(vi);
825        }
826        let self_t = obj.t();
827        match self.get_attr_info_from_attributive(&self_t, ident, namespace) {
828            Triple::Ok(vi) => {
829                return Triple::Ok(vi);
830            }
831            Triple::Err(e) => {
832                return Triple::Err(e);
833            }
834            _ => {}
835        }
836        // class/module attr
837        if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
838            for ctx in singular_ctxs {
839                match ctx.rec_get_var_info(ident, AccessKind::UnboundAttr, input, namespace) {
840                    Triple::Ok(vi) => {
841                        return Triple::Ok(vi);
842                    }
843                    Triple::Err(e) => {
844                        return Triple::Err(e);
845                    }
846                    Triple::None => {}
847                }
848            }
849        }
850        // bound method/instance attr
851        match self.get_bound_attr_from_nominal_t(obj, ident, input, namespace) {
852            Triple::Ok(vi) => {
853                if let Some(self_t) = vi.t.self_t() {
854                    let list = UndoableLinkedList::new();
855                    if let Err(errs) = self
856                        .undoable_sub_unify(obj.ref_t(), self_t, obj, &list, Some(&"self".into()))
857                        .map_err(|mut e| e.remove(0))
858                    {
859                        return Triple::Err(errs);
860                    }
861                    drop(list);
862                    let res =
863                        self.self_unify(obj.ref_t(), self_t, &vi.t, obj, Some(&"self".into()));
864                    if DEBUG_MODE {
865                        res.unwrap();
866                    }
867                }
868                return Triple::Ok(vi);
869            }
870            Triple::Err(e) => {
871                return Triple::Err(e);
872            }
873            _ => {}
874        }
875        for patch in self.find_patches_of(obj.ref_t()) {
876            if let Some(vi) = patch.get_current_scope_non_param(&ident.name) {
877                return match self.validate_visibility(ident, vi, input, namespace) {
878                    Ok(_) => Triple::Ok(vi.clone()),
879                    Err(e) => Triple::Err(e),
880                };
881            }
882            for methods_ctx in patch.methods_list.iter() {
883                if let Some(vi) = methods_ctx.get_current_scope_non_param(&ident.name) {
884                    return match self.validate_visibility(ident, vi, input, namespace) {
885                        Ok(_) => Triple::Ok(vi.clone()),
886                        Err(e) => Triple::Err(e),
887                    };
888                }
889            }
890        }
891        // REVIEW: get by name > coercion?
892        match self.get_attr_type_by_name(obj, ident, namespace) {
893            Triple::Ok(method) => {
894                let list = UndoableLinkedList::new();
895                if self
896                    .undoable_sub_unify(obj.ref_t(), &method.definition_type, obj, &list, None)
897                    .is_ok()
898                {
899                    drop(list);
900                    let res = self.sub_unify(obj.ref_t(), &method.definition_type, obj, None);
901                    if DEBUG_MODE {
902                        res.unwrap();
903                    }
904                    return Triple::Ok(method.method_info.clone());
905                }
906            }
907            Triple::Err(err) if ERG_MODE => {
908                return Triple::Err(err);
909            }
910            _ => {}
911        }
912        self.fallback_get_attr_info(obj, ident, input, namespace, expect)
913    }
914
915    fn fallback_get_attr_info(
916        &self,
917        obj: &hir::Expr,
918        ident: &Identifier,
919        input: &Input,
920        namespace: &Context,
921        expect: Option<&Type>,
922    ) -> Triple<VarInfo, TyCheckError> {
923        if let Ok(coerced) = self.coerce(obj.t(), &obj) {
924            if &coerced != obj.ref_t() {
925                let hash = get_hash(obj.ref_t());
926                let list = UndoableLinkedList::new();
927                obj.ref_t().undoable_coerce(&list);
928                if hash == get_hash(obj.ref_t()) {
929                    return Triple::None;
930                }
931                if let Triple::Ok(vi) = self.get_attr_info(obj, ident, input, namespace, expect) {
932                    drop(list);
933                    obj.ref_t().destructive_link(&coerced);
934                    return Triple::Ok(vi);
935                }
936            }
937        }
938        Triple::None
939    }
940
941    fn get_bound_attr_from_nominal_t(
942        &self,
943        obj: &hir::Expr,
944        ident: &Identifier,
945        input: &Input,
946        namespace: &Context,
947    ) -> Triple<VarInfo, TyCheckError> {
948        let self_t = obj.t().derefine().destructuralize();
949        // NOTE: get_nominal_super_type_ctxs({Nat}) == [<Nat>, ...], so we need to derefine
950        if let Some(sups) = self.get_nominal_super_type_ctxs(&self_t) {
951            for ctx in sups {
952                match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
953                    Triple::Ok(vi) => {
954                        return Triple::Ok(vi);
955                    }
956                    Triple::Err(e) => {
957                        return Triple::Err(e);
958                    }
959                    _ => {}
960                }
961                // if self is a methods context
962                if let Some(ctx) = self.get_same_name_context(&ctx.name) {
963                    match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
964                        Triple::Ok(vi) => {
965                            return Triple::Ok(vi);
966                        }
967                        Triple::Err(e) => {
968                            return Triple::Err(e);
969                        }
970                        _ => {}
971                    }
972                }
973            }
974        }
975        let coerced = match self.coerce(obj.t(), &()).map_err(|mut es| es.remove(0)) {
976            Ok(t) => t,
977            Err(e) => {
978                return Triple::Err(e);
979            }
980        };
981        if obj.ref_t() != &coerced {
982            let ctxs = match self.get_nominal_super_type_ctxs(&coerced).ok_or_else(|| {
983                TyCheckError::type_not_found(
984                    self.cfg.input.clone(),
985                    line!() as usize,
986                    obj.loc(),
987                    self.caused_by(),
988                    &coerced,
989                )
990            }) {
991                Ok(ctxs) => ctxs,
992                Err(e) => {
993                    return Triple::Err(e);
994                }
995            };
996            for ctx in ctxs {
997                match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
998                    Triple::Ok(vi) => {
999                        obj.ref_t().destructive_coerce();
1000                        return Triple::Ok(vi);
1001                    }
1002                    Triple::Err(e) => {
1003                        return Triple::Err(e);
1004                    }
1005                    _ => {}
1006                }
1007                if let Some(ctx) = self.get_same_name_context(&ctx.name) {
1008                    match ctx.rec_get_var_info(ident, AccessKind::BoundAttr, input, namespace) {
1009                        Triple::Ok(vi) => {
1010                            return Triple::Ok(vi);
1011                        }
1012                        Triple::Err(e) => {
1013                            return Triple::Err(e);
1014                        }
1015                        _ => {}
1016                    }
1017                }
1018            }
1019        }
1020        Triple::None
1021    }
1022
1023    /// get type from given attributive type (Record).
1024    /// not ModuleType or ClassType etc.
1025    /// if `t == Failure`, returns `VarInfo::ILLEGAL`
1026    fn get_attr_info_from_attributive(
1027        &self,
1028        t: &Type,
1029        ident: &Identifier,
1030        namespace: &Context,
1031    ) -> Triple<VarInfo, TyCheckError> {
1032        match t {
1033            // (obj: Failure).foo: Failure
1034            Type::Failure => Triple::Ok(VarInfo::ILLEGAL),
1035            Type::FreeVar(fv) if fv.is_linked() => {
1036                self.get_attr_info_from_attributive(&fv.unwrap_linked(), ident, namespace)
1037            }
1038            Type::FreeVar(fv) if fv.get_super().is_some() => {
1039                let sup = fv.get_super().unwrap();
1040                self.get_attr_info_from_attributive(&sup, ident, namespace)
1041            }
1042            Type::Ref(t) => self.get_attr_info_from_attributive(t, ident, namespace),
1043            Type::RefMut { before, .. } => {
1044                self.get_attr_info_from_attributive(before, ident, namespace)
1045            }
1046            Type::Refinement(refine) => {
1047                self.get_attr_info_from_attributive(&refine.t, ident, namespace)
1048            }
1049            Type::Record(record) => {
1050                if let Some((field, attr_t)) = record.get_key_value(ident.inspect()) {
1051                    let muty = Mutability::from(&ident.inspect()[..]);
1052                    let vi = VarInfo::new(
1053                        attr_t.clone(),
1054                        muty,
1055                        Visibility::new(field.vis.clone(), Str::ever("<dummy>")),
1056                        VarKind::Builtin,
1057                        None,
1058                        ContextKind::Record,
1059                        None,
1060                        AbsLocation::unknown(),
1061                    );
1062                    if let Err(err) =
1063                        self.validate_visibility(ident, &vi, &self.cfg.input, namespace)
1064                    {
1065                        return Triple::Err(err);
1066                    }
1067                    Triple::Ok(vi)
1068                } else {
1069                    Triple::None
1070                }
1071            }
1072            Type::NamedTuple(tuple) => {
1073                if let Some((field, attr_t)) =
1074                    tuple.iter().find(|(f, _)| &f.symbol == ident.inspect())
1075                {
1076                    let muty = Mutability::from(&ident.inspect()[..]);
1077                    let vi = VarInfo::new(
1078                        attr_t.clone(),
1079                        muty,
1080                        Visibility::new(field.vis.clone(), Str::ever("<dummy>")),
1081                        VarKind::Builtin,
1082                        None,
1083                        ContextKind::Record,
1084                        None,
1085                        AbsLocation::unknown(),
1086                    );
1087                    if let Err(err) =
1088                        self.validate_visibility(ident, &vi, &self.cfg.input, namespace)
1089                    {
1090                        return Triple::Err(err);
1091                    }
1092                    Triple::Ok(vi)
1093                } else {
1094                    Triple::None
1095                }
1096            }
1097            Type::Structural(t) => self.get_attr_info_from_attributive(t, ident, namespace),
1098            // TODO: And
1099            Type::Or(tys) => {
1100                let mut info = Triple::<VarInfo, _>::None;
1101                for ty in tys {
1102                    match (
1103                        self.get_attr_info_from_attributive(ty, ident, namespace),
1104                        &info,
1105                    ) {
1106                        (Triple::Ok(vi), Triple::Ok(vi_)) => {
1107                            let res = self.union(&vi.t, &vi_.t);
1108                            let vis = if vi.vis.is_public() && vi_.vis.is_public() {
1109                                Visibility::DUMMY_PUBLIC
1110                            } else {
1111                                Visibility::DUMMY_PRIVATE
1112                            };
1113                            let vi = VarInfo { t: res, vis, ..vi };
1114                            info = Triple::Ok(vi);
1115                        }
1116                        (Triple::Ok(vi), Triple::None) => {
1117                            info = Triple::Ok(vi);
1118                        }
1119                        (Triple::Err(err), _) => {
1120                            info = Triple::Err(err);
1121                            break;
1122                        }
1123                        (Triple::None, _) => {}
1124                        (_, Triple::Err(_)) => unreachable!(),
1125                    }
1126                }
1127                info
1128            }
1129            _other => Triple::None,
1130        }
1131    }
1132
1133    // returns callee's type, not the return type
1134    #[allow(clippy::too_many_arguments)]
1135    fn search_callee_info(
1136        &self,
1137        obj: &hir::Expr,
1138        attr_name: &Option<Identifier>,
1139        pos_args: &mut [hir::PosArg],
1140        kw_args: &[hir::KwArg],
1141        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
1142        input: &Input,
1143        namespace: &Context,
1144    ) -> SingleTyCheckResult<VarInfo> {
1145        if obj.ref_t() == Type::FAILURE {
1146            // (...Obj) -> Failure
1147            return Ok(VarInfo {
1148                t: Type::Subr(SubrType::new(
1149                    SubrKind::Func,
1150                    vec![],
1151                    Some(ParamTy::Pos(ref_(Obj))),
1152                    vec![],
1153                    Some(ParamTy::Pos(ref_(Obj))),
1154                    Failure,
1155                )),
1156                ..VarInfo::default()
1157            });
1158        }
1159        if let Some(attr_name) = attr_name.as_ref() {
1160            let mut vi =
1161                self.search_method_info(obj, attr_name, pos_args, kw_args, input, namespace)?;
1162            vi.t = self.resolve_overload(
1163                obj,
1164                vi.t,
1165                pos_args,
1166                kw_args,
1167                (var_args, kw_var_args),
1168                attr_name,
1169            )?;
1170            Ok(vi)
1171        } else {
1172            let t = self.resolve_overload(
1173                obj,
1174                obj.t(),
1175                pos_args,
1176                kw_args,
1177                (var_args, kw_var_args),
1178                obj,
1179            )?;
1180            Ok(VarInfo {
1181                t,
1182                ..VarInfo::default()
1183            })
1184        }
1185    }
1186
1187    fn search_callee_info_without_args(
1188        &self,
1189        obj: &hir::Expr,
1190        attr_name: &Option<Identifier>,
1191        input: &Input,
1192        namespace: &Context,
1193    ) -> SingleTyCheckResult<VarInfo> {
1194        if obj.ref_t() == Type::FAILURE {
1195            // (...Obj) -> Failure
1196            return Ok(VarInfo {
1197                t: Type::Subr(SubrType::new(
1198                    SubrKind::Func,
1199                    vec![],
1200                    Some(ParamTy::Pos(ref_(Obj))),
1201                    vec![],
1202                    Some(ParamTy::Pos(ref_(Obj))),
1203                    Failure,
1204                )),
1205                ..VarInfo::default()
1206            });
1207        }
1208        if let Some(attr_name) = attr_name.as_ref() {
1209            self.search_method_info_without_args(obj, attr_name, input, namespace)
1210        } else {
1211            Ok(VarInfo {
1212                t: obj.t(),
1213                ..VarInfo::default()
1214            })
1215        }
1216    }
1217
1218    /// ```erg
1219    /// resolve_overload(obj, (|T|T -> T and (Int, Str) -> Str), [1], ...) => OK(|T| T -> T)
1220    /// ```
1221    fn resolve_overload(
1222        &self,
1223        obj: &hir::Expr,
1224        instance: Type,
1225        pos_args: &[hir::PosArg],
1226        kw_args: &[hir::KwArg],
1227        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
1228        loc: &impl Locational,
1229    ) -> SingleTyCheckResult<Type> {
1230        let intersecs = instance.intersection_types();
1231        if intersecs.len() == 1 {
1232            Ok(instance)
1233        } else {
1234            let mut input_t = subr_t(
1235                SubrKind::Proc,
1236                pos_args
1237                    .iter()
1238                    .map(|pos| ParamTy::Pos(pos.expr.t()))
1239                    .collect(),
1240                None,
1241                kw_args
1242                    .iter()
1243                    .map(|kw| ParamTy::kw(kw.keyword.content.clone(), kw.expr.t()))
1244                    .collect(),
1245                None,
1246                Obj,
1247            );
1248            for ty in intersecs.iter() {
1249                match (ty.is_method(), input_t.is_method()) {
1250                    (true, false) => {
1251                        let Type::Subr(sub) = &mut input_t else {
1252                            unreachable!()
1253                        };
1254                        sub.non_default_params
1255                            .insert(0, ParamTy::kw(Str::ever("self"), obj.t()));
1256                    }
1257                    (false, true) => {
1258                        let Type::Subr(sub) = &mut input_t else {
1259                            unreachable!()
1260                        };
1261                        sub.non_default_params.remove(0);
1262                    }
1263                    _ => {}
1264                }
1265                if self.subtype_of(ty, &input_t) {
1266                    if let Ok(instance) = self.instantiate(ty.clone(), obj) {
1267                        let subst = self
1268                            .substitute_call(
1269                                obj,
1270                                &None,
1271                                &instance,
1272                                pos_args,
1273                                kw_args,
1274                                (var_args, kw_var_args),
1275                                self,
1276                            )
1277                            .is_ok();
1278                        let eval = self.eval_t_params(instance, self.level, obj).is_ok();
1279                        if subst && eval {
1280                            debug_assert!(!ty.is_intersection_type());
1281                            return Ok(ty.clone());
1282                        }
1283                    }
1284                }
1285            }
1286            if let Some(default) = instance.default_intersection_type() {
1287                debug_assert!(!default.is_intersection_type());
1288                return Ok(default.clone());
1289            }
1290            let Type::Subr(subr_t) = input_t else {
1291                unreachable!()
1292            };
1293            let non_default_params = subr_t
1294                .non_default_params
1295                .iter()
1296                .map(|pt| pt.clone().map_type(&mut |t| self.readable_type(t)));
1297            let default_params = subr_t
1298                .default_params
1299                .iter()
1300                .map(|pt| pt.clone().map_type(&mut |t| self.readable_type(t)));
1301            Err(TyCheckError::overload_error(
1302                self.cfg.input.clone(),
1303                line!() as usize,
1304                loc.loc(),
1305                self.caused_by(),
1306                non_default_params,
1307                default_params,
1308                intersecs.iter(),
1309            ))
1310        }
1311    }
1312
1313    pub(crate) fn get_same_name_context(&self, name: &str) -> Option<&Context> {
1314        if &self.name[..] == name {
1315            Some(self)
1316        } else {
1317            self.get_outer_scope()
1318                .and_then(|p| p.get_same_name_context(name))
1319        }
1320    }
1321
1322    pub(crate) fn get_no_attr_hint(&self, self_t: &Type, attr: &str) -> Option<String> {
1323        self.get_similar_attr(self_t, attr).map(|n| {
1324            switch_lang!(
1325                "japanese" => format!("似た名前の属性があります: {n}"),
1326                "simplified_chinese" => format!("具有相同名称的属性: {n}"),
1327                "traditional_chinese" => format!("具有相同名稱的屬性: {n}"),
1328                "english" => format!("has a similar name attribute: {n}"),
1329            )
1330        }).or_else(|| {
1331            let unions = self_t.union_types()?;
1332            let mismatches = unions.iter().filter(|t| {
1333                !self.exists_attr(t, attr)
1334            }).collect::<Vec<_>>();
1335            if !mismatches.is_empty() && unions.len() != mismatches.len() {
1336                return Some(switch_lang!(
1337                    "japanese" => format!("{}型でないことを確かめる必要があります", fmt_vec(&mismatches)),
1338                    "simplified_chinese" => format!("需要确认不是{}类型", fmt_vec(&mismatches)),
1339                    "traditional_chinese" => format!("需要確認不是{}類型", fmt_vec(&mismatches)),
1340                    "english" => format!("You need to confirm that the receiver is not type of {}", fmt_vec(&mismatches)),
1341                ));
1342            }
1343            None
1344        })
1345    }
1346
1347    // Note that the method may be static.
1348    fn search_method_info(
1349        &self,
1350        obj: &hir::Expr,
1351        attr_name: &Identifier,
1352        pos_args: &[hir::PosArg],
1353        kw_args: &[hir::KwArg],
1354        input: &Input,
1355        namespace: &Context,
1356    ) -> SingleTyCheckResult<VarInfo> {
1357        // search_method_info(?T, aaa, pos_args: [1, 2]) == None
1358        // => ?T(<: Structural({ .aaa = (self: ?T, ?U, ?V) -> ?W }))
1359        // search_method_info(?T, aaa, kw_args: [b:=1, c:=2]) == None
1360        // => ?T(<: Structural({ .aaa = (self: ?T, b: ?U, c: ?V) -> ?W }))
1361        if PYTHON_MODE
1362            && obj
1363                .var_info()
1364                .is_some_and(|vi| vi.is_ambiguously_typed_parameter())
1365        {
1366            let nd_params = pos_args
1367                .iter()
1368                .map(|_| ParamTy::Pos(free_var(self.level, Constraint::new_type_of(Type))))
1369                .collect::<Vec<_>>();
1370            let d_params = kw_args
1371                .iter()
1372                .map(|arg| {
1373                    ParamTy::kw(
1374                        arg.keyword.inspect().clone(),
1375                        free_var(self.level, Constraint::new_type_of(Type)),
1376                    )
1377                })
1378                .collect::<Vec<_>>();
1379            let return_t = free_var(self.level, Constraint::new_type_of(Type));
1380            let mut subr_t = fn_met(obj.t(), nd_params, None, d_params, None, return_t);
1381            if let Some(fv) = obj.ref_t().as_free() {
1382                if let Some((_sub, sup)) = fv.get_subsup() {
1383                    // avoid recursion
1384                    *subr_t.mut_self_t().unwrap() = Failure;
1385                    let vis = self
1386                        .instantiate_vis_modifier(&attr_name.vis)
1387                        .unwrap_or(VisibilityModifier::Public);
1388                    let structural = Type::Record(
1389                        dict! { Field::new(vis, attr_name.inspect().clone()) => subr_t.clone() },
1390                    )
1391                    .structuralize();
1392                    let intersection = self.intersection(&sup, &structural);
1393                    if intersection != Never {
1394                        obj.ref_t().update_super(intersection, None, true);
1395                    }
1396                }
1397            }
1398            let muty = Mutability::from(&attr_name.inspect()[..]);
1399            let vi = VarInfo::new(
1400                subr_t,
1401                muty,
1402                Visibility::DUMMY_PUBLIC,
1403                VarKind::Builtin,
1404                None,
1405                ContextKind::Dummy,
1406                None,
1407                AbsLocation::unknown(),
1408            );
1409            return Ok(vi);
1410        }
1411        match self.get_attr_info_from_attributive(obj.ref_t(), attr_name, namespace) {
1412            Triple::Ok(vi) => {
1413                return Ok(vi);
1414            }
1415            Triple::Err(e) => {
1416                return Err(e);
1417            }
1418            _ => {}
1419        }
1420        if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
1421            for ctx in singular_ctxs {
1422                if let Some(vi) = ctx.get_current_scope_non_param(&attr_name.name) {
1423                    self.validate_visibility(attr_name, vi, input, namespace)?;
1424                    return Ok(vi.clone());
1425                }
1426                for method_ctx in ctx.methods_list.iter() {
1427                    if let Some(vi) = method_ctx.get_current_scope_non_param(&attr_name.name) {
1428                        self.validate_visibility(attr_name, vi, input, namespace)?;
1429                        return Ok(vi.clone());
1430                    }
1431                }
1432            }
1433        }
1434        let mut checked = vec![];
1435        // FIXME: tests/should_ok/collection.er
1436        let obj_t = if obj.ref_t().lower_bounded().is_dict() {
1437            obj.t()
1438        } else {
1439            obj.ref_t().lower_bounded()
1440        };
1441        for ctx in self.get_nominal_super_type_ctxs(&obj_t).ok_or_else(|| {
1442            TyCheckError::type_not_found(
1443                self.cfg.input.clone(),
1444                line!() as usize,
1445                obj.loc(),
1446                self.caused_by(),
1447                obj.ref_t(),
1448            )
1449        })? {
1450            checked.push(&ctx.typ);
1451            if let Some(vi) = ctx.get_current_scope_non_param(&attr_name.name) {
1452                self.validate_visibility(attr_name, vi, input, namespace)?;
1453                return Ok(vi.clone());
1454            }
1455            for methods_ctx in ctx.methods_list.iter() {
1456                if let Some(vi) = methods_ctx.get_current_scope_non_param(&attr_name.name) {
1457                    self.validate_visibility(attr_name, vi, input, namespace)?;
1458                    return Ok(vi.clone());
1459                }
1460            }
1461            if let Some(ctx) = self.get_same_name_context(&ctx.name) {
1462                match ctx.rec_get_var_info(attr_name, AccessKind::BoundAttr, input, namespace) {
1463                    Triple::Ok(t) => {
1464                        return Ok(t);
1465                    }
1466                    Triple::Err(e) => {
1467                        return Err(e);
1468                    }
1469                    Triple::None => {}
1470                }
1471            }
1472        }
1473        if obj.ref_t() != &obj.ref_t().lower_bounded() {
1474            for ctx in self
1475                .get_nominal_super_type_ctxs(obj.ref_t())
1476                .ok_or_else(|| {
1477                    TyCheckError::type_not_found(
1478                        self.cfg.input.clone(),
1479                        line!() as usize,
1480                        obj.loc(),
1481                        self.caused_by(),
1482                        obj.ref_t(),
1483                    )
1484                })?
1485            {
1486                if checked.contains(&&ctx.typ) {
1487                    continue;
1488                }
1489                if let Some(vi) = ctx.get_current_scope_non_param(&attr_name.name) {
1490                    self.validate_visibility(attr_name, vi, input, namespace)?;
1491                    return Ok(vi.clone());
1492                }
1493                for methods_ctx in ctx.methods_list.iter() {
1494                    if let Some(vi) = methods_ctx.get_current_scope_non_param(&attr_name.name) {
1495                        self.validate_visibility(attr_name, vi, input, namespace)?;
1496                        return Ok(vi.clone());
1497                    }
1498                }
1499                if let Some(ctx) = self.get_same_name_context(&ctx.name) {
1500                    match ctx.rec_get_var_info(attr_name, AccessKind::BoundAttr, input, namespace) {
1501                        Triple::Ok(t) => {
1502                            return Ok(t);
1503                        }
1504                        Triple::Err(e) => {
1505                            return Err(e);
1506                        }
1507                        Triple::None => {}
1508                    }
1509                }
1510            }
1511        }
1512        match self.get_attr_type_by_name(obj, attr_name, namespace) {
1513            Triple::Ok(method) => {
1514                let def_t = self
1515                    .instantiate_def_type(&method.definition_type)
1516                    .map_err(|mut errs| errs.remove(0))?;
1517                let list = UndoableLinkedList::new();
1518                self.undoable_sub_unify(obj.ref_t(), &def_t, obj, &list, None)
1519                    // HACK: change this func's return type to TyCheckResult<Type>
1520                    .map_err(|mut errs| errs.remove(0))?;
1521                drop(list);
1522                let res = self.sub_unify(obj.ref_t(), &def_t, obj, None);
1523                if DEBUG_MODE {
1524                    res.unwrap();
1525                }
1526                return Ok(method.method_info.clone());
1527            }
1528            Triple::Err(err) if ERG_MODE => {
1529                return Err(err);
1530            }
1531            _ => {}
1532        }
1533        if PYTHON_MODE {
1534            if let Some(subr_t) = self.get_union_attr_type_by_name(attr_name) {
1535                let muty = Mutability::from(&attr_name.inspect()[..]);
1536                let vi = VarInfo::new(
1537                    subr_t,
1538                    muty,
1539                    Visibility::DUMMY_PUBLIC,
1540                    VarKind::Builtin,
1541                    None,
1542                    ContextKind::Dummy,
1543                    None,
1544                    AbsLocation::unknown(),
1545                );
1546                return Ok(vi);
1547            }
1548        } else {
1549            for patch in self.find_patches_of(obj.ref_t()) {
1550                if let Some(vi) = patch.get_current_scope_non_param(&attr_name.name) {
1551                    self.validate_visibility(attr_name, vi, input, namespace)?;
1552                    return Ok(vi.clone());
1553                }
1554                for methods_ctx in patch.methods_list.iter() {
1555                    if let Some(vi) = methods_ctx.get_current_scope_non_param(&attr_name.name) {
1556                        self.validate_visibility(attr_name, vi, input, namespace)?;
1557                        return Ok(vi.clone());
1558                    }
1559                }
1560            }
1561        }
1562        let coerced = self
1563            .coerce(obj.t(), &())
1564            .map_err(|mut errs| errs.remove(0))?;
1565        if coerced != Never && &coerced != obj.ref_t() && obj.ref_t().as_free().is_some() {
1566            let hash = get_hash(obj.ref_t());
1567            obj.ref_t().destructive_link(&coerced); // obj.ref_t().coerce(None);
1568            if get_hash(obj.ref_t()) != hash {
1569                return self
1570                    .search_method_info(obj, attr_name, pos_args, kw_args, input, namespace);
1571            }
1572        }
1573        Err(TyCheckError::no_attr_error(
1574            self.cfg.input.clone(),
1575            line!() as usize,
1576            attr_name.loc(),
1577            namespace.name.to_string(),
1578            obj.ref_t(),
1579            attr_name.inspect(),
1580            self.get_no_attr_hint(obj.ref_t(), attr_name.inspect()),
1581        ))
1582    }
1583
1584    fn search_method_info_without_args(
1585        &self,
1586        obj: &hir::Expr,
1587        attr_name: &Identifier,
1588        input: &Input,
1589        namespace: &Context,
1590    ) -> SingleTyCheckResult<VarInfo> {
1591        match self.get_attr_info_from_attributive(obj.ref_t(), attr_name, namespace) {
1592            Triple::Ok(vi) => {
1593                return Ok(vi);
1594            }
1595            Triple::Err(e) => {
1596                return Err(e);
1597            }
1598            _ => {}
1599        }
1600        if let Ok(singular_ctxs) = self.get_singular_ctxs_by_hir_expr(obj, namespace) {
1601            for ctx in singular_ctxs {
1602                if let Some(vi) = ctx.get_current_scope_callable(&attr_name.name) {
1603                    self.validate_visibility(attr_name, vi, input, namespace)?;
1604                    return Ok(vi.clone());
1605                }
1606                for method_ctx in ctx.methods_list.iter() {
1607                    if let Some(vi) = method_ctx.get_current_scope_callable(&attr_name.name) {
1608                        self.validate_visibility(attr_name, vi, input, namespace)?;
1609                        return Ok(vi.clone());
1610                    }
1611                }
1612            }
1613        }
1614        for ctx in self
1615            .get_nominal_super_type_ctxs(obj.ref_t())
1616            .ok_or_else(|| {
1617                TyCheckError::type_not_found(
1618                    self.cfg.input.clone(),
1619                    line!() as usize,
1620                    obj.loc(),
1621                    self.caused_by(),
1622                    obj.ref_t(),
1623                )
1624            })?
1625        {
1626            if let Some(vi) = ctx.get_current_scope_callable(&attr_name.name) {
1627                self.validate_visibility(attr_name, vi, input, namespace)?;
1628                return Ok(vi.clone());
1629            }
1630            for methods_ctx in ctx.methods_list.iter() {
1631                if let Some(vi) = methods_ctx.get_current_scope_callable(&attr_name.name) {
1632                    self.validate_visibility(attr_name, vi, input, namespace)?;
1633                    return Ok(vi.clone());
1634                }
1635            }
1636            if let Some(ctx) = self.get_same_name_context(&ctx.name) {
1637                match ctx.rec_get_var_info(attr_name, AccessKind::BoundAttr, input, namespace) {
1638                    Triple::Ok(vi) => {
1639                        return Ok(vi);
1640                    }
1641                    Triple::Err(e) => {
1642                        return Err(e);
1643                    }
1644                    Triple::None => {}
1645                }
1646            }
1647        }
1648        match self.get_attr_type_by_name(obj, attr_name, namespace) {
1649            Triple::Ok(method) => {
1650                let def_t = self
1651                    .instantiate_def_type(&method.definition_type)
1652                    .map_err(|mut errs| errs.remove(0))?;
1653                let list = UndoableLinkedList::new();
1654                self.undoable_sub_unify(obj.ref_t(), &def_t, obj, &list, None)
1655                    // HACK: change this func's return type to TyCheckResult<Type>
1656                    .map_err(|mut errs| errs.remove(0))?;
1657                drop(list);
1658                let res = self.sub_unify(obj.ref_t(), &def_t, obj, None);
1659                if DEBUG_MODE {
1660                    res.unwrap();
1661                }
1662                return Ok(method.method_info.clone());
1663            }
1664            Triple::Err(err) if ERG_MODE => {
1665                return Err(err);
1666            }
1667            _ => {}
1668        }
1669        if PYTHON_MODE {
1670            if let Some(subr_t) = self.get_union_attr_type_by_name(attr_name) {
1671                let muty = Mutability::from(&attr_name.inspect()[..]);
1672                let vi = VarInfo::new(
1673                    subr_t,
1674                    muty,
1675                    Visibility::DUMMY_PUBLIC,
1676                    VarKind::Builtin,
1677                    None,
1678                    ContextKind::Dummy,
1679                    None,
1680                    AbsLocation::unknown(),
1681                );
1682                return Ok(vi);
1683            }
1684        } else {
1685            for patch in self.find_patches_of(obj.ref_t()) {
1686                if let Some(vi) = patch.get_current_scope_callable(&attr_name.name) {
1687                    self.validate_visibility(attr_name, vi, input, namespace)?;
1688                    return Ok(vi.clone());
1689                }
1690                for methods_ctx in patch.methods_list.iter() {
1691                    if let Some(vi) = methods_ctx.get_current_scope_callable(&attr_name.name) {
1692                        self.validate_visibility(attr_name, vi, input, namespace)?;
1693                        return Ok(vi.clone());
1694                    }
1695                }
1696            }
1697        }
1698        let coerced = self
1699            .coerce(obj.t(), &())
1700            .map_err(|mut errs| errs.remove(0))?;
1701        // REVIEW: if obj.ref_t() is not a free-var but contains free-vars
1702        if coerced != Never && &coerced != obj.ref_t() && obj.ref_t().as_free().is_some() {
1703            let hash = get_hash(obj.ref_t());
1704            obj.ref_t().destructive_link(&coerced); // obj.ref_t().coerce(None);
1705            if get_hash(obj.ref_t()) != hash {
1706                return self.search_method_info_without_args(obj, attr_name, input, namespace);
1707            }
1708        }
1709        Err(TyCheckError::no_attr_error(
1710            self.cfg.input.clone(),
1711            line!() as usize,
1712            attr_name.loc(),
1713            namespace.name.to_string(),
1714            obj.ref_t(),
1715            attr_name.inspect(),
1716            self.get_no_attr_hint(obj.ref_t(), attr_name.inspect()),
1717        ))
1718    }
1719
1720    pub(crate) fn validate_visibility(
1721        &self,
1722        ident: &Identifier,
1723        vi: &VarInfo,
1724        input: &Input,
1725        namespace: &Context,
1726    ) -> SingleTyCheckResult<()> {
1727        if vi.vis.compatible(&ident.acc_kind(), namespace) {
1728            Ok(())
1729        } else {
1730            Err(TyCheckError::visibility_error(
1731                input.clone(),
1732                line!() as usize,
1733                ident.loc(),
1734                self.caused_by(),
1735                ident.inspect(),
1736                vi.vis.clone(),
1737            ))
1738        }
1739    }
1740
1741    // HACK: dname.loc()はダミーLocationしか返さないので、エラーならop.loc()で上書きする
1742    fn append_loc_info(&self, e: TyCheckError, loc: Location) -> TyCheckError {
1743        if e.core.loc == Location::Unknown {
1744            let mut sub_msgs = Vec::new();
1745            for sub_msg in e.core.sub_messages {
1746                sub_msgs.push(SubMessage::ambiguous_new(loc, sub_msg.msg, sub_msg.hint));
1747            }
1748            let core = ErrorCore::new(
1749                sub_msgs,
1750                e.core.main_message,
1751                e.core.errno,
1752                e.core.kind,
1753                e.core.loc,
1754            );
1755            TyCheckError::new(core, self.cfg.input.clone(), e.caused_by)
1756        } else {
1757            e
1758        }
1759    }
1760
1761    pub(crate) fn get_binop_t(
1762        &self,
1763        op: &Token,
1764        args: &mut [hir::PosArg],
1765        input: &Input,
1766        namespace: &Context,
1767    ) -> TyCheckResult<VarInfo> {
1768        erg_common::debug_power_assert!(args.len() == 2);
1769        let Some(cont) = binop_to_dname(op.inspect()) else {
1770            return Err(TyCheckError::no_var_error(
1771                self.cfg.input.clone(),
1772                line!() as usize,
1773                op.loc(),
1774                namespace.caused_by(),
1775                op.inspect(),
1776                None,
1777            )
1778            .into());
1779        };
1780        // not a `Token::from_str(op.kind, cont)` because ops are defined as symbols
1781        let symbol = Token::symbol_with_loc(Str::rc(cont), Location::concat(&args[0], &args[1]));
1782        let ident = Identifier::private_from_token(symbol.clone());
1783        let t = self
1784            .rec_get_var_info(&ident, AccessKind::Name, input, namespace)
1785            .none_or_result(|| {
1786                let (similar_info, similar_name) =
1787                    namespace.get_similar_name_and_info(ident.inspect()).unzip();
1788                TyCheckError::detailed_no_var_error(
1789                    self.cfg.input.clone(),
1790                    line!() as usize,
1791                    ident.loc(),
1792                    namespace.caused_by(),
1793                    ident.inspect(),
1794                    similar_name,
1795                    similar_info,
1796                )
1797            })?;
1798        let op = hir::Expr::Accessor(hir::Accessor::private(symbol, t));
1799        self.get_call_t(&op, &None, args, &[], (None, None), input, namespace)
1800            .map_err(|(_, errs)| {
1801                let hir::Expr::Accessor(hir::Accessor::Ident(op_ident)) = op else {
1802                    return errs;
1803                };
1804                let vi = op_ident.vi.clone();
1805                let lhs = args[0].expr.clone();
1806                let rhs = args[1].expr.clone();
1807                let bin = hir::BinOp::new(op_ident.raw.name.into_token(), lhs, rhs, vi);
1808                let errs = errs
1809                    .into_iter()
1810                    .map(|e| self.append_loc_info(e, bin.loc()))
1811                    .collect();
1812                TyCheckErrors::new(errs)
1813            })
1814    }
1815
1816    pub(crate) fn get_unaryop_t(
1817        &self,
1818        op: &Token,
1819        args: &mut [hir::PosArg],
1820        input: &Input,
1821        namespace: &Context,
1822    ) -> TyCheckResult<VarInfo> {
1823        erg_common::debug_power_assert!(args.len() == 1);
1824        let Some(cont) = unaryop_to_dname(op.inspect()) else {
1825            return Err(TyCheckError::no_var_error(
1826                self.cfg.input.clone(),
1827                line!() as usize,
1828                op.loc(),
1829                namespace.caused_by(),
1830                op.inspect(),
1831                None,
1832            )
1833            .into());
1834        };
1835        let symbol = Token::symbol(cont);
1836        let ident = Identifier::private_from_token(symbol.clone());
1837        let vi = self
1838            .rec_get_var_info(&ident, AccessKind::Name, input, namespace)
1839            .none_or_result(|| {
1840                let (similar_info, similar_name) =
1841                    namespace.get_similar_name_and_info(ident.inspect()).unzip();
1842                TyCheckError::detailed_no_var_error(
1843                    self.cfg.input.clone(),
1844                    line!() as usize,
1845                    ident.loc(),
1846                    namespace.caused_by(),
1847                    ident.inspect(),
1848                    similar_name,
1849                    similar_info,
1850                )
1851            })?;
1852        let op = hir::Expr::Accessor(hir::Accessor::private(symbol, vi));
1853        self.get_call_t(&op, &None, args, &[], (None, None), input, namespace)
1854            .map_err(|(_, errs)| {
1855                let hir::Expr::Accessor(hir::Accessor::Ident(op_ident)) = op else {
1856                    return errs;
1857                };
1858                let vi = op_ident.vi.clone();
1859                let expr = args[0].expr.clone();
1860                let unary = hir::UnaryOp::new(op_ident.raw.name.into_token(), expr, vi);
1861                let errs = errs
1862                    .into_iter()
1863                    .map(|e| self.append_loc_info(e, unary.loc()))
1864                    .collect();
1865                TyCheckErrors::new(errs)
1866            })
1867    }
1868
1869    /// Propagate mutable dependent types changes
1870    /// 可変依存型の変更を伝搬させる
1871    /// ```erg
1872    /// v = ![] # Γ: { v: [Int; 0]! }
1873    /// v.push! 1 # v: [Int; 0]! ~> [Int; 1]!; Γ: { v: [Int; 1]! }
1874    /// v # : [Int; 1]!
1875    /// ```
1876    pub(crate) fn propagate(
1877        &mut self,
1878        subr_t: &mut Type,
1879        receiver: &hir::Expr,
1880    ) -> TyCheckResult<()> {
1881        if let Type::Subr(subr) = subr_t {
1882            if let Some(self_t) = subr.mut_self_t() {
1883                log!(info "Propagating:\n {self_t}");
1884                if let RefMut {
1885                    after: Some(after), ..
1886                } = self_t
1887                {
1888                    log!(info "~> {after}\n");
1889                    *self_t = *after.clone();
1890                    if let Some(ident) = receiver.as_ident() {
1891                        if let Some(vi) = self.rec_get_mut_var_info(&ident.raw, AccessKind::Name) {
1892                            vi.t = self_t.clone();
1893                        }
1894                    }
1895                }
1896            }
1897            Ok(())
1898        } else {
1899            Ok(())
1900        }
1901    }
1902
1903    fn not_callable_error(
1904        &self,
1905        obj: &hir::Expr,
1906        attr_name: &Option<Identifier>,
1907        other: &Type,
1908        hint: Option<String>,
1909    ) -> TyCheckErrors {
1910        let (loc, name) = if let Some(attr_name) = attr_name {
1911            (
1912                Location::concat(obj, attr_name),
1913                (obj.to_string() + &attr_name.to_string()),
1914            )
1915        } else {
1916            (obj.loc(), obj.to_string())
1917        };
1918        let other = self.readable_type(other.clone());
1919        TyCheckErrors::from(TyCheckError::type_mismatch_error(
1920            self.cfg.input.clone(),
1921            line!() as usize,
1922            loc,
1923            self.caused_by(),
1924            &name,
1925            None,
1926            &mono("Callable"),
1927            &other,
1928            self.get_candidates(&other),
1929            hint,
1930        ))
1931    }
1932
1933    /// if `obj` has `__call__` method, then the return value is `Some(call_instance)`
1934    ///
1935    /// e.g.
1936    /// ```python
1937    /// substitute_call(instance: ((?T, ?U) -> ?T), [Int, Str], []) => instance: (Int, Str) -> Int
1938    /// substitute_call(instance: ((?T, Int) -> ?T), [Int, Nat], []) => instance: (Int, Int) -> Str
1939    /// substitute_call(instance: ((?M(: Nat)..?N(: Nat)) -> ?M+?N), [1..2], []) => instance: (1..2) -> {3}
1940    /// substitute_call(instance: ((?L(: Add(?R, ?O)), ?R) -> ?O), [1, 2], []) => instance: (Nat, Nat) -> Nat
1941    /// substitute_call(instance: ((Failure, ?T) -> ?T), [Int, Int]) => instance: (Failure, Int) -> Int
1942    /// substitute_call(instance: (|T|T -> T, [1]) => Err(...) # instance must be instantiated
1943    /// substitute_call(instance: (|T|T -> T and (Int, Int) -> Int, [1]) => instance(Coerced): Int -> Int
1944    /// ↓ don't substitute `Int` to `self`
1945    /// substitute_call(obj: Int, instance: ((self: Int, other: Int) -> Int), [1, 2]) => instance: (Int, Int) -> Int
1946    /// ```
1947    #[allow(clippy::too_many_arguments)]
1948    fn substitute_call(
1949        &self,
1950        obj: &hir::Expr,
1951        attr_name: &Option<Identifier>,
1952        instance: &Type,
1953        pos_args: &[hir::PosArg],
1954        kw_args: &[hir::KwArg],
1955        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
1956        namespace: &Context,
1957    ) -> TyCheckResult<SubstituteResult> {
1958        match instance {
1959            Type::FreeVar(fv) if fv.is_linked() => self.substitute_call(
1960                obj,
1961                attr_name,
1962                &fv.unwrap_linked(),
1963                pos_args,
1964                kw_args,
1965                (var_args, kw_var_args),
1966                namespace,
1967            ),
1968            Type::FreeVar(fv) => {
1969                if let Some(sub) = fv.get_sub() {
1970                    fv.dummy_link();
1971                    let subtype_of = self.subtype_of(&sub, &mono("GenericCallable"));
1972                    fv.undo();
1973                    if !subtype_of {
1974                        return Err(self.not_callable_error(obj, attr_name, instance, None));
1975                    }
1976                    if sub != Never {
1977                        let hash = get_hash(instance);
1978                        instance.destructive_coerce();
1979                        if instance.is_quantified_subr() {
1980                            let instance = self.instantiate(instance.clone(), obj)?;
1981                            self.substitute_call(
1982                                obj,
1983                                attr_name,
1984                                &instance,
1985                                pos_args,
1986                                kw_args,
1987                                (var_args, kw_var_args),
1988                                namespace,
1989                            )?;
1990                            return Ok(SubstituteResult::Coerced(instance));
1991                        } else if get_hash(instance) != hash {
1992                            return self.substitute_call(
1993                                obj,
1994                                attr_name,
1995                                instance,
1996                                pos_args,
1997                                kw_args,
1998                                (var_args, kw_var_args),
1999                                namespace,
2000                            );
2001                        }
2002                    }
2003                }
2004                if let Some(attr_name) = attr_name {
2005                    feature_error!(
2006                        TyCheckErrors,
2007                        TyCheckError,
2008                        self,
2009                        attr_name.loc(),
2010                        "substitute_call for methods/type-var"
2011                    )
2012                } else {
2013                    let is_procedural = obj
2014                        .show_acc()
2015                        .map(|acc| acc.ends_with('!'))
2016                        .unwrap_or(false);
2017                    let kind = if is_procedural {
2018                        SubrKind::Proc
2019                    } else {
2020                        SubrKind::Func
2021                    };
2022                    let ret_t = free_var(self.level, Constraint::new_type_of(Type));
2023                    let non_default_params = pos_args.iter().map(|a| anon(a.expr.t())).collect();
2024                    let subr_t = subr_t(kind, non_default_params, None, vec![], None, ret_t);
2025                    self.occur(&subr_t, instance, obj)?;
2026                    instance.destructive_link(&subr_t);
2027                    Ok(SubstituteResult::Ok)
2028                }
2029            }
2030            Type::Refinement(refine) => self.substitute_call(
2031                obj,
2032                attr_name,
2033                &refine.t,
2034                pos_args,
2035                kw_args,
2036                (var_args, kw_var_args),
2037                namespace,
2038            ),
2039            // instance must be instantiated
2040            Type::Quantified(_) => unreachable_error!(TyCheckErrors, TyCheckError, self),
2041            Type::Subr(subr) => {
2042                let res = self.substitute_subr_call(
2043                    obj,
2044                    attr_name,
2045                    subr,
2046                    pos_args,
2047                    kw_args,
2048                    (var_args, kw_var_args),
2049                );
2050                // TODO: change polymorphic type syntax
2051                if res.is_err() && subr.return_t.is_class_type() {
2052                    self.substitute_dunder_call(
2053                        obj,
2054                        attr_name,
2055                        instance,
2056                        pos_args,
2057                        kw_args,
2058                        (var_args, kw_var_args),
2059                        namespace,
2060                    )
2061                    .or(res)
2062                } else {
2063                    res
2064                }
2065            }
2066            Type::And(_, _) => {
2067                let resolved = self.resolve_overload(
2068                    obj,
2069                    instance.clone(),
2070                    pos_args,
2071                    kw_args,
2072                    (var_args, kw_var_args),
2073                    &obj,
2074                )?;
2075                let instance = self.instantiate(resolved, obj)?;
2076                self.substitute_call(
2077                    obj,
2078                    attr_name,
2079                    &instance,
2080                    pos_args,
2081                    kw_args,
2082                    (var_args, kw_var_args),
2083                    namespace,
2084                )
2085                .map(|res| {
2086                    if let SubstituteResult::Ok = res {
2087                        SubstituteResult::Coerced(instance)
2088                    } else {
2089                        res
2090                    }
2091                })
2092            }
2093            Type::Failure | Type::Never => Ok(SubstituteResult::Ok),
2094            _ => self.substitute_dunder_call(
2095                obj,
2096                attr_name,
2097                instance,
2098                pos_args,
2099                kw_args,
2100                (var_args, kw_var_args),
2101                namespace,
2102            ),
2103        }
2104    }
2105
2106    fn substitute_subr_call(
2107        &self,
2108        obj: &hir::Expr,
2109        attr_name: &Option<Identifier>,
2110        subr: &SubrType,
2111        pos_args: &[hir::PosArg],
2112        kw_args: &[hir::KwArg],
2113        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
2114    ) -> TyCheckResult<SubstituteResult> {
2115        let mut errs = TyCheckErrors::empty();
2116        // method: obj: 1, subr: (self: Int, other: Int) -> Int
2117        // non-method: obj: Int, subr: (self: Int, other: Int) -> Int
2118        // FIXME: staticmethod
2119        let is_method_call = subr.self_t().is_some() && !obj.ref_t().is_singleton_refinement_type();
2120        let callee = if let Some(ident) = attr_name {
2121            if is_method_call {
2122                obj.clone()
2123            } else {
2124                let attr = hir::Attribute::new(obj.clone(), hir::Identifier::bare(ident.clone()));
2125                hir::Expr::Accessor(hir::Accessor::Attr(attr))
2126            }
2127        } else {
2128            obj.clone()
2129        };
2130        let params_len = if is_method_call {
2131            subr.non_default_params.len().saturating_sub(1) + subr.default_params.len()
2132        } else {
2133            subr.non_default_params.len() + subr.default_params.len()
2134        };
2135        let there_var = var_args.is_some() || kw_var_args.is_some();
2136        if (params_len < pos_args.len()
2137            || params_len < pos_args.len() + kw_args.len()
2138            // if there are extra *args or **kwargs
2139            || (params_len == pos_args.len() + kw_args.len() && there_var))
2140            && subr.is_no_var()
2141        {
2142            return Err(self.gen_too_many_args_error(
2143                &callee,
2144                subr,
2145                is_method_call,
2146                pos_args,
2147                kw_args,
2148            ));
2149        }
2150        let mut passed_params = set! {};
2151        let non_default_params = if is_method_call {
2152            let mut non_default_params = subr.non_default_params.iter();
2153            let self_pt = non_default_params.next().unwrap();
2154            if let Err(mut es) = self.self_unify(
2155                obj.ref_t(),
2156                self_pt.typ(),
2157                &Type::Subr(subr.clone()),
2158                obj,
2159                self_pt.name(),
2160            ) {
2161                errs.append(&mut es);
2162            }
2163            passed_params.insert("self".into());
2164            non_default_params
2165        } else {
2166            subr.non_default_params.iter()
2167        };
2168        let non_default_params_len = non_default_params.len();
2169        if pos_args.len() >= non_default_params_len {
2170            let (non_default_args, var_args) = pos_args.split_at(non_default_params_len);
2171            let mut args = non_default_args
2172                .iter()
2173                .zip(non_default_params)
2174                .enumerate()
2175                .collect::<Vec<_>>();
2176            // TODO: remove `obj.local_name() != Some("__contains__")`
2177            if obj.local_name() != Some("__contains__") && !subr.essential_qnames().is_empty() {
2178                args.sort_by(|(_, (l, _)), (_, (r, _))| {
2179                    l.expr.complexity().cmp(&r.expr.complexity())
2180                });
2181            }
2182            for (i, (nd_arg, nd_param)) in args {
2183                if let Err(mut es) = self.substitute_pos_arg(
2184                    &callee,
2185                    attr_name,
2186                    &nd_arg.expr,
2187                    i + 1,
2188                    nd_param,
2189                    &mut passed_params,
2190                ) {
2191                    errs.append(&mut es);
2192                }
2193            }
2194            let mut nth = 1 + non_default_params_len;
2195            if let Some(var_param) = subr.var_params.as_ref() {
2196                for var_arg in var_args.iter() {
2197                    if let Err(mut es) =
2198                        self.substitute_var_arg(&callee, attr_name, &var_arg.expr, nth, var_param)
2199                    {
2200                        errs.append(&mut es);
2201                    }
2202                    nth += 1;
2203                }
2204            } else {
2205                for (arg, pt) in var_args.iter().zip(subr.default_params.iter()) {
2206                    if let Err(mut es) = self.substitute_pos_arg(
2207                        &callee,
2208                        attr_name,
2209                        &arg.expr,
2210                        nth,
2211                        pt,
2212                        &mut passed_params,
2213                    ) {
2214                        errs.append(&mut es);
2215                    }
2216                    nth += 1;
2217                }
2218            }
2219            for kw_arg in kw_args.iter() {
2220                if let Err(mut es) = self.substitute_kw_arg(
2221                    &callee,
2222                    attr_name,
2223                    kw_arg,
2224                    nth,
2225                    subr,
2226                    &mut passed_params,
2227                ) {
2228                    errs.append(&mut es);
2229                }
2230                nth += 1;
2231            }
2232            for not_passed in subr
2233                .default_params
2234                .iter()
2235                .filter(|pt| pt.name().is_some_and(|name| !passed_params.contains(name)))
2236            {
2237                if let ParamTy::KwWithDefault { ty, default, .. } = &not_passed {
2238                    if let Err(mut es) = self.sub_unify(default, ty, obj, not_passed.name()) {
2239                        errs.append(&mut es);
2240                    }
2241                }
2242            }
2243        } else {
2244            let mut nth = 1;
2245            // pos_args.len() < non_default_params_len
2246            // don't use `zip`
2247            let mut params = non_default_params.chain(subr.default_params.iter());
2248            for pos_arg in pos_args.iter() {
2249                if let Err(mut es) = self.substitute_pos_arg(
2250                    &callee,
2251                    attr_name,
2252                    &pos_arg.expr,
2253                    nth,
2254                    params.next().unwrap(),
2255                    &mut passed_params,
2256                ) {
2257                    errs.append(&mut es);
2258                }
2259                nth += 1;
2260            }
2261            for kw_arg in kw_args.iter() {
2262                if let Err(mut es) = self.substitute_kw_arg(
2263                    &callee,
2264                    attr_name,
2265                    kw_arg,
2266                    nth,
2267                    subr,
2268                    &mut passed_params,
2269                ) {
2270                    errs.append(&mut es);
2271                }
2272                nth += 1;
2273            }
2274            let missing_params = subr
2275                .non_default_params
2276                .iter()
2277                .enumerate()
2278                .filter(|(_, pt)| pt.name().is_none_or(|name| !passed_params.contains(name)))
2279                .map(|(i, pt)| {
2280                    let n = if is_method_call { i } else { i + 1 };
2281                    let nth = format!("({} param)", ordinal_num(n));
2282                    pt.name()
2283                        .map_or(nth.clone(), |name| format!("{name} {nth}"))
2284                        .into()
2285                })
2286                .collect::<Vec<_>>();
2287            if let Some(var_args) = var_args {
2288                if !self.subtype_of(
2289                    var_args.expr.ref_t(),
2290                    &poly("Iterable", vec![TyParam::t(Obj)]),
2291                ) {
2292                    let err = TyCheckError::type_mismatch_error(
2293                        self.cfg.input.clone(),
2294                        line!() as usize,
2295                        var_args.loc(),
2296                        self.caused_by(),
2297                        "_",
2298                        None,
2299                        &poly("Iterable", vec![TyParam::t(Obj)]),
2300                        var_args.expr.ref_t(),
2301                        None,
2302                        None,
2303                    );
2304                    errs.push(err);
2305                }
2306            }
2307            if let Some(kw_var_args) = kw_var_args {
2308                if !self.subtype_of(
2309                    kw_var_args.expr.ref_t(),
2310                    &poly("Mapping", vec![TyParam::t(Obj), TyParam::t(Obj)]),
2311                ) {
2312                    let err = TyCheckError::type_mismatch_error(
2313                        self.cfg.input.clone(),
2314                        line!() as usize,
2315                        kw_var_args.loc(),
2316                        self.caused_by(),
2317                        "_",
2318                        None,
2319                        &poly("Mapping", vec![TyParam::t(Obj), TyParam::t(Obj)]),
2320                        kw_var_args.expr.ref_t(),
2321                        None,
2322                        None,
2323                    );
2324                    errs.push(err);
2325                }
2326            }
2327            if missing_params.is_empty() && (var_args.is_some() || kw_var_args.is_some()) {
2328                return Err(TyCheckErrors::from(TyCheckError::too_many_args_error(
2329                    self.cfg.input.clone(),
2330                    line!() as usize,
2331                    callee.loc(),
2332                    &callee.to_string(),
2333                    self.caused_by(),
2334                    params_len,
2335                    pos_args.len(),
2336                    kw_args.len(),
2337                )));
2338            }
2339            if !missing_params.is_empty() && var_args.is_none() && kw_var_args.is_none() {
2340                return Err(TyCheckErrors::from(TyCheckError::args_missing_error(
2341                    self.cfg.input.clone(),
2342                    line!() as usize,
2343                    callee.loc(),
2344                    &callee.to_string(),
2345                    self.caused_by(),
2346                    missing_params,
2347                )));
2348            }
2349        }
2350        if errs.is_empty() {
2351            /*if subr.has_qvar() {
2352                panic!("{subr} has qvar");
2353            }*/
2354            Ok(SubstituteResult::Ok)
2355        } else {
2356            Err(errs)
2357        }
2358    }
2359
2360    #[allow(clippy::too_many_arguments)]
2361    fn substitute_dunder_call(
2362        &self,
2363        obj: &hir::Expr,
2364        attr_name: &Option<Identifier>,
2365        instance: &Type,
2366        pos_args: &[hir::PosArg],
2367        kw_args: &[hir::KwArg],
2368        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
2369        namespace: &Context,
2370    ) -> TyCheckResult<SubstituteResult> {
2371        let ctxs = self
2372            .get_singular_ctxs_by_hir_expr(obj, self)
2373            .ok()
2374            .unwrap_or_default();
2375        let one = attr_name
2376            .as_ref()
2377            .map(|attr| {
2378                ctxs.iter()
2379                    .flat_map(|ctx| {
2380                        ctx.get_singular_ctxs_by_ident(attr, self)
2381                            .ok()
2382                            .unwrap_or_default()
2383                    })
2384                    .collect()
2385            })
2386            .unwrap_or(ctxs);
2387        let two = obj
2388            .qual_name()
2389            .map(|name| {
2390                self.get_same_name_context(&name)
2391                    .map_or(vec![], |ctx| vec![ctx])
2392            })
2393            .unwrap_or_default();
2394        let three = self
2395            .get_nominal_super_type_ctxs(instance)
2396            .unwrap_or_default()
2397            .into_iter()
2398            .map(|ctx| &ctx.ctx);
2399        let fallbacks = one.into_iter().chain(two).chain(three);
2400        for typ_ctx in fallbacks {
2401            // staticmethod __call__
2402            if instance.is_type() {
2403                if let Some(call_vi) =
2404                    typ_ctx.get_current_scope_var(&VarName::from_static("__call__"))
2405                {
2406                    if ERG_MODE && call_vi.vis.is_private() {
2407                        self.validate_visibility(
2408                            &Identifier::private_with_loc("__call__".into(), obj.loc()),
2409                            call_vi,
2410                            &self.cfg.input,
2411                            namespace,
2412                        )?;
2413                    }
2414                    let call_instance = self.instantiate_def_type(&call_vi.t)?;
2415                    if !call_instance.contains_intersec(instance) {
2416                        let instance = match self.substitute_call(
2417                            obj,
2418                            attr_name,
2419                            &call_instance,
2420                            pos_args,
2421                            kw_args,
2422                            (var_args, kw_var_args),
2423                            namespace,
2424                        )? {
2425                            SubstituteResult::__Call__(instance)
2426                            | SubstituteResult::Coerced(instance) => instance,
2427                            SubstituteResult::Ok => call_instance,
2428                        };
2429                        debug_assert!(!instance.is_intersection_type());
2430                        return Ok(SubstituteResult::__Call__(instance));
2431                    }
2432                }
2433            // instance method __call__
2434            } else if let Some(call_vi) = typ_ctx
2435                .get_method_context_of(&mono("GenericCallable"))
2436                .and_then(|method_ctx| {
2437                    method_ctx.get_current_scope_var(&VarName::from_static("__call__"))
2438                })
2439            {
2440                let call_instance = self.instantiate_def_type(&call_vi.t)?;
2441                if !call_instance.contains_intersec(instance) {
2442                    let instance = match self.substitute_call(
2443                        obj,
2444                        attr_name,
2445                        &call_instance,
2446                        pos_args,
2447                        kw_args,
2448                        (var_args, kw_var_args),
2449                        namespace,
2450                    )? {
2451                        SubstituteResult::__Call__(instance)
2452                        | SubstituteResult::Coerced(instance) => instance,
2453                        SubstituteResult::Ok => call_instance,
2454                    };
2455                    return Ok(SubstituteResult::__Call__(instance));
2456                }
2457            }
2458        }
2459        let hint = if self.subtype_of(instance, &ClassType) {
2460            let acc = attr_name.as_ref().map_or(obj.to_string_notype(), |attr| {
2461                obj.to_string_notype() + &attr.to_string()
2462            });
2463            Some(switch_lang! {
2464                "japanese" => format!("インスタンスを生成したい場合は、{acc}.newを使用してください"),
2465                "simplified_chinese" => format!("如果要生成实例,请使用 {acc}.new"),
2466                "traditional_chinese" => format!("如果要生成實例,請使用 {acc}.new"),
2467                "english" => format!("If you want to generate an instance, use {acc}.new"),
2468            })
2469        } else {
2470            None
2471        };
2472        Err(self.not_callable_error(obj, attr_name, instance, hint))
2473    }
2474
2475    fn gen_too_many_args_error(
2476        &self,
2477        callee: &hir::Expr,
2478        subr_ty: &SubrType,
2479        is_method: bool,
2480        pos_args: &[hir::PosArg],
2481        kw_args: &[hir::KwArg],
2482    ) -> TyCheckErrors {
2483        let mut unknown_args = vec![];
2484        let mut passed_args: Vec<&hir::KwArg> = vec![];
2485        let mut duplicated_args = vec![];
2486        for kw_arg in kw_args.iter() {
2487            if subr_ty
2488                .non_default_params
2489                .iter()
2490                .all(|pt| pt.name() != Some(kw_arg.keyword.inspect()))
2491                && subr_ty
2492                    .var_params
2493                    .as_ref()
2494                    .map(|pt| pt.name() != Some(kw_arg.keyword.inspect()))
2495                    .unwrap_or(true)
2496                && subr_ty
2497                    .default_params
2498                    .iter()
2499                    .all(|pt| pt.name() != Some(kw_arg.keyword.inspect()))
2500            {
2501                unknown_args.push(kw_arg);
2502            }
2503            if passed_args.iter().any(|a| a.keyword == kw_arg.keyword) {
2504                duplicated_args.push(kw_arg);
2505            } else {
2506                passed_args.push(kw_arg);
2507            }
2508        }
2509        if unknown_args.is_empty() && duplicated_args.is_empty() {
2510            let params_len = if is_method {
2511                subr_ty.non_default_params.len().saturating_sub(1) + subr_ty.default_params.len()
2512            } else {
2513                subr_ty.non_default_params.len() + subr_ty.default_params.len()
2514            };
2515            TyCheckErrors::from(TyCheckError::too_many_args_error(
2516                self.cfg.input.clone(),
2517                line!() as usize,
2518                callee.loc(),
2519                &callee.to_string(),
2520                self.caused_by(),
2521                params_len,
2522                pos_args.len(),
2523                kw_args.len(),
2524            ))
2525        } else {
2526            let unknown_arg_errors = unknown_args.into_iter().map(|arg| {
2527                let similar =
2528                    levenshtein::get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
2529                TyCheckError::unexpected_kw_arg_error(
2530                    self.cfg.input.clone(),
2531                    line!() as usize,
2532                    arg.loc(),
2533                    &callee.to_string(),
2534                    self.caused_by(),
2535                    arg.keyword.inspect(),
2536                    similar,
2537                )
2538            });
2539            let duplicated_arg_errors = duplicated_args.into_iter().map(|arg| {
2540                TyCheckError::multiple_args_error(
2541                    self.cfg.input.clone(),
2542                    line!() as usize,
2543                    arg.loc(),
2544                    &callee.to_string(),
2545                    self.caused_by(),
2546                    arg.keyword.inspect(),
2547                )
2548            });
2549            unknown_arg_errors.chain(duplicated_arg_errors).collect()
2550        }
2551    }
2552
2553    fn substitute_pos_arg(
2554        &self,
2555        callee: &hir::Expr,
2556        attr_name: &Option<Identifier>,
2557        arg: &hir::Expr,
2558        nth: usize,
2559        param: &ParamTy,
2560        passed_params: &mut Set<Str>,
2561    ) -> TyCheckResult<()> {
2562        let arg_t = arg.ref_t();
2563        let param_t = param.typ();
2564        if let Some(name) = param.name() {
2565            if passed_params.contains(name) {
2566                return Err(TyCheckErrors::from(TyCheckError::multiple_args_error(
2567                    self.cfg.input.clone(),
2568                    line!() as usize,
2569                    callee.loc(),
2570                    &callee.to_string(),
2571                    self.caused_by(),
2572                    name,
2573                )));
2574            } else {
2575                passed_params.insert(name.clone());
2576            }
2577        } else {
2578            passed_params.insert(Str::from(format!("({} param)", ordinal_num(nth))));
2579        }
2580        self.sub_unify_with_coercion(arg_t, param_t, arg, param.name())
2581            .map_err(|errs| {
2582                log!(err "semi-unification failed with {callee}\n{arg_t} !<: {param_t}");
2583                let name = if let Some(attr) = attr_name {
2584                    format!("{callee}{attr}")
2585                } else {
2586                    callee.show_acc().unwrap_or_default()
2587                };
2588                let name = name + "::" + param.name().map(|s| readable_name(&s[..])).unwrap_or("");
2589                let mut hint = self.get_call_type_mismatch_hint(
2590                    callee.ref_t(),
2591                    attr_name.as_ref().map(|i| &i.inspect()[..]),
2592                    nth,
2593                    param_t,
2594                    arg_t,
2595                );
2596                let param_t = self.readable_type(param_t.clone());
2597                let arg_t = self.readable_type(arg_t.clone());
2598                TyCheckErrors::new(
2599                    errs.into_iter()
2600                        .map(|e| {
2601                            log!("err: {e}");
2602                            TyCheckError::type_mismatch_error(
2603                                self.cfg.input.clone(),
2604                                line!() as usize,
2605                                e.core.loc,
2606                                e.caused_by,
2607                                &name[..],
2608                                Some(nth),
2609                                &param_t,
2610                                &arg_t,
2611                                self.get_candidates(&arg_t),
2612                                std::mem::take(&mut hint),
2613                            )
2614                        })
2615                        .collect(),
2616                )
2617            })?;
2618        Ok(())
2619    }
2620
2621    fn substitute_var_arg(
2622        &self,
2623        callee: &hir::Expr,
2624        attr_name: &Option<Identifier>,
2625        arg: &hir::Expr,
2626        nth: usize,
2627        param: &ParamTy,
2628    ) -> TyCheckResult<()> {
2629        let arg_t = arg.ref_t();
2630        let param_t = param.typ();
2631        self.sub_unify_with_coercion(arg_t, param_t, arg, param.name())
2632            .map_err(|errs| {
2633                log!(err "semi-unification failed with {callee}\n{arg_t} !<: {param_t}");
2634                let name = if let Some(attr) = attr_name {
2635                    format!("{callee}{attr}")
2636                } else {
2637                    callee.show_acc().unwrap_or_default()
2638                };
2639                let name = name + "::" + param.name().map(|s| readable_name(&s[..])).unwrap_or("");
2640                let hint = self.get_simple_type_mismatch_hint(param_t, arg_t);
2641                TyCheckErrors::new(
2642                    errs.into_iter()
2643                        .map(|e| {
2644                            TyCheckError::type_mismatch_error(
2645                                self.cfg.input.clone(),
2646                                line!() as usize,
2647                                e.core.loc,
2648                                e.caused_by,
2649                                &name[..],
2650                                Some(nth),
2651                                param_t,
2652                                arg_t,
2653                                self.get_candidates(arg_t),
2654                                hint.clone(),
2655                            )
2656                        })
2657                        .collect(),
2658                )
2659            })
2660    }
2661
2662    fn substitute_kw_arg(
2663        &self,
2664        callee: &hir::Expr,
2665        attr_name: &Option<Identifier>,
2666        arg: &hir::KwArg,
2667        nth: usize,
2668        subr_ty: &SubrType,
2669        passed_params: &mut Set<Str>,
2670    ) -> TyCheckResult<()> {
2671        let arg_t = arg.expr.ref_t();
2672        let kw_name = arg.keyword.inspect();
2673        if passed_params.contains(&kw_name[..]) {
2674            return Err(TyCheckErrors::from(TyCheckError::multiple_args_error(
2675                self.cfg.input.clone(),
2676                line!() as usize,
2677                callee.loc(),
2678                &callee.to_string(),
2679                self.caused_by(),
2680                arg.keyword.inspect(),
2681            )));
2682        }
2683        if let Some(pt) = subr_ty
2684            .non_default_params
2685            .iter()
2686            .chain(subr_ty.default_params.iter())
2687            .find(|pt| pt.name().as_ref() == Some(&kw_name))
2688        {
2689            let param_t = pt.typ();
2690            passed_params.insert(kw_name.clone());
2691            self.sub_unify_with_coercion(arg_t, param_t, arg, Some(kw_name))
2692                .map_err(|errs| {
2693                    log!(err "semi-unification failed with {callee}\n{arg_t} !<: {}", pt.typ());
2694                    let name = if let Some(attr) = attr_name {
2695                        format!("{callee}{attr}")
2696                    } else {
2697                        callee.show_acc().unwrap_or_default()
2698                    };
2699                    let name = name + "::" + readable_name(kw_name);
2700                    let hint = self.get_simple_type_mismatch_hint(param_t, arg_t);
2701                    let param_t = self.readable_type(param_t.clone());
2702                    let arg_t = self.readable_type(arg_t.clone());
2703                    TyCheckErrors::new(
2704                        errs.into_iter()
2705                            .map(|e| {
2706                                TyCheckError::type_mismatch_error(
2707                                    self.cfg.input.clone(),
2708                                    line!() as usize,
2709                                    e.core.loc,
2710                                    e.caused_by,
2711                                    &name[..],
2712                                    Some(nth),
2713                                    &param_t,
2714                                    &arg_t,
2715                                    self.get_candidates(&arg_t),
2716                                    hint.clone(),
2717                                )
2718                            })
2719                            .collect(),
2720                    )
2721                })?;
2722        } else if let Some(kw_var) = subr_ty.kw_var_params.as_deref() {
2723            self.sub_unify_with_coercion(arg_t, kw_var.typ(), arg, Some(kw_name))?;
2724        } else {
2725            let similar =
2726                levenshtein::get_similar_name(subr_ty.param_names(), arg.keyword.inspect());
2727            return Err(TyCheckErrors::from(TyCheckError::unexpected_kw_arg_error(
2728                self.cfg.input.clone(),
2729                line!() as usize,
2730                arg.keyword.loc(),
2731                &callee.to_string(),
2732                self.caused_by(),
2733                kw_name,
2734                similar,
2735            )));
2736        }
2737        Ok(())
2738    }
2739
2740    pub(crate) fn get_call_t_without_args(
2741        &self,
2742        obj: &hir::Expr,
2743        attr_name: &Option<Identifier>,
2744        input: &Input,
2745        expected_return: Option<&Type>,
2746        namespace: &Context,
2747    ) -> FailableOption<VarInfo> {
2748        let found = self
2749            .search_callee_info_without_args(obj, attr_name, input, namespace)
2750            .map_err(|err| (None, TyCheckErrors::from(err)))?;
2751        log!(
2752            "Found:\ncallee: {obj}{}\nfound: {found}",
2753            fmt_option!(pre ".", attr_name.as_ref().map(|ident| &ident.name))
2754        );
2755        let instance = self.instantiate(found.t.clone(), obj).map_err(|errs| {
2756            (
2757                (!found.t.is_quantified_subr()).then_some(found.clone()),
2758                errs,
2759            )
2760        })?;
2761        log!("Instantiated:\ninstance: {instance}");
2762        debug_assert!(
2763            !instance.is_quantified_subr(),
2764            "{instance} is quantified subr"
2765        );
2766        log!(info "Substituted:\ninstance: {instance}");
2767        debug_assert!(
2768            instance.has_no_qvar() || self.subtype_of(&instance, &Type::Type),
2769            "{instance} has qvar (obj: {obj}, attr: {}",
2770            fmt_option!(attr_name)
2771        );
2772        if let Some((expected, instance)) = expected_return.zip(instance.return_t()) {
2773            let _res = self.sub_unify(instance, expected, obj, None);
2774        }
2775        let res = VarInfo {
2776            t: instance,
2777            ..found
2778        };
2779        Ok(res)
2780    }
2781
2782    #[allow(clippy::too_many_arguments)]
2783    pub(crate) fn get_call_t(
2784        &self,
2785        obj: &hir::Expr,
2786        attr_name: &Option<Identifier>,
2787        pos_args: &mut [hir::PosArg],
2788        kw_args: &[hir::KwArg],
2789        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
2790        input: &Input,
2791        namespace: &Context,
2792    ) -> FailableOption<VarInfo> {
2793        if let Some(local) = obj.as_ident() {
2794            if local.vis().is_private() {
2795                match &local.inspect()[..] {
2796                    "match" => {
2797                        return self.get_match_call_t(SubrKind::Func, pos_args, kw_args);
2798                    }
2799                    "match!" => {
2800                        return self.get_match_call_t(SubrKind::Proc, pos_args, kw_args);
2801                    }
2802                    _ => {}
2803                }
2804            }
2805        }
2806        let found = self
2807            .search_callee_info(
2808                obj,
2809                attr_name,
2810                pos_args,
2811                kw_args,
2812                (var_args, kw_var_args),
2813                input,
2814                namespace,
2815            )
2816            .map_err(|err| (None, TyCheckErrors::from(err)))?;
2817        log!(
2818            "Found:\ncallee: {obj}{}\nfound: {found}",
2819            fmt_option!(pre ".", attr_name.as_ref().map(|ident| &ident.name))
2820        );
2821        let instance = self.instantiate(found.t.clone(), obj).map_err(|errs| {
2822            (
2823                (!found.t.is_quantified_subr()).then_some(found.clone()),
2824                errs,
2825            )
2826        })?;
2827        log!(
2828            "Instantiated:\ninstance: {instance}\npos_args: ({})\nkw_args: ({})",
2829            fmt_slice(pos_args),
2830            fmt_slice(kw_args)
2831        );
2832        debug_assert!(instance.has_no_qvar(), "{instance} has qvar");
2833        let instance = match self
2834            .substitute_call(
2835                obj,
2836                attr_name,
2837                &instance,
2838                pos_args,
2839                kw_args,
2840                (var_args, kw_var_args),
2841                namespace,
2842            )
2843            .or_else(|errs| {
2844                if let Some(res) = self.widen_call_type(
2845                    obj,
2846                    &found.t,
2847                    attr_name,
2848                    pos_args,
2849                    kw_args,
2850                    (var_args, kw_var_args),
2851                ) {
2852                    Ok(res)
2853                } else {
2854                    Err(errs)
2855                }
2856            })
2857            .map_err(|errs| {
2858                (
2859                    Some(VarInfo {
2860                        t: instance.clone(),
2861                        ..found.clone()
2862                    }),
2863                    errs,
2864                )
2865            })? {
2866            SubstituteResult::Ok => instance,
2867            SubstituteResult::__Call__(__call__) => __call__,
2868            SubstituteResult::Coerced(coerced) => coerced,
2869        };
2870        debug_assert!(
2871            !instance.is_quantified_subr(),
2872            "{instance} is quantified subr"
2873        );
2874        log!(info "Substituted:\ninstance: {instance}");
2875        debug_assert!(instance.has_no_qvar(), "{instance} has qvar");
2876        let res = self
2877            .eval_t_params(instance, self.level, obj)
2878            .map_err(|(t, errs)| {
2879                log!(err "failed to eval: {t}");
2880                (Some(VarInfo { t, ..found.clone() }), errs)
2881            })?;
2882        debug_assert!(res.has_no_qvar(), "{res} has qvar");
2883        log!(info "Params evaluated:\nres: {res}\n");
2884        let res = VarInfo { t: res, ..found };
2885        Ok(res)
2886    }
2887
2888    // e.g.
2889    // ```
2890    // found_t: (Structural({ .__sub__ = (self: L, other: R) -> O }), R) -> O
2891    // pos_args [100, 1.0]
2892    // 100: Nat ==> Float
2893    // => Coerced((Float, Float) -> Float) # not (Nat, Nat) -> Nat
2894    // ```
2895    fn widen_call_type(
2896        &self,
2897        obj: &hir::Expr,
2898        found_t: &Type,
2899        attr_name: &Option<Identifier>,
2900        pos_args: &mut [hir::PosArg],
2901        kw_args: &[hir::KwArg],
2902        (var_args, kw_var_args): (Option<&hir::PosArg>, Option<&hir::PosArg>),
2903    ) -> Option<SubstituteResult> {
2904        let found = <&SubrType>::try_from(found_t).ok()?;
2905        if found.has_type_satisfies(|t| t.is_structural()) {
2906            let idx_structural = found
2907                .non_default_params
2908                .iter()
2909                .position(|pt| pt.typ().is_structural())?;
2910            pos_args.get(idx_structural)?;
2911            let old_type = pos_args[idx_structural].expr.t();
2912            for sub in self.get_super_classes_or_self(&old_type).skip(1) {
2913                let Ok(Type::Subr(subr)) = self.instantiate(found_t.clone(), obj) else {
2914                    return None;
2915                };
2916                let pos_arg = pos_args.get_mut(idx_structural)?;
2917                *pos_arg.expr.ref_mut_t()? = sub.clone();
2918                let res = self.substitute_subr_call(
2919                    obj,
2920                    attr_name,
2921                    &subr,
2922                    pos_args,
2923                    kw_args,
2924                    (var_args, kw_var_args),
2925                );
2926                if res.is_ok() {
2927                    return Some(SubstituteResult::Coerced(Type::Subr(subr)));
2928                }
2929            }
2930            *pos_args[idx_structural].expr.ref_mut_t()? = old_type;
2931        }
2932        None
2933    }
2934
2935    pub(crate) fn get_const_local(
2936        &self,
2937        name: &Token,
2938        namespace: &Str,
2939    ) -> SingleTyCheckResult<ValueObj> {
2940        if let Some(obj) = self.consts.get(name.inspect()) {
2941            Ok(obj.clone())
2942        } else {
2943            /*if let Some(parent) = self.get_outer().or_else(|| self.get_builtins()) {
2944                return parent.get_const_local(name, namespace);
2945            }*/
2946            Err(TyCheckError::no_var_error(
2947                self.cfg.input.clone(),
2948                line!() as usize,
2949                name.loc(),
2950                namespace.into(),
2951                name.inspect(),
2952                self.get_similar_name(name.inspect()),
2953            ))
2954        }
2955    }
2956
2957    pub(crate) fn _get_const_attr(
2958        &self,
2959        obj: &hir::Expr,
2960        name: &Token,
2961        namespace: &Str,
2962    ) -> SingleTyCheckResult<ValueObj> {
2963        let self_t = obj.ref_t();
2964        for ctx in self.get_nominal_super_type_ctxs(self_t).ok_or_else(|| {
2965            TyCheckError::type_not_found(
2966                self.cfg.input.clone(),
2967                line!() as usize,
2968                obj.loc(),
2969                self.caused_by(),
2970                self_t,
2971            )
2972        })? {
2973            if let Ok(t) = ctx.get_const_local(name, namespace) {
2974                return Ok(t);
2975            }
2976        }
2977        // TODO: dependent type widening
2978        if let Some(parent) = self.get_outer_scope_or_builtins() {
2979            parent._get_const_attr(obj, name, namespace)
2980        } else {
2981            Err(TyCheckError::no_attr_error(
2982                self.cfg.input.clone(),
2983                line!() as usize,
2984                name.loc(),
2985                namespace.into(),
2986                self_t,
2987                name.inspect(),
2988                self.get_no_attr_hint(self_t, name.inspect()),
2989            ))
2990        }
2991    }
2992
2993    pub(crate) fn get_similar_name(&self, name: &str) -> Option<&str> {
2994        if self.cfg.fast_error_report {
2995            return None;
2996        }
2997        levenshtein::get_similar_name(
2998            self.dir().into_iter().map(|(vn, _)| &vn.inspect()[..]),
2999            name,
3000        )
3001    }
3002
3003    pub(crate) fn exists_name(&self, name: &str) -> bool {
3004        self.dir().iter().any(|(vn, _)| vn.inspect() == name)
3005    }
3006
3007    pub(crate) fn get_similar_name_and_info(&self, name: &str) -> Option<(&VarInfo, &str)> {
3008        if self.cfg.fast_error_report {
3009            return None;
3010        }
3011        levenshtein::get_similar_name_and_some(
3012            self.dir()
3013                .into_iter()
3014                .map(|(vn, vi)| (vi, &vn.inspect()[..])),
3015            name,
3016        )
3017    }
3018
3019    pub(crate) fn _get_similar_attr_from_singular<'a>(
3020        &'a self,
3021        obj: &hir::Expr,
3022        name: &str,
3023    ) -> Option<&'a str> {
3024        if let Ok(ctxs) = self.get_singular_ctxs_by_hir_expr(obj, self) {
3025            for ctx in ctxs {
3026                if let Some(name) = ctx.get_similar_name(name) {
3027                    return Some(name);
3028                }
3029            }
3030        }
3031        None
3032    }
3033
3034    pub(crate) fn get_similar_attr<'a>(&'a self, self_t: &'a Type, name: &str) -> Option<&'a str> {
3035        if self.cfg.fast_error_report {
3036            return None;
3037        }
3038        for ctx in self.get_nominal_super_type_ctxs(self_t)? {
3039            if let Some(name) = ctx.get_similar_name(name) {
3040                return Some(name);
3041            }
3042        }
3043        None
3044    }
3045
3046    pub(crate) fn exists_attr<'a>(&'a self, self_t: &'a Type, name: &str) -> bool {
3047        let Some(ctxs) = self.get_nominal_super_type_ctxs(self_t) else {
3048            return false;
3049        };
3050        for ctx in ctxs {
3051            if ctx.exists_name(name) {
3052                return true;
3053            }
3054        }
3055        false
3056    }
3057
3058    pub(crate) fn get_similar_attr_and_info<'a>(
3059        &'a self,
3060        self_t: &'a Type,
3061        name: &str,
3062    ) -> Option<(&'a VarInfo, &'a str)> {
3063        if self.cfg.fast_error_report {
3064            return None;
3065        }
3066        for ctx in self.get_nominal_super_type_ctxs(self_t)? {
3067            if let Some((vi, name)) = ctx.get_similar_name_and_info(name) {
3068                return Some((vi, name));
3069            }
3070        }
3071        None
3072    }
3073
3074    // Returns what kind of variance the type has for each parameter Type.
3075    // Invariant for types not specified
3076    // selfが示す型が、各パラメータTypeに対してどのような変性Varianceを持つかを返す
3077    // 特に指定されない型に対してはInvariant
3078    // e.g. K(T, U) = Class(..., Impl: F(T) and Output(U) and Input(T))
3079    // -> K.variance() == vec![Contravariant, Covariant]
3080    // TODO: support keyword arguments
3081    pub(crate) fn type_params_variance(&self) -> Vec<Variance> {
3082        let match_tp_name = |tp: &TyParam, name: &VarName| -> bool {
3083            if let Ok(free) = <&FreeTyParam>::try_from(tp) {
3084                if let Some(prev) = free.get_undoable_root() {
3085                    return prev.unbound_name().as_ref() == Some(name.inspect());
3086                }
3087            } else if let Ok(free) = <&FreeTyVar>::try_from(tp) {
3088                if let Some(prev) = free.get_undoable_root() {
3089                    return prev.unbound_name().as_ref() == Some(name.inspect());
3090                }
3091            }
3092            tp.qual_name().as_ref() == Some(name.inspect())
3093        };
3094        let in_inout = |t: &Type, name: &VarName| {
3095            (&t.qual_name()[..] == "Input" || &t.qual_name()[..] == "Output")
3096                && t.typarams()
3097                    .first()
3098                    .map(|inner| match_tp_name(inner, name))
3099                    .unwrap_or(false)
3100        };
3101        self.params
3102            .iter()
3103            .map(|(opt_name, _)| {
3104                if let Some(name) = opt_name {
3105                    // トレイトの変性を調べるときはsuper_classesも見る必要がある
3106                    if let Some(variance_trait) = self
3107                        .super_traits
3108                        .iter()
3109                        .chain(self.super_classes.iter())
3110                        .find(|t| in_inout(t, name))
3111                    {
3112                        match &variance_trait.qual_name()[..] {
3113                            "Output" => Variance::Covariant,
3114                            "Input" => Variance::Contravariant,
3115                            _ => unreachable!(),
3116                        }
3117                    } else {
3118                        Variance::Invariant
3119                    }
3120                } else {
3121                    Variance::Invariant
3122                }
3123            })
3124            .collect()
3125    }
3126
3127    /// Perform types linearization.
3128    /// TODO: Current implementation may be very inefficient.
3129    ///
3130    /// C3 linearization requires prior knowledge of inter-type dependencies, and cannot be used for Erg structural subtype linearization
3131    ///
3132    /// Algorithm:
3133    /// ```python
3134    /// [Int, Str, Nat, Never, Obj, Str!, Module]
3135    /// => [], [Int, Str, Nat, Never, Obj, Str!, Module]
3136    /// => [[Int]], [Str, Nat, Never, Obj, Str!, Module]
3137    /// # 1. If related, put them in the same array; if not, put them in different arrays.
3138    /// => [[Int], [Str]], [Nat, Never, Obj, Str!, Module]
3139    /// => ...
3140    /// => [[Int, Nat, Never, Obj]], [Str, Str!], [Module]]
3141    /// # 2. Then, perform sorting on the arrays
3142    /// => [[Never, Nat, Int, Obj], [Str!, Str], [Module]]
3143    /// # 3. Concatenate the arrays
3144    /// => [Never, Nat, Int, Obj, Str!, Str, Module]
3145    /// # 4. From the left, "slide" types as far as it can.
3146    /// => [Never, Nat, Int, Str!, Str, Module, Obj]
3147    /// ```
3148    pub fn sort_types<'a>(&self, types: impl Iterator<Item = &'a Type>) -> Vec<&'a Type> {
3149        let mut buffers: Vec<Vec<&Type>> = vec![];
3150        for t in types {
3151            let mut found = false;
3152            for buf in buffers.iter_mut() {
3153                if buf.iter().all(|buf_inner| self.related(buf_inner, t)) {
3154                    found = true;
3155                    buf.push(t);
3156                    break;
3157                }
3158            }
3159            if !found {
3160                buffers.push(vec![t]);
3161            }
3162        }
3163        for buf in buffers.iter_mut() {
3164            // this unwrap should be safe
3165            buf.sort_by(|lhs, rhs| self.cmp_t(lhs, rhs).try_into().unwrap());
3166        }
3167        let mut concatenated = buffers.into_iter().flatten().collect::<Vec<_>>();
3168        let mut idx = 0;
3169        let len = concatenated.len();
3170        while let Some(maybe_sup) = concatenated.get(idx) {
3171            if let Some(pos) = concatenated
3172                .iter()
3173                .take(len - idx - 1)
3174                .rposition(|t| self.supertype_of(maybe_sup, t))
3175            {
3176                let sup = concatenated.remove(idx);
3177                concatenated.insert(pos, sup); // not `pos + 1` because the element was removed at idx
3178            }
3179            idx += 1;
3180        }
3181        concatenated
3182    }
3183
3184    /// Returns the smallest type among the iterators of a given type.
3185    /// If there is no subtype relationship, returns `None`.
3186    /// ```erg
3187    /// min_type([Int, Int]) == Int
3188    /// min_type([Int, Nat]) == Nat
3189    /// min_type([Int, Str]) == None
3190    /// min_type([Int, Str, Nat]) == None
3191    /// ```
3192    pub fn min_type<'a>(&self, types: impl Iterator<Item = &'a Type>) -> Option<&'a Type> {
3193        let mut opt_min = None;
3194        for t in types {
3195            if let Some(min) = opt_min {
3196                if self.subtype_of(min, t) {
3197                    continue;
3198                } else if self.subtype_of(t, min) {
3199                    opt_min = Some(t);
3200                } else {
3201                    return None;
3202                }
3203            } else {
3204                opt_min = Some(t);
3205            }
3206        }
3207        opt_min
3208    }
3209
3210    /// Returns the largest type among the iterators of a given type.
3211    /// If there is no subtype relationship, returns `None`.
3212    /// ```erg
3213    /// max_type([Int, Int]) == Int
3214    /// max_type([Int, Nat]) == Int
3215    /// max_type([Int, Str]) == None
3216    /// max_type([Int, Str, Nat]) == None
3217    /// ```
3218    pub fn max_type<'a>(&self, types: impl Iterator<Item = &'a Type>) -> Option<&'a Type> {
3219        let mut opt_max = None;
3220        for t in types {
3221            if let Some(max) = opt_max {
3222                if self.supertype_of(max, t) {
3223                    continue;
3224                } else if self.supertype_of(t, max) {
3225                    opt_max = Some(t);
3226                } else {
3227                    return None;
3228                }
3229            } else {
3230                opt_max = Some(t);
3231            }
3232        }
3233        opt_max
3234    }
3235
3236    pub fn min_by_type<T>(&self, types: Vec<(T, Type)>) -> Option<(T, Type)> {
3237        let mut opt_min = None;
3238        for (x, t) in types {
3239            if let Some((_, min)) = opt_min.as_ref() {
3240                if self.subtype_of(min, &t) {
3241                    continue;
3242                } else if self.subtype_of(&t, min) {
3243                    opt_min = Some((x, t));
3244                } else {
3245                    return None;
3246                }
3247            } else {
3248                opt_min = Some((x, t));
3249            }
3250        }
3251        opt_min
3252    }
3253
3254    pub fn max_by_type<T>(&self, types: Vec<(T, Type)>) -> Option<(T, Type)> {
3255        let mut opt_max = None;
3256        for (x, t) in types {
3257            if let Some((_, max)) = opt_max.as_ref() {
3258                if self.supertype_of(max, &t) {
3259                    continue;
3260                } else if self.supertype_of(&t, max) {
3261                    opt_max = Some((x, t));
3262                } else {
3263                    return None;
3264                }
3265            } else {
3266                opt_max = Some((x, t));
3267            }
3268        }
3269        opt_max
3270    }
3271
3272    /// ```erg
3273    /// get_nominal_super_type_ctxs(Nat) == [<Nat>, <Int>, <Float>, ..., <Obj>, <Eq>, ...]
3274    /// # FIXME: ↓ should be [<Type>, <Obj>, <Eq>, ...]
3275    /// get_nominal_super_type_ctxs({Nat}) == [<Nat>, <Int>, <Float>, ..., <Obj>, <Eq>, ...]
3276    /// get_nominal_super_type_ctxs(?T(:> Nat, <: Eq)) == == [<Eq>, ...]
3277    /// ```
3278    pub fn get_nominal_super_type_ctxs<'a>(&'a self, t: &Type) -> Option<Vec<&'a TypeContext>> {
3279        match t {
3280            Type::FreeVar(fv) if fv.is_linked() => {
3281                self.get_nominal_super_type_ctxs(&fv.unwrap_linked())
3282            }
3283            Type::FreeVar(fv) => {
3284                if let Some(sup) = fv.get_super() {
3285                    self.get_nominal_super_type_ctxs(&sup)
3286                } else {
3287                    self.get_nominal_super_type_ctxs(&Type)
3288                }
3289            }
3290            Type::And(tys, _) => {
3291                let mut acc = vec![];
3292                for ctxs in tys
3293                    .iter()
3294                    .filter_map(|t| self.get_nominal_super_type_ctxs(t))
3295                {
3296                    acc.extend(ctxs);
3297                }
3298                if acc.is_empty() {
3299                    None
3300                } else {
3301                    Some(acc)
3302                }
3303            }
3304            Type::Or(tys) => {
3305                let union = tys
3306                    .iter()
3307                    .fold(Never, |l, r| self.union(&l, &r.upper_bounded()));
3308                if union.is_union_type() {
3309                    self.get_nominal_super_type_ctxs(&Obj)
3310                } else {
3311                    self.get_nominal_super_type_ctxs(&union)
3312                }
3313            }
3314            _ => self
3315                .get_simple_nominal_super_type_ctxs(t)
3316                .map(|ctxs| ctxs.collect()),
3317        }
3318    }
3319
3320    /// include `t` itself
3321    fn get_simple_nominal_super_type_ctxs<'a>(
3322        &'a self,
3323        t: &Type,
3324    ) -> Option<impl Iterator<Item = &'a TypeContext>> {
3325        let ctx = self.get_nominal_type_ctx(t)?;
3326        let sups = ctx.super_classes.iter().chain(ctx.super_traits.iter());
3327        let mut sup_ctxs = vec![];
3328        for sup in sups {
3329            if let Some(ctx) = self.get_nominal_type_ctx(sup) {
3330                sup_ctxs.push(ctx);
3331            } else if DEBUG_MODE {
3332                todo!("no ctx ({} / {}) for {sup}", self.name, self.kind);
3333            }
3334        }
3335        Some(vec![ctx].into_iter().chain(sup_ctxs))
3336    }
3337
3338    pub(crate) fn get_super_traits(&self, typ: &Type) -> Option<impl Iterator<Item = Type>> {
3339        self.get_nominal_type_ctx(typ)
3340            .map(|ctx| ctx.super_traits.clone().into_iter())
3341    }
3342
3343    /// include `typ` itself.
3344    /// if `typ` is a refinement type, include the base type (refine.t)
3345    pub(crate) fn get_super_classes(
3346        &self,
3347        typ: &Type,
3348    ) -> Option<impl Iterator<Item = Type> + Clone> {
3349        self.get_nominal_type_ctx(typ).map(|ctx| {
3350            let super_classes = ctx.super_classes.clone();
3351            let derefined = typ.derefine();
3352            if typ != &derefined {
3353                vec![ctx.typ.clone(), derefined]
3354                    .into_iter()
3355                    .chain(super_classes)
3356            } else {
3357                vec![ctx.typ.clone()].into_iter().chain(super_classes)
3358            }
3359        })
3360    }
3361
3362    pub(crate) fn get_super_classes_or_self(
3363        &self,
3364        typ: &Type,
3365    ) -> impl Iterator<Item = Type> + Clone {
3366        self.get_nominal_type_ctx(typ)
3367            .map(|ctx| {
3368                let super_classes = ctx.super_classes.clone();
3369                let derefined = typ.derefine();
3370                if typ != &derefined {
3371                    vec![ctx.typ.clone(), derefined]
3372                        .into_iter()
3373                        .chain(super_classes)
3374                } else {
3375                    vec![ctx.typ.clone()].into_iter().chain(super_classes)
3376                }
3377            })
3378            .unwrap_or(vec![typ.clone()].into_iter().chain(vec![]))
3379    }
3380
3381    /// include `typ` itself.
3382    pub(crate) fn get_super_types(&self, typ: &Type) -> Option<impl Iterator<Item = Type> + Clone> {
3383        self.get_nominal_type_ctx(typ).map(|ctx| {
3384            let super_classes = ctx.super_classes.clone();
3385            let super_traits = ctx.super_traits.clone();
3386            let derefined = typ.derefine();
3387            if typ != &derefined {
3388                vec![ctx.typ.clone(), derefined]
3389                    .into_iter()
3390                    .chain(super_classes)
3391                    .chain(super_traits)
3392            } else {
3393                vec![ctx.typ.clone()]
3394                    .into_iter()
3395                    .chain(super_classes)
3396                    .chain(super_traits)
3397            }
3398        })
3399    }
3400
3401    // TODO: Never
3402    /// ```erg
3403    /// get_nominal_type_ctx(Int) == Some(<Int>)
3404    /// get_nominal_type_ctx({Int}) == Some(<Int>) # FIXME: should be <Type>
3405    /// get_nominal_type_ctx(Int -> Int) == Some(<FuncMetaType>)
3406    /// get_nominal_type_ctx({ .x = Int }) == Some(<RecordMetaType>)
3407    /// get_nominal_type_ctx(?T(<: Int)) == Some(<Int>)
3408    /// get_nominal_type_ctx(?T(:> Int)) == None # you need to coerce it to Int
3409    /// get_nominal_type_ctx(T or U) == Some(<Or>)
3410    /// get_nominal_type_ctx(T and U) == None
3411    /// ```
3412    pub(crate) fn get_nominal_type_ctx<'a>(&'a self, typ: &Type) -> Option<&'a TypeContext> {
3413        match typ {
3414            Type::FreeVar(fv) if fv.is_linked() => {
3415                if let Some(res) = self.get_nominal_type_ctx(&fv.unwrap_linked()) {
3416                    return Some(res);
3417                }
3418            }
3419            Type::FreeVar(fv) => {
3420                let sup = fv.get_super()?;
3421                if let Some(res) = self.get_nominal_type_ctx(&sup) {
3422                    return Some(res);
3423                }
3424            }
3425            Type::Refinement(refine) => {
3426                // FIXME: Not good
3427                if let Predicate::Equal {
3428                    rhs: TyParam::Value(ValueObj::Type(typ)),
3429                    ..
3430                } = refine.pred.as_ref()
3431                {
3432                    if let Some(res) = self.get_nominal_type_ctx(typ.typ()) {
3433                        return Some(res);
3434                    }
3435                }
3436                if let Some(res) = self.get_nominal_type_ctx(&refine.t) {
3437                    return Some(res);
3438                }
3439            }
3440            Type::Quantified(quant) => {
3441                if self
3442                    .get_nominal_type_ctx(quant)
3443                    .is_some_and(|ctx| &ctx.typ.qual_name() == "ProcMetaType")
3444                {
3445                    if let Some(ctx) = self
3446                        .get_builtins_not_self()
3447                        .unwrap_or(self)
3448                        .rec_local_get_mono_type("QuantifiedProcMetaType")
3449                    {
3450                        return Some(ctx);
3451                    }
3452                } else if self
3453                    .get_nominal_type_ctx(quant)
3454                    .is_some_and(|ctx| &ctx.typ.qual_name() == "FuncMetaType")
3455                {
3456                    if let Some(ctx) = self
3457                        .get_builtins_not_self()
3458                        .unwrap_or(self)
3459                        .rec_local_get_mono_type("QuantifiedFuncMetaType")
3460                    {
3461                        return Some(ctx);
3462                    }
3463                }
3464                if let Some(ctx) = self
3465                    .get_builtins_not_self()
3466                    .unwrap_or(self)
3467                    .rec_local_get_mono_type("QuantifiedFunc")
3468                {
3469                    return Some(ctx);
3470                }
3471            }
3472            Type::Subr(subr) => match subr.kind {
3473                SubrKind::Func => {
3474                    if self.subtype_of(&subr.return_t, &Type) {
3475                        if let Some(ctx) = self
3476                            .get_builtins_not_self()
3477                            .unwrap_or(self)
3478                            .rec_local_get_mono_type("FuncMetaType")
3479                        {
3480                            return Some(ctx);
3481                        }
3482                    }
3483                    if let Some(ctx) = self
3484                        .get_builtins_not_self()
3485                        .unwrap_or(self)
3486                        .rec_local_get_mono_type("Func")
3487                    {
3488                        return Some(ctx);
3489                    }
3490                }
3491                SubrKind::Proc => {
3492                    if self.subtype_of(&subr.return_t, &Type) {
3493                        if let Some(ctx) = self
3494                            .get_builtins_not_self()
3495                            .unwrap_or(self)
3496                            .rec_local_get_mono_type("ProcMetaType")
3497                        {
3498                            return Some(ctx);
3499                        }
3500                    }
3501                    if let Some(ctx) = self
3502                        .get_builtins_not_self()
3503                        .unwrap_or(self)
3504                        .rec_local_get_mono_type("Proc")
3505                    {
3506                        return Some(ctx);
3507                    }
3508                }
3509            },
3510            Type::Mono(name) => {
3511                return self.get_mono_type(name);
3512            }
3513            Type::Poly { name, .. } => {
3514                return self.get_poly_type(name);
3515            }
3516            Type::Record(rec) => {
3517                if rec.values().all(|t| self.subtype_of(t, &Type)) {
3518                    if let Some(ctx) = self
3519                        .get_builtins_not_self()
3520                        .unwrap_or(self)
3521                        .rec_local_get_mono_type("RecordMetaType")
3522                    {
3523                        return Some(ctx);
3524                    }
3525                }
3526                return self
3527                    .get_builtins_not_self()
3528                    .unwrap_or(self)
3529                    .rec_local_get_mono_type("Record");
3530            }
3531            Type::NamedTuple(_) => {
3532                return self
3533                    .get_builtins_not_self()
3534                    .unwrap_or(self)
3535                    .rec_local_get_mono_type("GenericNamedTuple");
3536            }
3537            Type::Or(_) => {
3538                if let Some(ctx) = self.get_nominal_type_ctx(&poly("Or", vec![])) {
3539                    return Some(ctx);
3540                }
3541            }
3542            Type::Guard(_) => {
3543                return self.get_nominal_type_ctx(&Bool);
3544            }
3545            // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
3546            other if other.is_monomorphic() => {
3547                if let Some(ctx) = self.rec_local_get_mono_type(&other.local_name()) {
3548                    return Some(ctx);
3549                }
3550            }
3551            Type::Ref(t) | Type::RefMut { before: t, .. } => {
3552                if let Some(res) = self.get_nominal_type_ctx(t) {
3553                    return Some(res);
3554                }
3555            }
3556            Type::Bounded { sup, .. } => {
3557                if let Some(res) = self.get_nominal_type_ctx(sup) {
3558                    return Some(res);
3559                }
3560            }
3561            Type::Proj { lhs, rhs } => {
3562                if let Ok(evaled) = self.eval_proj(*lhs.clone(), rhs.clone(), self.level, &()) {
3563                    if typ != &evaled {
3564                        return self.get_nominal_type_ctx(&evaled);
3565                    }
3566                }
3567            }
3568            Type::ProjCall {
3569                lhs,
3570                attr_name,
3571                args,
3572            } => {
3573                if let Ok(evaled) = self.eval_proj_call_t(
3574                    *lhs.clone(),
3575                    attr_name.clone(),
3576                    args.clone(),
3577                    self.level,
3578                    &(),
3579                ) {
3580                    if typ != &evaled {
3581                        return self.get_nominal_type_ctx(&evaled);
3582                    }
3583                }
3584            }
3585            other => {
3586                log!("{other} has no nominal definition");
3587            }
3588        }
3589        None
3590    }
3591
3592    /// It is currently not possible to get the type defined in another module
3593    // TODO: Never
3594    pub(crate) fn get_mut_nominal_type_ctx<'a>(
3595        &'a mut self,
3596        typ: &Type,
3597    ) -> Option<&'a mut TypeContext> {
3598        match typ {
3599            Type::FreeVar(fv) if fv.is_linked() => {
3600                if let Some(res) = self.get_mut_nominal_type_ctx(&fv.unwrap_linked()) {
3601                    return Some(res);
3602                }
3603            }
3604            Type::FreeVar(fv) => {
3605                if let Some(res) = fv
3606                    .get_super()
3607                    .and_then(|sup| self.get_mut_nominal_type_ctx(&sup))
3608                {
3609                    return Some(res);
3610                }
3611            }
3612            Type::Refinement(refine) => {
3613                if let Some(res) = self.get_mut_nominal_type_ctx(&refine.t) {
3614                    return Some(res);
3615                }
3616            }
3617            Type::Quantified(_) => {
3618                if let Some(res) = self.get_mut_nominal_type_ctx(&mono("QuantifiedFunc")) {
3619                    return Some(res);
3620                }
3621            }
3622            Type::Mono(_) => {
3623                if let Some(ctx) = self.rec_get_mut_mono_type(&typ.local_name()) {
3624                    return Some(ctx);
3625                }
3626            }
3627            Type::Poly { .. } => {
3628                if let Some(ctx) = self.rec_get_mut_poly_type(&typ.local_name()) {
3629                    return Some(ctx);
3630                }
3631            }
3632            // FIXME: `F()`などの場合、実際は引数が省略されていてもmonomorphicになる
3633            other if other.is_monomorphic() => {
3634                if let Some(ctx) = self.rec_get_mut_mono_type(&other.local_name()) {
3635                    return Some(ctx);
3636                }
3637            }
3638            Type::Ref(t) | Type::RefMut { before: t, .. } => {
3639                if let Some(res) = self.get_mut_nominal_type_ctx(t) {
3640                    return Some(res);
3641                }
3642            }
3643            Type::Bounded { sup, .. } => {
3644                if let Some(res) = self.get_mut_nominal_type_ctx(sup) {
3645                    return Some(res);
3646                }
3647            }
3648            Type::Proj { lhs, rhs } => {
3649                if let Ok(evaled) = self.eval_proj(*lhs.clone(), rhs.clone(), self.level, &()) {
3650                    if typ != &evaled {
3651                        return self.get_mut_nominal_type_ctx(&evaled);
3652                    }
3653                }
3654            }
3655            Type::ProjCall {
3656                lhs,
3657                attr_name,
3658                args,
3659            } => {
3660                if let Ok(evaled) = self.eval_proj_call_t(
3661                    *lhs.clone(),
3662                    attr_name.clone(),
3663                    args.clone(),
3664                    self.level,
3665                    &(),
3666                ) {
3667                    if typ != &evaled {
3668                        return self.get_mut_nominal_type_ctx(&evaled);
3669                    }
3670                }
3671            }
3672            other => {
3673                log!("{other} has no nominal definition");
3674            }
3675        }
3676        None
3677    }
3678
3679    pub(crate) fn get_trait_impls(&self, trait_: &Type) -> Set<TraitImpl> {
3680        match trait_ {
3681            // And(Add, Sub) == intersection({Int <: Add(Int), Bool <: Add(Bool) ...}, {Int <: Sub(Int), ...})
3682            // == {Int <: Add(Int) and Sub(Int), ...}
3683            Type::And(tys, _) => {
3684                let impls = tys
3685                    .iter()
3686                    .flat_map(|ty| self.get_trait_impls(ty))
3687                    .collect::<Set<_>>();
3688                let bases = impls.iter().map(|ti| &ti.sub_type);
3689                let mut isec = set! {};
3690                for base in bases {
3691                    let base_impls = impls.iter().filter(|ti| ti.sub_type == *base);
3692                    let sup_trait =
3693                        base_impls.fold(Obj, |l, r| self.intersection(&l, &r.sup_trait));
3694                    if sup_trait != Obj {
3695                        isec.insert(TraitImpl::new(base.clone(), sup_trait, None));
3696                    }
3697                }
3698                isec
3699            }
3700            Type::Or(tys) => {
3701                // FIXME:
3702                tys.iter()
3703                    .fold(set! {}, |acc, ty| acc.union(&self.get_trait_impls(ty)))
3704            }
3705            _ => self.get_simple_trait_impls(trait_),
3706        }
3707    }
3708
3709    pub(crate) fn get_simple_trait_impls(&self, trait_: &Type) -> Set<TraitImpl> {
3710        let current = if let Some(impls) = self.trait_impls().get(&trait_.qual_name()) {
3711            impls.clone()
3712        } else {
3713            set! {}
3714        };
3715        if let Some(outer) = self.get_outer_scope_or_builtins() {
3716            current.union(&outer.get_simple_trait_impls(trait_))
3717        } else {
3718            current
3719        }
3720    }
3721
3722    pub(crate) fn all_patches(&self) -> Vec<&Context> {
3723        if let Some(outer) = self.get_outer_scope_or_builtins() {
3724            [outer.all_patches(), self.patches.values().collect()].concat()
3725        } else {
3726            self.patches.values().collect()
3727        }
3728    }
3729
3730    /// get a module by its name in the current scope
3731    ///
3732    /// name: Identifier.inspect()
3733    // FIXME: imported modules can access from any scope with the current implementation
3734    // 現在の実装だとimportしたモジュールはどこからでも見れる
3735    pub(crate) fn get_mod(&self, name: &str) -> Option<&Context> {
3736        if name == "module" && ERG_MODE {
3737            self.get_module()
3738        } else if name == "global" {
3739            self.get_builtins()
3740        } else {
3741            let t = self.get_var_info(name).map(|(_, vi)| &vi.t)?;
3742            self.get_mod_with_t(t)
3743        }
3744    }
3745
3746    pub fn get_mod_with_t(&self, mod_t: &Type) -> Option<&Context> {
3747        self.get_mod_with_path(&mod_t.module_path()?)
3748    }
3749
3750    // rec_get_const_localとは違い、位置情報を持たないしエラーとならない
3751    pub(crate) fn rec_get_const_obj(&self, name: &str) -> Option<&ValueObj> {
3752        if name.split('.').count() > 1 {
3753            let typ = Type::Mono(Str::rc(name));
3754            let namespace = self.get_namespace(&typ.namespace())?;
3755            return namespace.rec_get_const_obj(&typ.local_name());
3756        }
3757        #[cfg(feature = "py_compat")]
3758        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3759        if name == "Self" {
3760            if let Some(ty) = self.rec_get_self_t() {
3761                return self.rec_get_const_obj(&ty.local_name());
3762            }
3763        }
3764        if let Some(val) = self.consts.get(name) {
3765            return Some(val);
3766        }
3767        for ctx in self.methods_list.iter() {
3768            if let Some(val) = ctx.consts.get(name) {
3769                return Some(val);
3770            }
3771        }
3772        if let Some(outer) = self.get_outer_scope_or_builtins() {
3773            outer.rec_get_const_obj(name)
3774        } else {
3775            None
3776        }
3777    }
3778
3779    pub(crate) fn _rec_get_const_param_defaults(&self, name: &str) -> Option<&Vec<ConstTemplate>> {
3780        if let Some(impls) = self.const_param_defaults.get(name) {
3781            Some(impls)
3782        } else if let Some(outer) = self.get_outer_scope_or_builtins() {
3783            outer._rec_get_const_param_defaults(name)
3784        } else {
3785            None
3786        }
3787    }
3788
3789    // TODO: poly type
3790    pub(crate) fn rec_get_self_t(&self) -> Option<Type> {
3791        if self.kind.is_method_def() || self.kind.is_type() {
3792            Some(mono(self.name.clone()))
3793        } else if let ContextKind::PatchMethodDefs(t) = &self.kind {
3794            Some(t.clone())
3795        } else if let Some(outer) = self.get_outer_scope() {
3796            outer.rec_get_self_t()
3797        } else {
3798            None
3799        }
3800    }
3801
3802    pub(crate) fn gen_type(&self, ident: &ast::Identifier) -> Type {
3803        let vis = ident.vis.display_as_accessor();
3804        mono(format!("{}{vis}{}", self.name, ident.inspect()))
3805    }
3806
3807    pub(crate) fn get_namespace_path(&self, namespace: &Str) -> Option<PathBuf> {
3808        // get the true name
3809        let namespace = if let Some((_, vi)) = self.get_var_info(namespace) {
3810            if let Some(path) = vi.t.module_path() {
3811                return Some(path);
3812            } else {
3813                namespace.clone()
3814            }
3815        } else {
3816            namespace.clone()
3817        };
3818        let mut namespaces = namespace.split_with(&[".", "::"]);
3819        let mut str_namespace = namespaces.first().map(|n| n.to_string())?;
3820        namespaces.remove(0);
3821        while str_namespace.is_empty() || str_namespace.ends_with('.') {
3822            if namespaces.is_empty() {
3823                break;
3824            }
3825            str_namespace.push('.');
3826            str_namespace.push_str(namespaces.remove(0));
3827        }
3828        let path = Path::new(&str_namespace);
3829        let mut path = self.cfg.input.resolve_path(path, &self.cfg)?;
3830        for p in namespaces.into_iter() {
3831            path = Input::try_push_path(path, Path::new(p)).ok()?;
3832        }
3833        Some(path) // NG: path.canonicalize().ok()
3834    }
3835
3836    pub(crate) fn get_namespace(&self, namespace: &Str) -> Option<&Context> {
3837        if &namespace[..] == "global" {
3838            return self.get_builtins();
3839        } else if &namespace[..] == "module" || namespace.is_empty() {
3840            return self.get_module();
3841        }
3842        self.get_mod_with_path(self.get_namespace_path(namespace)?.as_path())
3843    }
3844
3845    pub(crate) fn get_mono_type(&self, name: &Str) -> Option<&TypeContext> {
3846        if let Some(ctx) = self.rec_local_get_mono_type(name) {
3847            return Some(ctx);
3848        }
3849        let typ = Type::Mono(Str::rc(name));
3850        if self.name.starts_with(&typ.namespace()[..]) {
3851            if let Some(ctx) = self.rec_local_get_mono_type(&typ.local_name()) {
3852                return Some(ctx);
3853            }
3854        }
3855        if let Some(ctx) = self.get_namespace(&typ.namespace()) {
3856            if let Some(ctx) = ctx.rec_local_get_mono_type(&typ.local_name()) {
3857                return Some(ctx);
3858            }
3859        }
3860        None
3861    }
3862
3863    /// you should use `get_mono_type` instead of this
3864    pub(crate) fn rec_local_get_mono_type(&self, name: &str) -> Option<&TypeContext> {
3865        #[cfg(feature = "py_compat")]
3866        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3867        if let Some(ctx) = self.mono_types.get(name) {
3868            Some(ctx)
3869        } else if let Some(outer) = self.get_outer_scope_or_builtins() {
3870            outer.rec_local_get_mono_type(name)
3871        } else {
3872            None
3873        }
3874    }
3875
3876    pub(crate) fn rec_local_get_poly_type(&self, name: &str) -> Option<&TypeContext> {
3877        #[cfg(feature = "py_compat")]
3878        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3879        if let Some(ctx) = self.poly_types.get(name) {
3880            Some(ctx)
3881        } else if let Some(outer) = self.get_outer_scope_or_builtins() {
3882            outer.rec_local_get_poly_type(name)
3883        } else {
3884            None
3885        }
3886    }
3887
3888    pub(crate) fn get_poly_type(&self, name: &Str) -> Option<&TypeContext> {
3889        if let Some(ctx) = self.rec_local_get_poly_type(name) {
3890            return Some(ctx);
3891        }
3892        let typ = Type::Mono(Str::rc(name));
3893        if self.name.starts_with(&typ.namespace()[..]) {
3894            if let Some(ctx) = self.rec_local_get_poly_type(&typ.local_name()) {
3895                return Some(ctx);
3896            }
3897        }
3898        if let Some(ctx) = self.get_namespace(&typ.namespace()) {
3899            if let Some(ctx) = ctx.rec_local_get_poly_type(&typ.local_name()) {
3900                return Some(ctx);
3901            }
3902        }
3903        None
3904    }
3905
3906    fn rec_get_mut_mono_type(&mut self, name: &str) -> Option<&mut TypeContext> {
3907        #[cfg(feature = "py_compat")]
3908        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3909        if let Some(ctx) = self.mono_types.get_mut(name) {
3910            Some(ctx)
3911        } else if let Some(outer) = self.outer.as_mut() {
3912            // builtins cannot be got as mutable
3913            outer.rec_get_mut_mono_type(name)
3914        } else {
3915            None
3916        }
3917    }
3918
3919    fn rec_get_mut_poly_type(&mut self, name: &str) -> Option<&mut TypeContext> {
3920        #[cfg(feature = "py_compat")]
3921        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3922        if let Some(ctx) = self.poly_types.get_mut(name) {
3923            Some(ctx)
3924        } else if let Some(outer) = self.outer.as_mut() {
3925            outer.rec_get_mut_poly_type(name)
3926        } else {
3927            None
3928        }
3929    }
3930
3931    pub(crate) fn rec_get_mut_type(&mut self, name: &str) -> Option<&mut TypeContext> {
3932        #[cfg(feature = "py_compat")]
3933        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3934        if let Some(ctx) = self.mono_types.get_mut(name) {
3935            Some(ctx)
3936        } else if let Some(ctx) = self.poly_types.get_mut(name) {
3937            Some(ctx)
3938        } else if let Some(outer) = self.outer.as_mut() {
3939            outer.rec_get_mut_type(name)
3940        } else {
3941            None
3942        }
3943    }
3944
3945    pub(crate) fn get_type_ctx(&self, name: &str) -> Option<&TypeContext> {
3946        if let Some(ctx) = self.rec_local_get_type(name) {
3947            return Some(ctx);
3948        }
3949        let typ = Type::Mono(Str::rc(name));
3950        if self.name.starts_with(&typ.namespace()[..]) {
3951            if let Some(ctx) = self.rec_local_get_type(&typ.local_name()) {
3952                return Some(ctx);
3953            }
3954        }
3955        if let Some(ctx) = self.get_namespace(&typ.namespace()) {
3956            if let Some(ctx) = ctx.rec_local_get_type(&typ.local_name()) {
3957                return Some(ctx);
3958            }
3959        }
3960        None
3961    }
3962
3963    pub fn get_type_info_by_str(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
3964        self.get_type_ctx(name)
3965            .and_then(|ctx| self.get_type_info(&ctx.typ))
3966    }
3967
3968    /// you should use `get_type` instead of this
3969    pub(crate) fn rec_local_get_type(&self, name: &str) -> Option<&TypeContext> {
3970        #[cfg(feature = "py_compat")]
3971        let name = self.erg_to_py_names.get(name).map_or(name, |s| &s[..]);
3972        if let Some(ctx) = self.mono_types.get(name) {
3973            Some(ctx)
3974        } else if let Some(ctx) = self.poly_types.get(name) {
3975            Some(ctx)
3976        } else if let Some(value) = self.consts.get(name) {
3977            value
3978                .as_type(self)
3979                .and_then(|typ_obj| self.get_nominal_type_ctx(typ_obj.typ()))
3980        } else if let Some(outer) = self.get_outer_scope_or_builtins() {
3981            outer.rec_local_get_type(name)
3982        } else {
3983            None
3984        }
3985    }
3986
3987    pub(crate) fn rec_get_patch(&self, name: &str) -> Option<&Context> {
3988        if let Some(ctx) = self.patches.get(name) {
3989            Some(ctx)
3990        } else if let Some(outer) = self.get_outer_scope_or_builtins() {
3991            outer.rec_get_patch(name)
3992        } else {
3993            None
3994        }
3995    }
3996
3997    pub(crate) fn rec_get_guards(&self) -> Vec<&GuardType> {
3998        if let Some(outer) = self.get_outer_scope() {
3999            [self.guards.iter().collect(), outer.rec_get_guards()].concat()
4000        } else {
4001            self.guards.iter().collect()
4002        }
4003    }
4004
4005    // TODO: `Override` decorator should also be used
4006    /// e.g.
4007    /// ```erg
4008    /// [Int -> Bool, Float -> Bool] => true
4009    /// [Int -> Bool, (Float, Str) -> Bool] => false
4010    /// [Int -> Bool, Int -> Str] => false
4011    /// [] => true
4012    /// ```
4013    fn same_shape<'t>(&self, mut candidates: impl Iterator<Item = &'t Type>) -> bool {
4014        let Some(first) = candidates.next() else {
4015            return true;
4016        };
4017        for cand in candidates {
4018            if cand
4019                .return_t()
4020                .zip(first.return_t())
4021                .is_none_or(|(a, b)| a != b)
4022            {
4023                return false;
4024            }
4025            if cand
4026                .non_default_params()
4027                .zip(first.non_default_params())
4028                .is_none_or(|(a, b)| a.len() != b.len())
4029            {
4030                return false;
4031            }
4032            if cand.var_params().is_some() != first.var_params().is_some() {
4033                return false;
4034            }
4035            if cand
4036                .default_params()
4037                .zip(first.default_params())
4038                .is_none_or(|(a, b)| {
4039                    a.len() != b.len() || a.iter().zip(b.iter()).any(|(a, b)| a.name() != b.name())
4040                })
4041            {
4042                return false;
4043            }
4044        }
4045        true
4046    }
4047
4048    fn get_attr_type<'m>(
4049        &self,
4050        obj: &hir::Expr,
4051        attr: &Identifier,
4052        candidates: &'m [MethodPair],
4053        namespace: &Context,
4054    ) -> Triple<&'m MethodPair, TyCheckError> {
4055        if candidates.is_empty() {
4056            return Triple::None;
4057        }
4058        let matches = candidates
4059            .iter()
4060            .filter(|mp| self.supertype_of(&mp.definition_type, obj.ref_t()))
4061            .collect::<Vec<_>>();
4062        if matches.len() == 1 {
4063            let method_pair = matches[0];
4064            if method_pair
4065                .method_info
4066                .vis
4067                .compatible(&attr.acc_kind(), self)
4068            {
4069                return Triple::Ok(method_pair);
4070            }
4071        }
4072        if self.same_shape(candidates.iter().map(|mp| &mp.method_info.t)) {
4073            // if all methods have the same return type, the minimum type (has biggest param types) is selected
4074            // e.g. [Float -> Bool, Int -> Bool] => Float -> Bool
4075            // REVIEW: should [Int -> Bool, Str -> Bool] => (Str or Int) -> Bool?
4076            // -> get_union_method_type
4077            if let Some(min) = self.min_type(candidates.iter().map(|mp| &mp.method_info.t)) {
4078                let min_pair = candidates
4079                    .iter()
4080                    .find(|mp| &mp.method_info.t == min)
4081                    .unwrap();
4082                if min_pair.method_info.vis.compatible(&attr.acc_kind(), self) {
4083                    return Triple::Ok(min_pair);
4084                }
4085            }
4086        }
4087        Triple::Err(TyCheckError::ambiguous_method_error(
4088            namespace.cfg.input.clone(),
4089            line!() as usize,
4090            obj,
4091            attr,
4092            &candidates
4093                .iter()
4094                .map(|mp| self.readable_type(mp.definition_type.clone()))
4095                .collect::<Vec<_>>(),
4096            namespace.caused_by(),
4097        ))
4098    }
4099
4100    pub fn partial_get_methods_by_name(
4101        &self,
4102        partial_attr: &Identifier,
4103    ) -> Vec<(&Str, &Vec<MethodPair>)> {
4104        let mut res = vec![];
4105        for candidates in self
4106            .method_to_traits
4107            .iter()
4108            .filter(|(key, _)| key.starts_with(&partial_attr.inspect()[..]))
4109        {
4110            res.push(candidates);
4111        }
4112        for candidates in self
4113            .method_to_classes
4114            .iter()
4115            .filter(|(key, _)| key.starts_with(&partial_attr.inspect()[..]))
4116        {
4117            res.push(candidates);
4118        }
4119        if let Some(outer) = self.get_outer_scope_or_builtins() {
4120            res.extend(outer.partial_get_methods_by_name(partial_attr));
4121        }
4122        res
4123    }
4124
4125    // (Int -> Bool, Float -> Bool) => Int or Float -> Bool
4126    fn get_union_method_type(&self, candidates: &[MethodPair]) -> Option<Type> {
4127        let fst = candidates.first()?;
4128        let mut kind = fst.method_info.t.subr_kind()?;
4129        let mut union_nds = fst.method_info.t.non_default_params()?.clone();
4130        let mut union_var = fst.method_info.t.var_params().cloned();
4131        let mut union_ds = fst.method_info.t.default_params()?.clone();
4132        let mut union_kw_var = fst.method_info.t.kw_var_params().cloned();
4133        let mut union_return = fst.method_info.t.return_t()?.clone();
4134        for cand in candidates.iter().skip(1) {
4135            kind = kind | cand.method_info.t.subr_kind()?;
4136            for (union, r) in union_nds
4137                .iter_mut()
4138                .zip(cand.method_info.t.non_default_params()?)
4139            {
4140                *union.typ_mut() = self.union(union.typ(), r.typ());
4141            }
4142            if let Some((union, r)) = union_var.as_mut().zip(cand.method_info.t.var_params()) {
4143                *union.typ_mut() = self.union(union.typ(), r.typ());
4144            }
4145            for (union, r) in union_ds
4146                .iter_mut()
4147                .zip(cand.method_info.t.default_params()?)
4148            {
4149                *union.typ_mut() = self.union(union.typ(), r.typ());
4150            }
4151            if let Some((union, r)) = union_kw_var
4152                .as_mut()
4153                .zip(cand.method_info.t.kw_var_params())
4154            {
4155                *union.typ_mut() = self.union(union.typ(), r.typ());
4156            }
4157            union_return = self.union(&union_return, cand.method_info.t.return_t()?);
4158        }
4159        let subr = Type::Subr(SubrType::new(
4160            kind,
4161            union_nds,
4162            union_var,
4163            union_ds,
4164            union_kw_var,
4165            union_return,
4166        ));
4167        if subr.has_qvar() {
4168            Some(subr.quantify())
4169        } else {
4170            Some(subr)
4171        }
4172    }
4173
4174    /// Infer the receiver type from the attribute name.
4175    /// Returns an error if multiple candidates are found. If nothing is found, returns None.
4176    fn get_attr_type_by_name(
4177        &self,
4178        receiver: &hir::Expr,
4179        attr: &Identifier,
4180        namespace: &Context,
4181    ) -> Triple<&MethodPair, TyCheckError> {
4182        if let Some(candidates) = self.method_to_traits.get(attr.inspect()) {
4183            return self.get_attr_type(receiver, attr, candidates, namespace);
4184        }
4185        if let Some(candidates) = self.method_to_classes.get(attr.inspect()) {
4186            return self.get_attr_type(receiver, attr, candidates, namespace);
4187        }
4188        if let Some(outer) = self.get_outer_scope_or_builtins() {
4189            outer.get_attr_type_by_name(receiver, attr, namespace)
4190        } else {
4191            Triple::None
4192        }
4193    }
4194
4195    fn get_union_attr_type_by_name(&self, attr: &Identifier) -> Option<Type> {
4196        if let Some(candidates) = self.method_to_traits.get(attr.inspect()) {
4197            return self.get_union_method_type(candidates);
4198        }
4199        if let Some(candidates) = self.method_to_classes.get(attr.inspect()) {
4200            return self.get_union_method_type(candidates);
4201        }
4202        if let Some(outer) = self.get_outer_scope_or_builtins() {
4203            outer.get_union_attr_type_by_name(attr)
4204        } else {
4205            None
4206        }
4207    }
4208
4209    fn _get_gen_t_require_attr_t<'a>(
4210        &'a self,
4211        gen: &'a GenTypeObj,
4212        attr: &str,
4213    ) -> Option<&'a Type> {
4214        match gen.base_or_sup().map(|req_sup| req_sup.typ()) {
4215            Some(Type::Record(rec)) => {
4216                if let Some(t) = rec.get(attr) {
4217                    return Some(t);
4218                }
4219            }
4220            Some(other) => {
4221                let obj = self.rec_get_const_obj(&other.local_name());
4222                let obj = option_enum_unwrap!(obj, Some:(ValueObj::Type:(TypeObj::Generated:(_))))?;
4223                if let Some(t) = self._get_gen_t_require_attr_t(obj, attr) {
4224                    return Some(t);
4225                }
4226            }
4227            None => {}
4228        }
4229        if let Some(additional) = gen.additional() {
4230            if let Type::Record(gen) = additional.typ() {
4231                if let Some(t) = gen.get(attr) {
4232                    return Some(t);
4233                }
4234            }
4235        }
4236        None
4237    }
4238
4239    // TODO: params, polymorphic types
4240    pub(crate) fn get_candidates(&self, t: &Type) -> Option<Set<Type>> {
4241        match t {
4242            Type::Proj { lhs, rhs } => Some(self.get_proj_candidates(lhs, rhs)),
4243            Type::Subr(subr) => {
4244                let candidates = self.get_candidates(&subr.return_t)?;
4245                Some(
4246                    candidates
4247                        .into_iter()
4248                        .map(|ret_t| {
4249                            let subr = SubrType::new(
4250                                subr.kind,
4251                                subr.non_default_params.clone(),
4252                                subr.var_params.as_deref().cloned(),
4253                                subr.default_params.clone(),
4254                                subr.kw_var_params.as_deref().cloned(),
4255                                ret_t,
4256                            );
4257                            Type::Subr(subr)
4258                        })
4259                        .collect(),
4260                )
4261            }
4262            _ => None,
4263        }
4264    }
4265
4266    fn get_proj_candidates(&self, lhs: &Type, rhs: &Str) -> Set<Type> {
4267        match lhs {
4268            Type::FreeVar(fv) => {
4269                if let Some(sup) = fv.get_super() {
4270                    if self.is_trait(&sup) {
4271                        self.get_trait_proj_candidates(&sup, rhs)
4272                    } else {
4273                        self.eval_proj(sup, rhs.clone(), self.level, &())
4274                            .map_or(set! {}, |t| set! {t})
4275                    }
4276                } else {
4277                    set! {}
4278                }
4279            }
4280            Type::Failure | Type::Never => set! { lhs.clone() },
4281            _ => set! {},
4282        }
4283    }
4284
4285    fn get_trait_proj_candidates(&self, trait_: &Type, rhs: &Str) -> Set<Type> {
4286        let impls = self.get_trait_impls(trait_);
4287        let candidates = impls.into_iter().filter_map(move |imp| {
4288            if self.supertype_of(&imp.sup_trait, trait_) {
4289                self.eval_t_params(proj(imp.sub_type, rhs), self.level, &())
4290                    .ok()
4291            } else {
4292                None
4293            }
4294        });
4295        candidates.collect()
4296    }
4297
4298    pub(crate) fn get_proj_impl_candidates(&self, lhs: &Type, rhs: &Str) -> Set<(TraitImpl, Type)> {
4299        match lhs {
4300            Type::FreeVar(fv) => {
4301                if let Some(sup) = fv.get_super() {
4302                    if self.is_trait(&sup) {
4303                        self.get_trait_proj_impl_candidates(&sup, rhs)
4304                    } else {
4305                        set! {}
4306                    }
4307                } else {
4308                    set! {}
4309                }
4310            }
4311            _ => set! {},
4312        }
4313    }
4314
4315    fn get_trait_proj_impl_candidates(&self, trait_: &Type, rhs: &Str) -> Set<(TraitImpl, Type)> {
4316        let impls = self.get_trait_impls(trait_);
4317        let candidates = impls.into_iter().filter_map(move |imp| {
4318            if self.supertype_of(&imp.sup_trait, trait_) {
4319                let evaled = self
4320                    .eval_t_params(proj(imp.sub_type.clone(), rhs), self.level, &())
4321                    .ok()?;
4322                Some((imp, evaled))
4323            } else {
4324                None
4325            }
4326        });
4327        candidates.collect()
4328    }
4329
4330    pub fn is_class(&self, typ: &Type) -> bool {
4331        match typ {
4332            Type::Never => true,
4333            Type::FreeVar(fv) if fv.is_linked() => self.is_class(&fv.unwrap_linked()),
4334            Type::FreeVar(_) => false,
4335            Type::And(_, _) => false,
4336            Type::Or(tys) => tys.iter().all(|t| self.is_class(t)),
4337            Type::Not(ty) => self.is_class(ty),
4338            Type::Proj { lhs, rhs } => self
4339                .get_proj_candidates(lhs, rhs)
4340                .iter()
4341                .all(|t| self.is_class(t)),
4342            Type::Refinement(refine) => self.is_class(&refine.t),
4343            Type::Ref(t) | Type::RefMut { before: t, .. } => self.is_class(t),
4344            Type::Structural(_) => false,
4345            Type::Record(_) => true,
4346            Type::Subr(_) => true,
4347            _ => {
4348                if let Some(ctx) = self.get_nominal_type_ctx(typ) {
4349                    ctx.kind.is_class()
4350                } else {
4351                    // TODO: unknown types
4352                    false
4353                }
4354            }
4355        }
4356    }
4357
4358    pub fn is_trait(&self, typ: &Type) -> bool {
4359        match typ {
4360            Type::Never => false,
4361            Type::FreeVar(fv) if fv.is_linked() => self.is_trait(&fv.unwrap_linked()),
4362            Type::FreeVar(_) => false,
4363            Type::And(tys, _) => tys.iter().any(|t| self.is_trait(t)),
4364            Type::Or(tys) => tys.iter().all(|t| self.is_trait(t)),
4365            Type::Not(ty) => self.is_trait(ty),
4366            Type::Proj { lhs, rhs } => self
4367                .get_proj_candidates(lhs, rhs)
4368                .iter()
4369                .all(|t| self.is_trait(t)),
4370            Type::Refinement(refine) => self.is_trait(&refine.t),
4371            Type::Ref(t) | Type::RefMut { before: t, .. } => self.is_trait(t),
4372            Type::Structural(_) => false,
4373            Type::Record(_) => false,
4374            Type::Subr(_) => false,
4375            _ => {
4376                if let Some(ctx) = self.get_nominal_type_ctx(typ) {
4377                    ctx.kind.is_trait()
4378                } else {
4379                    false
4380                }
4381            }
4382        }
4383    }
4384
4385    // TODO:
4386    /// ```erg
4387    /// Int.meta_type() == ClassType (<: Type)
4388    /// Show.meta_type() == TraitType (<: Type)
4389    /// [Int; 3].meta_type() == [ClassType; 3] (<: Type)
4390    /// (Int, Str).meta_type() == (ClassType, ClassType) (<: Type)
4391    /// {Str: Int}.meta_type() == {ClassType: ClassType} (<: Type)
4392    /// Indexable(T).meta_type() == TraitType (<: Type)
4393    /// NamedTuple({ .x = Int; .y = Str }).meta_type() == NamedTuple({ .x = ClassType; .y = ClassType })
4394    /// ```
4395    pub fn meta_type(&self, typ: &Type) -> Type {
4396        match typ {
4397            Type::Poly { name, params } if typ.is_list() || typ.is_set() || typ.is_tuple() => poly(
4398                name.clone(),
4399                params
4400                    .iter()
4401                    .map(|tp| {
4402                        if let Ok(t) = self.convert_tp_into_type(tp.clone()) {
4403                            TyParam::t(self.meta_type(&t))
4404                        } else {
4405                            tp.clone()
4406                        }
4407                    })
4408                    .collect(),
4409            ),
4410            Type::Poly { params, .. } if typ.is_dict() => self
4411                .convert_tp_into_value(params[0].clone())
4412                .map(|value| {
4413                    if let ValueObj::Dict(dict) = value {
4414                        let mut ty = dict! {};
4415                        for (k, v) in dict {
4416                            let Ok(k) = self.convert_value_into_type(k) else {
4417                                return Type;
4418                            };
4419                            let Ok(v) = self.convert_value_into_type(v) else {
4420                                return Type;
4421                            };
4422                            ty.insert(self.meta_type(&k), self.meta_type(&v));
4423                        }
4424                        Type::from(ty)
4425                    } else {
4426                        Type
4427                    }
4428                })
4429                .unwrap_or(Type),
4430            NamedTuple(tuple) => NamedTuple(
4431                tuple
4432                    .iter()
4433                    .map(|(name, tp)| (name.clone(), self.meta_type(tp)))
4434                    .collect(),
4435            ),
4436            Record(rec) => Record(
4437                rec.iter()
4438                    .map(|(name, tp)| (name.clone(), self.meta_type(tp)))
4439                    .collect(),
4440            ),
4441            _ => Type,
4442        }
4443    }
4444
4445    pub(crate) fn get_tp_from_tv_cache<'v>(
4446        &'v self,
4447        name: &str,
4448        tmp_tv_cache: &'v TyVarCache,
4449    ) -> Option<TyParam> {
4450        if let Some(tp) = tmp_tv_cache.get_typaram(name) {
4451            Some(tp.clone())
4452        } else if let Some(t) = tmp_tv_cache.get_tyvar(name) {
4453            Some(TyParam::t(t.clone()))
4454        } else if let Some(tv_ctx) = &self.tv_cache {
4455            if let Some(t) = tv_ctx.get_tyvar(name) {
4456                Some(TyParam::t(t.clone()))
4457            } else {
4458                tv_ctx.get_typaram(name).cloned()
4459            }
4460        } else {
4461            None
4462        }
4463    }
4464
4465    pub(crate) fn get_tp_and_vi_from_tv_cache<'v>(
4466        &'v self,
4467        name: &str,
4468        tmp_tv_cache: &'v TyVarCache,
4469    ) -> Option<(TyParam, &'v VarInfo)> {
4470        if let Some(tp) = tmp_tv_cache.get_typaram(name) {
4471            Some((tp.clone(), tmp_tv_cache.var_infos.get(name)?))
4472        } else if let Some(t) = tmp_tv_cache.get_tyvar(name) {
4473            Some((TyParam::t(t.clone()), tmp_tv_cache.var_infos.get(name)?))
4474        } else if let Some(tv_ctx) = &self.tv_cache {
4475            if let Some(t) = tv_ctx.get_tyvar(name) {
4476                Some((TyParam::t(t.clone()), tv_ctx.var_infos.get(name)?))
4477            } else {
4478                tv_ctx
4479                    .get_typaram(name)
4480                    .cloned()
4481                    .and_then(|tp| Some((tp, tv_ctx.var_infos.get(name)?)))
4482            }
4483        } else {
4484            None
4485        }
4486    }
4487
4488    /// ```erg
4489    /// recover_typarams(Int, Nat) == Nat
4490    /// recover_typarams(List!(Int, _), List(Nat, 2)) == List!(Nat, 2)
4491    /// recover_typarams(Str or NoneType, {"a", "b"}) == {"a", "b"}
4492    /// ```
4493    /// ```erg
4494    /// # REVIEW: should be?
4495    /// recover_typarams(Nat or Str, Int) == Nat
4496    /// ```
4497    pub(crate) fn recover_typarams(&self, base: &Type, guard: &GuardType) -> TyCheckResult<Type> {
4498        let intersec = self.intersection(&guard.to, base);
4499        let is_never =
4500            guard.to.as_ref() != &Type::Never && self.subtype_of(&intersec, &Type::Never);
4501        if !is_never {
4502            return Ok(intersec);
4503        }
4504        if guard.to.is_monomorphic() {
4505            if self.related(base, &guard.to) {
4506                return Ok(*guard.to.clone());
4507            } else {
4508                return Err(TyCheckErrors::from(TyCheckError::invalid_type_cast_error(
4509                    self.cfg.input.clone(),
4510                    line!() as usize,
4511                    guard.target.loc(),
4512                    self.caused_by(),
4513                    &guard.target.to_string(),
4514                    base,
4515                    &guard.to,
4516                    None,
4517                )));
4518            }
4519        }
4520        // List(Nat, 2) !<: List!(Int, _)
4521        let base_def_t = self
4522            .get_nominal_type_ctx(base)
4523            .map(|ctx| &ctx.typ)
4524            .unwrap_or(&Type::Obj);
4525        let assert_def_t = self
4526            .get_nominal_type_ctx(&guard.to)
4527            .map(|ctx| &ctx.typ)
4528            .unwrap_or(&Type::Obj);
4529        if self.related(base_def_t, assert_def_t) {
4530            // FIXME: Vec(_), List(Int, 2) -> Vec(2)
4531            let casted = if base.is_polymorphic() {
4532                poly(base.qual_name(), guard.to.typarams())
4533            } else {
4534                *guard.to.clone()
4535            };
4536            Ok(casted)
4537        } else {
4538            Err(TyCheckErrors::from(TyCheckError::invalid_type_cast_error(
4539                self.cfg.input.clone(),
4540                line!() as usize,
4541                guard.target.loc(),
4542                self.caused_by(),
4543                &guard.target.to_string(),
4544                base,
4545                &guard.to,
4546                None,
4547            )))
4548        }
4549    }
4550
4551    pub(crate) fn get_instance_attr(&self, name: &str) -> Option<&VarInfo> {
4552        if let Some(vi) = self.locals.get(name) {
4553            if vi.kind.is_instance_attr() {
4554                return Some(vi);
4555            }
4556        }
4557        if let Some(vi) = self.decls.get(name) {
4558            if vi.kind.is_instance_attr() {
4559                return Some(vi);
4560            }
4561        }
4562        if self.kind.is_method_def() {
4563            self.get_nominal_type_ctx(&mono(&self.name))
4564                .and_then(|ctx| ctx.get_instance_attr(name))
4565        } else {
4566            self.methods_list.iter().find_map(|ctx| {
4567                if ctx.kind.is_trait_impl() {
4568                    None
4569                } else {
4570                    ctx.get_instance_attr(name)
4571                }
4572            })
4573        }
4574    }
4575
4576    /// does not remove instance attribute declarations
4577    pub(crate) fn remove_class_attr(&mut self, name: &str) -> Option<(VarName, VarInfo)> {
4578        if let Some((k, v)) = self.locals.remove_entry(name) {
4579            if v.kind.is_instance_attr() {
4580                self.locals.insert(k, v);
4581            } else {
4582                return Some((k, v));
4583            }
4584        } else if let Some((k, v)) = self.decls.remove_entry(name) {
4585            if v.kind.is_instance_attr() {
4586                self.decls.insert(k, v);
4587            } else {
4588                return Some((k, v));
4589            }
4590        }
4591        if self.kind.is_method_def() {
4592            self.get_mut_nominal_type_ctx(&mono(&self.name))
4593                .and_then(|ctx| ctx.remove_class_attr(name))
4594        } else {
4595            self.methods_list.iter_mut().find_map(|ctx| {
4596                if ctx.kind.is_trait_impl() {
4597                    None
4598                } else {
4599                    ctx.remove_class_attr(name)
4600                }
4601            })
4602        }
4603    }
4604
4605    /// does not include instance attribute declarations
4606    /// see also: `get_class_member`
4607    pub(crate) fn get_class_attr(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
4608        if let Some((k, v)) = self.locals.get_key_value(name) {
4609            if !v.kind.is_instance_attr() {
4610                return Some((k, v));
4611            }
4612        } else if let Some((k, v)) = self.decls.get_key_value(name) {
4613            if !v.kind.is_instance_attr() {
4614                return Some((k, v));
4615            }
4616        }
4617        if self.kind.is_method_def() {
4618            self.get_nominal_type_ctx(&mono(&self.name))
4619                .and_then(|ctx| ctx.get_class_attr(name))
4620        } else {
4621            self.methods_list.iter().find_map(|ctx| {
4622                if ctx.kind.is_trait_impl() {
4623                    None
4624                } else {
4625                    ctx.get_class_attr(name)
4626                }
4627            })
4628        }
4629    }
4630}