erg_compiler/context/
mod.rs

1//! Defines `Context`.
2//!
3//! `Context` is used for type inference and type checking.
4#![allow(clippy::result_unit_err)]
5#![allow(clippy::assigning_clones)]
6pub mod compare;
7pub mod eval;
8pub mod generalize;
9pub mod hint;
10pub mod initialize;
11pub mod inquire;
12pub mod instantiate;
13pub mod instantiate_spec;
14pub mod register;
15pub mod test;
16pub mod unify;
17
18use std::fmt;
19use std::mem;
20use std::ops::{Deref, DerefMut};
21use std::option::Option; // conflicting to Type::Option
22use std::path::Path;
23
24use erg_common::config::ErgConfig;
25use erg_common::consts::DEBUG_MODE;
26use erg_common::consts::ERG_MODE;
27use erg_common::consts::PYTHON_MODE;
28use erg_common::dict::Dict;
29use erg_common::error::Location;
30use erg_common::impl_display_from_debug;
31use erg_common::pathutil::NormalizedPathBuf;
32use erg_common::traits::{Locational, Stream};
33use erg_common::Str;
34use erg_common::{fmt_option, fn_name, get_hash, log};
35
36use ast::{DefId, DefKind, VarName};
37use erg_parser::ast;
38use erg_parser::ast::Def;
39use erg_parser::ast::Signature;
40use erg_parser::token::Token;
41
42use crate::context::instantiate::TyVarCache;
43use crate::context::instantiate_spec::ConstTemplate;
44use crate::error::{TyCheckError, TyCheckErrors};
45use crate::hir::Identifier;
46use crate::module::SharedModuleGraph;
47use crate::module::{
48    SharedCompilerResource, SharedModuleCache, SharedModuleIndex, SharedPromises, SharedTraitImpls,
49};
50use crate::ty::value::ValueObj;
51use crate::ty::GuardType;
52use crate::ty::ParamTy;
53use crate::ty::{Predicate, Type, Visibility, VisibilityModifier};
54use crate::varinfo::{AbsLocation, Mutability, VarInfo, VarKind};
55use Type::*;
56
57/// For implementing LSP or other IDE features
58pub trait ContextProvider {
59    fn dir(&self) -> Dict<&VarName, &VarInfo>;
60    fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context>;
61    fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)>;
62    fn has(&self, name: &str) -> bool {
63        self.get_var_info(name).is_some()
64    }
65}
66
67#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
68pub enum ControlKind {
69    If,
70    While,
71    For,
72    Match,
73    Try,
74    With,
75    Discard,
76    Assert,
77}
78
79impl fmt::Display for ControlKind {
80    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81        match self {
82            Self::If => write!(f, "if"),
83            Self::While => write!(f, "while"),
84            Self::For => write!(f, "for"),
85            Self::Match => write!(f, "match"),
86            Self::Try => write!(f, "try"),
87            Self::With => write!(f, "with"),
88            Self::Discard => write!(f, "discard"),
89            Self::Assert => write!(f, "assert"),
90        }
91    }
92}
93
94impl TryFrom<&str> for ControlKind {
95    type Error = ();
96    fn try_from(s: &str) -> Result<Self, Self::Error> {
97        match s {
98            "if" | "if!" => Ok(ControlKind::If),
99            "while!" => Ok(ControlKind::While),
100            "while" if PYTHON_MODE => Ok(ControlKind::While),
101            "for" | "for!" => Ok(ControlKind::For),
102            "match" | "match!" => Ok(ControlKind::Match),
103            "try" | "try!" => Ok(ControlKind::Try),
104            "with" | "with!" => Ok(ControlKind::With),
105            "discard" => Ok(ControlKind::Discard),
106            "assert" => Ok(ControlKind::Assert),
107            _ => Err(()),
108        }
109    }
110}
111
112impl ControlKind {
113    pub const fn is_if(&self) -> bool {
114        matches!(self, Self::If)
115    }
116    /// if | if! | while!
117    pub const fn is_conditional(&self) -> bool {
118        matches!(self, Self::If | Self::While)
119    }
120    pub const fn makes_scope(&self) -> bool {
121        !matches!(self, Self::Assert)
122    }
123}
124
125#[derive(Debug, Clone)]
126pub struct TraitImpl {
127    pub sub_type: Type,
128    pub sup_trait: Type,
129    pub declared_in: Option<NormalizedPathBuf>,
130}
131
132impl PartialEq for TraitImpl {
133    fn eq(&self, other: &Self) -> bool {
134        self.sub_type == other.sub_type && self.sup_trait == other.sup_trait
135    }
136}
137
138impl Eq for TraitImpl {}
139
140impl std::hash::Hash for TraitImpl {
141    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
142        self.sub_type.hash(state);
143        self.sup_trait.hash(state);
144    }
145}
146
147impl std::fmt::Display for TraitImpl {
148    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
149        write!(f, "TraitImpl{{{} <: {}}}", self.sub_type, self.sup_trait)
150    }
151}
152
153impl TraitImpl {
154    pub const fn new(
155        sub_type: Type,
156        sup_trait: Type,
157        declared_in: Option<NormalizedPathBuf>,
158    ) -> Self {
159        Self {
160            sub_type,
161            sup_trait,
162            declared_in,
163        }
164    }
165}
166
167#[derive(Debug, Clone, PartialEq, Eq, Hash)]
168pub enum ClassDefType {
169    Simple(Type),
170    ImplTrait { class: Type, impl_trait: Type },
171}
172
173impl std::fmt::Display for ClassDefType {
174    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
175        match self {
176            ClassDefType::Simple(ty) => write!(f, "{ty}"),
177            ClassDefType::ImplTrait { class, impl_trait } => {
178                write!(f, "{class}|<: {impl_trait}|")
179            }
180        }
181    }
182}
183
184impl ClassDefType {
185    pub const fn impl_trait(class: Type, impl_trait: Type) -> Self {
186        ClassDefType::ImplTrait { class, impl_trait }
187    }
188
189    pub fn get_class(&self) -> &Type {
190        match self {
191            ClassDefType::Simple(class) => class,
192            ClassDefType::ImplTrait { class, .. } => class,
193        }
194    }
195
196    pub fn get_impl_trait(&self) -> Option<&Type> {
197        match self {
198            ClassDefType::Simple(_) => None,
199            ClassDefType::ImplTrait { impl_trait, .. } => Some(impl_trait),
200        }
201    }
202
203    pub fn is_class_of(&self, t: &Type) -> bool {
204        match self {
205            ClassDefType::Simple(class) => class == t,
206            ClassDefType::ImplTrait { class, .. } => class == t,
207        }
208    }
209
210    pub fn is_impl_of(&self, trait_: &Type) -> bool {
211        match self {
212            ClassDefType::ImplTrait { impl_trait, .. } => impl_trait == trait_,
213            _ => false,
214        }
215    }
216}
217
218#[derive(Debug, Clone)]
219pub struct MethodContext {
220    pub id: DefId,
221    pub typ: ClassDefType,
222    pub ctx: Context,
223}
224
225impl Deref for MethodContext {
226    type Target = Context;
227
228    fn deref(&self) -> &Self::Target {
229        &self.ctx
230    }
231}
232
233impl DerefMut for MethodContext {
234    fn deref_mut(&mut self) -> &mut Self::Target {
235        &mut self.ctx
236    }
237}
238
239impl MethodContext {
240    pub const fn new(id: DefId, typ: ClassDefType, ctx: Context) -> Self {
241        Self { id, typ, ctx }
242    }
243}
244
245#[derive(Debug, Clone, Default)]
246pub struct TypeContext {
247    pub typ: Type,
248    pub ctx: Context,
249}
250
251impl Deref for TypeContext {
252    type Target = Context;
253
254    fn deref(&self) -> &Self::Target {
255        &self.ctx
256    }
257}
258
259impl DerefMut for TypeContext {
260    fn deref_mut(&mut self) -> &mut Self::Target {
261        &mut self.ctx
262    }
263}
264
265impl TypeContext {
266    pub const fn new(typ: Type, ctx: Context) -> Self {
267        Self { typ, ctx }
268    }
269
270    /// contains both class attributes and instance attributes
271    /// see also: `get_class_attr`
272    pub(crate) fn get_class_member<'c>(
273        &'c self,
274        name: &VarName,
275        ctx: &'c Context,
276    ) -> Option<&'c VarInfo> {
277        self.get_current_scope_attr(name).or_else(|| {
278            let sups = ctx.get_nominal_super_type_ctxs(&self.typ)?;
279            for sup in sups {
280                if let Some(vi) = sup.get_current_scope_attr(name) {
281                    return Some(vi);
282                }
283            }
284            None
285        })
286    }
287
288    pub(crate) fn get_trait_impl_types(&self, trait_: &Type) -> Option<(&Type, &Type)> {
289        self.ctx.methods_list.iter().find_map(|mc| match &mc.typ {
290            ClassDefType::ImplTrait { class, impl_trait }
291                if impl_trait.qual_name() == trait_.qual_name() =>
292            {
293                Some((class, impl_trait))
294            }
295            _ => None,
296        })
297    }
298}
299
300#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
301pub enum DefaultInfo {
302    NonDefault, // var-args should be non-default
303    WithDefault,
304}
305
306impl_display_from_debug!(DefaultInfo);
307
308impl DefaultInfo {
309    pub const fn has_default(&self) -> bool {
310        matches!(self, DefaultInfo::WithDefault)
311    }
312}
313
314#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
315pub enum Variance {
316    /// Output(T), 共変, +
317    Covariant,
318    /// Input(T), 反変, -
319    Contravariant,
320    /// 不変, 0
321    #[default]
322    Invariant,
323}
324
325impl_display_from_debug!(Variance);
326
327impl std::ops::Mul for Variance {
328    type Output = Self;
329
330    fn mul(self, rhs: Self) -> Self::Output {
331        match (self, rhs) {
332            (Variance::Covariant, Variance::Covariant)
333            | (Variance::Contravariant, Variance::Contravariant) => Variance::Covariant,
334            (Variance::Covariant, Variance::Contravariant)
335            | (Variance::Contravariant, Variance::Covariant) => Variance::Contravariant,
336            _ => Variance::Invariant,
337        }
338    }
339}
340
341impl Variance {
342    pub const fn is_invariant(&self) -> bool {
343        matches!(self, Variance::Invariant)
344    }
345}
346
347#[derive(Debug, Clone, PartialEq, Eq, Hash)]
348pub struct ParamSpec {
349    pub(crate) name: Option<Str>,
350    // TODO: `:` or `<:`
351    pub(crate) t: Type,
352    pub is_var_params: bool,
353    pub default_info: DefaultInfo,
354    loc: AbsLocation,
355}
356
357impl ParamSpec {
358    pub fn new<S: Into<Str>>(
359        name: Option<S>,
360        t: Type,
361        is_var_params: bool,
362        default: DefaultInfo,
363        loc: AbsLocation,
364    ) -> Self {
365        Self {
366            name: name.map(|s| s.into()),
367            t,
368            is_var_params,
369            default_info: default,
370            loc,
371        }
372    }
373
374    pub fn named<S: Into<Str>>(
375        name: S,
376        t: Type,
377        is_var_params: bool,
378        default: DefaultInfo,
379    ) -> Self {
380        Self::new(
381            Some(name),
382            t,
383            is_var_params,
384            default,
385            AbsLocation::unknown(),
386        )
387    }
388
389    pub fn named_nd<S: Into<Str>>(name: S, t: Type) -> Self {
390        Self::new(
391            Some(name),
392            t,
393            false,
394            DefaultInfo::NonDefault,
395            AbsLocation::unknown(),
396        )
397    }
398
399    pub fn default<S: Into<Str>>(name: S, t: Type) -> Self {
400        Self::new(
401            Some(name),
402            t,
403            false,
404            DefaultInfo::WithDefault,
405            AbsLocation::unknown(),
406        )
407    }
408
409    pub fn t<S: Into<Str>>(name: S, is_var_params: bool, default: DefaultInfo) -> Self {
410        Self::new(
411            Some(name),
412            Type,
413            is_var_params,
414            default,
415            AbsLocation::unknown(),
416        )
417    }
418
419    pub fn t_nd<S: Into<Str>>(name: S) -> Self {
420        Self::new(
421            Some(name),
422            Type,
423            false,
424            DefaultInfo::NonDefault,
425            AbsLocation::unknown(),
426        )
427    }
428
429    pub fn has_default(&self) -> bool {
430        self.default_info.has_default()
431    }
432}
433
434impl From<&ParamSpec> for ParamTy {
435    fn from(param: &ParamSpec) -> Self {
436        if let Some(name) = &param.name {
437            ParamTy::kw(name.clone(), param.t.clone())
438        } else {
439            ParamTy::Pos(param.t.clone())
440        }
441    }
442}
443
444#[derive(Debug, Clone, PartialEq, Eq, Hash)]
445pub enum ContextKind {
446    LambdaFunc(Option<ControlKind>),
447    LambdaProc(Option<ControlKind>),
448    Func,
449    Proc,
450    Class,
451    MethodDefs(Option<Type>), // Type: trait implemented
452    PatchMethodDefs(Type),
453    Trait,
454    StructuralTrait,
455    Patch(Type),
456    StructuralPatch(Type),
457    // use Box to reduce the size of enum
458    GluePatch(Box<TraitImpl>), // TODO: deprecate (integrate into Patch)
459    Module,
460    Instant,
461    Record,
462    Dummy,
463}
464
465impl From<&Def> for ContextKind {
466    fn from(def: &Def) -> Self {
467        match def.def_kind() {
468            DefKind::Class | DefKind::Inherit => Self::Class,
469            DefKind::Trait | DefKind::Subsume => Self::Trait,
470            DefKind::StructuralTrait => Self::StructuralTrait,
471            DefKind::ErgImport | DefKind::PyImport | DefKind::RsImport | DefKind::InlineModule => {
472                Self::Module
473            }
474            DefKind::Other => {
475                if let Signature::Subr(subr) = &def.sig {
476                    if subr.ident.is_procedural() {
477                        Self::Proc
478                    } else {
479                        Self::Func
480                    }
481                } else {
482                    Self::Instant
483                }
484            }
485            // FIXME: Patch(Type),
486            DefKind::Patch => Self::Instant,
487        }
488    }
489}
490
491impl fmt::Display for ContextKind {
492    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
493        match self {
494            Self::LambdaFunc(kind) => write!(f, "LambdaFunc({})", fmt_option!(kind)),
495            Self::LambdaProc(kind) => write!(f, "LambdaProc({})", fmt_option!(kind)),
496            Self::Func => write!(f, "Func"),
497            Self::Proc => write!(f, "Proc"),
498            Self::Class => write!(f, "Class"),
499            Self::MethodDefs(trait_) => write!(f, "MethodDefs({})", fmt_option!(trait_)),
500            Self::PatchMethodDefs(type_) => write!(f, "PatchMethodDefs({type_})"),
501            Self::Trait => write!(f, "Trait"),
502            Self::StructuralTrait => write!(f, "StructuralTrait"),
503            Self::Patch(type_) => write!(f, "Patch({type_})"),
504            Self::StructuralPatch(type_) => write!(f, "StructuralPatch({type_})"),
505            Self::GluePatch(type_) => write!(f, "GluePatch({type_})"),
506            Self::Module => write!(f, "Module"),
507            Self::Instant => write!(f, "Instant"),
508            Self::Record => write!(f, "Record"),
509            Self::Dummy => write!(f, "Dummy"),
510        }
511    }
512}
513
514impl ContextKind {
515    pub const fn is_method_def(&self) -> bool {
516        matches!(self, Self::MethodDefs(_))
517    }
518
519    pub const fn is_trait_impl(&self) -> bool {
520        matches!(self, Self::MethodDefs(Some(_)))
521    }
522
523    pub const fn is_type(&self) -> bool {
524        matches!(self, Self::Class | Self::Trait | Self::StructuralTrait)
525    }
526
527    pub const fn is_subr(&self) -> bool {
528        matches!(
529            self,
530            Self::Func | Self::Proc | Self::LambdaFunc(_) | Self::LambdaProc(_)
531        )
532    }
533
534    pub const fn is_class(&self) -> bool {
535        matches!(self, Self::Class)
536    }
537
538    pub const fn is_trait(&self) -> bool {
539        matches!(self, Self::Trait | Self::StructuralTrait)
540    }
541
542    pub const fn is_patch(&self) -> bool {
543        matches!(self, Self::Patch(_) | Self::GluePatch(_))
544    }
545
546    pub const fn is_module(&self) -> bool {
547        matches!(self, Self::Module)
548    }
549
550    pub const fn is_instant(&self) -> bool {
551        matches!(self, Self::Instant)
552    }
553
554    pub const fn control_kind(&self) -> Option<ControlKind> {
555        match self {
556            Self::LambdaFunc(kind) | Self::LambdaProc(kind) => *kind,
557            _ => None,
558        }
559    }
560}
561
562/// Indicates the mode registered in the Context
563/// Preregister: subroutine or constant expression, can be forward referenced
564/// Normal: Cannot be forward referenced
565/// 環境に登録されているモードを表す
566/// Preregister: サブルーチンまたは定数式、前方参照できる
567/// Normal: 前方参照できない
568#[derive(Debug, Clone, Copy, PartialEq, Eq)]
569pub enum RegistrationMode {
570    PreRegister,
571    Normal,
572}
573
574impl RegistrationMode {
575    pub const fn is_preregister(&self) -> bool {
576        matches!(self, Self::PreRegister)
577    }
578    pub const fn is_normal(&self) -> bool {
579        matches!(self, Self::Normal)
580    }
581}
582
583#[derive(Debug, Clone, PartialEq, Eq, Hash)]
584pub struct MethodPair {
585    pub definition_type: Type,
586    pub method_info: VarInfo,
587}
588
589impl fmt::Display for MethodPair {
590    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
591        write!(
592            f,
593            "{{ def: {} info: {} }}",
594            self.definition_type, self.method_info
595        )
596    }
597}
598
599impl MethodPair {
600    pub const fn new(definition_type: Type, method_info: VarInfo) -> Self {
601        Self {
602            definition_type,
603            method_info,
604        }
605    }
606}
607
608/// Represents the context of the current scope
609///
610/// Recursive functions/methods are highlighted with the prefix `rec_`, as performance may be significantly degraded.
611#[derive(Debug, Clone)]
612pub struct Context {
613    pub name: Str,
614    pub kind: ContextKind,
615    pub(crate) cfg: ErgConfig,
616    pub(crate) preds: Vec<Predicate>,
617    /// for looking up the parent scope
618    pub(crate) outer: Option<Box<Context>>,
619    // e.g. { "Add": [ConstObjTemplate::App("Self", vec![])])
620    pub(crate) const_param_defaults: Dict<Str, Vec<ConstTemplate>>,
621    // Superclasses/supertraits by a patch are not included here
622    // patchによってsuper class/traitになったものはここに含まれない
623    pub(crate) super_classes: Vec<Type>, // if self is a patch, means patch classes
624    pub(crate) super_traits: Vec<Type>,  // if self is not a trait, means implemented traits
625    // method definitions, if the context is a type
626    // specializations are included and needs to be separated out
627    pub(crate) methods_list: Vec<MethodContext>,
628    // K: method name, V: types defines the method
629    // If it is declared in a trait, it takes precedence over the class.
630    pub(crate) method_to_traits: Dict<Str, Vec<MethodPair>>,
631    pub(crate) method_to_classes: Dict<Str, Vec<MethodPair>>,
632    /// K: method name, V: impl patch
633    /// Provided methods can switch implementations on a scope-by-scope basis
634    /// K: メソッド名, V: それを実装するパッチたち
635    /// 提供メソッドはスコープごとに実装を切り替えることができる
636    pub(crate) method_impl_patches: Dict<VarName, Vec<VarName>>,
637    /// stores declared names (not initialized)
638    pub(crate) decls: Dict<VarName, VarInfo>,
639    /// for error reporting
640    pub(crate) future_defined_locals: Dict<VarName, VarInfo>,
641    pub(crate) deleted_locals: Dict<VarName, VarInfo>,
642    // stores defined names
643    // 型の一致はHashMapでは判定できないため、keyはVarNameとして1つずつ見ていく
644    /// ```python
645    /// f [x, y], z = ...
646    /// ```
647    /// => params: vec![(None, [T; 2]), (Some("z"), U)]
648    /// => locals: {"x": T, "y": T}
649    /// TODO: impl params desugaring and replace to `Dict`
650    pub(crate) params: Vec<(Option<VarName>, VarInfo)>,
651    pub(crate) params_spec: Vec<ParamSpec>,
652    pub(crate) locals: Dict<VarName, VarInfo>,
653    pub(crate) consts: Dict<VarName, ValueObj>,
654    // {"Nat": ctx, "Int": ctx, ...}
655    pub(crate) mono_types: Dict<VarName, TypeContext>,
656    // Implementation Contexts for Polymorphic Types
657    // Vec<TyParam> are specialization parameters
658    // e.g. {"List": [(List(Nat), ctx), (List(Int), ctx), (List(Str), ctx), (List(Obj), ctx), (List('T), ctx)], ...}
659    pub(crate) poly_types: Dict<VarName, TypeContext>,
660    // patches can be accessed like normal records
661    // but when used as a fallback to a type, values are traversed instead of accessing by keys
662    pub(crate) patches: Dict<VarName, Context>,
663    pub(crate) shared: Option<SharedCompilerResource>,
664    pub(crate) tv_cache: Option<TyVarCache>,
665    pub(crate) higher_order_caller: Vec<Str>,
666    pub(crate) guards: Vec<GuardType>,
667    pub(crate) erg_to_py_names: Dict<Str, Str>,
668    pub(crate) captured_names: Vec<Identifier>,
669    pub(crate) level: usize,
670}
671
672impl Default for Context {
673    #[inline]
674    fn default() -> Self {
675        Self::default_with_name("<dummy>")
676    }
677}
678
679impl fmt::Display for Context {
680    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
681        f.debug_struct("Context")
682            .field("name", &self.name)
683            .field("preds", &self.preds)
684            .field("params", &self.params)
685            .field("decls", &self.decls)
686            .field("locals", &self.params)
687            .field("consts", &self.consts)
688            .field("mono_types", &self.mono_types)
689            .field("poly_types", &self.poly_types)
690            .field("patches", &self.patches)
691            // .field("mod_cache", &self.mod_cache)
692            .finish()
693    }
694}
695
696impl ContextProvider for Context {
697    fn dir(&self) -> Dict<&VarName, &VarInfo> {
698        let mut vars = self.type_dir(self);
699        if let Some(outer) = self.get_outer_scope() {
700            vars.guaranteed_extend(outer.dir());
701        } else if let Some(builtins) = self.get_builtins_not_self() {
702            vars.guaranteed_extend(builtins.locals.iter());
703        }
704        vars
705    }
706
707    fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
708        self.get_mod(receiver_name)
709            .or_else(|| self.rec_local_get_type(receiver_name).map(|ctx| &ctx.ctx))
710            .or_else(|| {
711                let (_, vi) = self.get_var_info(receiver_name)?;
712                self.get_nominal_type_ctx(&vi.t).map(|ctx| &ctx.ctx)
713            })
714    }
715
716    // this is internally recursive
717    fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
718        self.get_var_kv(name).or_else(|| {
719            self.get_builtins_not_self()
720                .and_then(|builtin| builtin.get_var_kv(name))
721        })
722    }
723}
724
725impl Context {
726    pub fn dir(&self) -> Dict<&VarName, &VarInfo> {
727        ContextProvider::dir(self)
728    }
729
730    pub fn get_receiver_ctx(&self, receiver_name: &str) -> Option<&Context> {
731        ContextProvider::get_receiver_ctx(self, receiver_name)
732    }
733
734    pub fn get_receiver_ctxs(&self, receiver_name: &str) -> Vec<&Context> {
735        let mut ctxs = vec![];
736        if let Some(receiver_ctx) = self.get_receiver_ctx(receiver_name) {
737            ctxs.push(receiver_ctx);
738            ctxs.extend(
739                receiver_ctx
740                    .super_classes
741                    .iter()
742                    .flat_map(|t| self.get_nominal_type_ctx(t).map(|ctx| &ctx.ctx)),
743            );
744        }
745        ctxs
746    }
747
748    pub fn get_var_info(&self, name: &str) -> Option<(&VarName, &VarInfo)> {
749        ContextProvider::get_var_info(self, name)
750    }
751
752    pub fn has(&self, name: &str) -> bool {
753        ContextProvider::has(self, name)
754    }
755
756    /// NOTE: Actually, this can be used for searching variables, attributes, etc.
757    pub fn get_type_info(&self, typ: &Type) -> Option<(&VarName, &VarInfo)> {
758        let namespace = typ.namespace();
759        let ctx = self.get_namespace(&namespace)?;
760        ctx.get_var_info(&typ.local_name())
761    }
762
763    pub fn unregister(&mut self, name: &str) -> Option<VarInfo> {
764        self.mono_types.remove(name);
765        self.poly_types.remove(name);
766        self.patches.remove(name);
767        self.erg_to_py_names.remove(name);
768        self.locals
769            .remove(name)
770            .or_else(|| self.locals.remove(name))
771    }
772}
773
774impl Context {
775    #[allow(clippy::too_many_arguments)]
776    #[inline]
777    pub fn new(
778        name: Str,
779        cfg: ErgConfig,
780        kind: ContextKind,
781        params: Vec<ParamSpec>,
782        outer: Option<Context>,
783        shared: Option<SharedCompilerResource>,
784        level: usize,
785    ) -> Self {
786        Self::with_capacity(name, cfg, kind, params, outer, shared, 0, level)
787    }
788
789    pub fn default_with_name(name: &'static str) -> Self {
790        Self::new(
791            name.into(),
792            ErgConfig::default(),
793            ContextKind::Dummy,
794            vec![],
795            None,
796            None,
797            Self::TOP_LEVEL,
798        )
799    }
800
801    #[allow(clippy::too_many_arguments)]
802    pub fn with_capacity(
803        name: Str,
804        cfg: ErgConfig,
805        kind: ContextKind,
806        params: Vec<ParamSpec>,
807        outer: Option<Context>,
808        shared: Option<SharedCompilerResource>,
809        capacity: usize,
810        level: usize,
811    ) -> Self {
812        let mut params_ = Vec::new();
813        for param in params.clone().into_iter() {
814            let id = DefId(get_hash(&(&name, &param)));
815            if let Some(name) = param.name {
816                let var_kind = VarKind::parameter(id, param.is_var_params, param.default_info);
817                let muty = Mutability::from(&name[..]);
818                let vi = VarInfo::new(
819                    param.t,
820                    muty,
821                    Visibility::private(&name),
822                    var_kind,
823                    None,
824                    kind.clone(),
825                    None,
826                    param.loc,
827                );
828                params_.push((Some(VarName::new(Token::symbol(&name))), vi));
829            } else {
830                let var_kind = VarKind::parameter(id, param.is_var_params, param.default_info);
831                let muty = Mutability::Immutable;
832                let vi = VarInfo::new(
833                    param.t,
834                    muty,
835                    Visibility::private(name.clone()),
836                    var_kind,
837                    None,
838                    kind.clone(),
839                    None,
840                    param.loc,
841                );
842                params_.push((None, vi));
843            }
844        }
845        Self {
846            name,
847            cfg,
848            kind,
849            preds: vec![],
850            outer: outer.map(Box::new),
851            super_classes: vec![],
852            super_traits: vec![],
853            methods_list: vec![],
854            const_param_defaults: Dict::default(),
855            method_to_traits: Dict::default(),
856            method_to_classes: Dict::default(),
857            method_impl_patches: Dict::default(),
858            params: params_,
859            params_spec: params,
860            decls: Dict::default(),
861            future_defined_locals: Dict::default(),
862            deleted_locals: Dict::default(),
863            locals: Dict::with_capacity(capacity),
864            consts: Dict::default(),
865            mono_types: Dict::default(),
866            poly_types: Dict::default(),
867            shared,
868            tv_cache: None,
869            patches: Dict::default(),
870            higher_order_caller: vec![],
871            guards: vec![],
872            erg_to_py_names: Dict::default(),
873            captured_names: vec![],
874            level,
875        }
876    }
877
878    #[inline]
879    pub fn mono(
880        name: Str,
881        cfg: ErgConfig,
882        kind: ContextKind,
883        outer: Option<Context>,
884        shared: Option<SharedCompilerResource>,
885        level: usize,
886    ) -> Self {
887        Self::new(name, cfg, kind, vec![], outer, shared, level)
888    }
889
890    #[allow(clippy::too_many_arguments)]
891    #[inline]
892    pub fn poly(
893        name: Str,
894        cfg: ErgConfig,
895        kind: ContextKind,
896        params: Vec<ParamSpec>,
897        outer: Option<Context>,
898        shared: Option<SharedCompilerResource>,
899        capacity: usize,
900        level: usize,
901    ) -> Self {
902        Self::with_capacity(name, cfg, kind, params, outer, shared, capacity, level)
903    }
904
905    pub fn poly_trait<S: Into<Str>>(
906        name: S,
907        params: Vec<ParamSpec>,
908        cfg: ErgConfig,
909        shared: Option<SharedCompilerResource>,
910        capacity: usize,
911        level: usize,
912    ) -> Self {
913        let name = name.into();
914        Self::poly(
915            name,
916            cfg,
917            ContextKind::Trait,
918            params,
919            None,
920            shared,
921            capacity,
922            level,
923        )
924    }
925
926    #[inline]
927    pub fn builtin_poly_trait<S: Into<Str>>(
928        name: S,
929        params: Vec<ParamSpec>,
930        capacity: usize,
931    ) -> Self {
932        Self::poly_trait(
933            name,
934            params,
935            ErgConfig::default(),
936            None,
937            capacity,
938            Self::TOP_LEVEL,
939        )
940    }
941
942    pub fn poly_class<S: Into<Str>>(
943        name: S,
944        params: Vec<ParamSpec>,
945        cfg: ErgConfig,
946        shared: Option<SharedCompilerResource>,
947        capacity: usize,
948        level: usize,
949    ) -> Self {
950        let name = name.into();
951        Self::poly(
952            name,
953            cfg,
954            ContextKind::Class,
955            params,
956            None,
957            shared,
958            capacity,
959            level,
960        )
961    }
962
963    #[inline]
964    pub fn builtin_poly_class<S: Into<Str>>(
965        name: S,
966        params: Vec<ParamSpec>,
967        capacity: usize,
968    ) -> Self {
969        Self::poly_class(
970            name,
971            params,
972            ErgConfig::default(),
973            None,
974            capacity,
975            Self::TOP_LEVEL,
976        )
977    }
978
979    #[allow(clippy::too_many_arguments)]
980    pub fn poly_patch<S: Into<Str>>(
981        name: S,
982        base: Type,
983        params: Vec<ParamSpec>,
984        cfg: ErgConfig,
985        shared: Option<SharedCompilerResource>,
986        capacity: usize,
987        level: usize,
988    ) -> Self {
989        let name = name.into();
990        Self::poly(
991            name,
992            cfg,
993            ContextKind::Patch(base),
994            params,
995            None,
996            shared,
997            capacity,
998            level,
999        )
1000    }
1001
1002    #[inline]
1003    pub fn mono_trait<S: Into<Str>>(
1004        name: S,
1005        cfg: ErgConfig,
1006        shared: Option<SharedCompilerResource>,
1007        capacity: usize,
1008        level: usize,
1009    ) -> Self {
1010        Self::poly_trait(name, vec![], cfg, shared, capacity, level)
1011    }
1012
1013    #[inline]
1014    pub fn builtin_mono_trait<S: Into<Str>>(name: S, capacity: usize) -> Self {
1015        Self::mono_trait(name, ErgConfig::default(), None, capacity, Self::TOP_LEVEL)
1016    }
1017
1018    #[inline]
1019    pub fn mono_class<S: Into<Str>>(
1020        name: S,
1021        cfg: ErgConfig,
1022        shared: Option<SharedCompilerResource>,
1023        capacity: usize,
1024        level: usize,
1025    ) -> Self {
1026        Self::poly_class(name, vec![], cfg, shared, capacity, level)
1027    }
1028
1029    #[inline]
1030    pub fn builtin_mono_class<S: Into<Str>>(name: S, capacity: usize) -> Self {
1031        Self::mono_class(name, ErgConfig::default(), None, capacity, Self::TOP_LEVEL)
1032    }
1033
1034    #[inline]
1035    pub fn mono_patch<S: Into<Str>>(
1036        name: S,
1037        base: Type,
1038        cfg: ErgConfig,
1039        shared: Option<SharedCompilerResource>,
1040        capacity: usize,
1041        level: usize,
1042    ) -> Self {
1043        Self::poly_patch(name, base, vec![], cfg, shared, capacity, level)
1044    }
1045
1046    #[inline]
1047    pub fn methods(
1048        impl_trait: Option<Type>,
1049        cfg: ErgConfig,
1050        shared: Option<SharedCompilerResource>,
1051        capacity: usize,
1052        level: usize,
1053    ) -> Self {
1054        let name = if let Some(tr) = &impl_trait {
1055            tr.local_name()
1056        } else {
1057            Str::ever("Methods")
1058        };
1059        Self::with_capacity(
1060            name,
1061            cfg,
1062            ContextKind::MethodDefs(impl_trait),
1063            vec![],
1064            None,
1065            shared,
1066            capacity,
1067            level,
1068        )
1069    }
1070
1071    #[inline]
1072    pub fn builtin_methods(impl_trait: Option<Type>, capacity: usize) -> Self {
1073        Self::methods(
1074            impl_trait,
1075            ErgConfig::default(),
1076            None,
1077            capacity,
1078            Self::TOP_LEVEL,
1079        )
1080    }
1081
1082    #[allow(clippy::too_many_arguments)]
1083    #[inline]
1084    pub fn poly_glue_patch<S: Into<Str>>(
1085        name: S,
1086        base: Type,
1087        impls: Type,
1088        params: Vec<ParamSpec>,
1089        cfg: ErgConfig,
1090        shared: Option<SharedCompilerResource>,
1091        capacity: usize,
1092        level: usize,
1093    ) -> Self {
1094        Self::poly(
1095            name.into(),
1096            cfg,
1097            ContextKind::GluePatch(Box::new(TraitImpl::new(base, impls, None))),
1098            params,
1099            None,
1100            shared,
1101            capacity,
1102            level,
1103        )
1104    }
1105
1106    #[inline]
1107    pub fn builtin_poly_glue_patch<S: Into<Str>>(
1108        name: S,
1109        base: Type,
1110        impls: Type,
1111        params: Vec<ParamSpec>,
1112        capacity: usize,
1113    ) -> Self {
1114        Self::poly_glue_patch(
1115            name,
1116            base,
1117            impls,
1118            params,
1119            ErgConfig::default(),
1120            None,
1121            capacity,
1122            Self::TOP_LEVEL,
1123        )
1124    }
1125
1126    #[inline]
1127    pub fn builtin_patch<S: Into<Str>>(
1128        name: S,
1129        impls: Type,
1130        params: Vec<ParamSpec>,
1131        capacity: usize,
1132    ) -> Self {
1133        Self::poly(
1134            name.into(),
1135            ErgConfig::default(),
1136            ContextKind::Patch(impls),
1137            params,
1138            None,
1139            None,
1140            capacity,
1141            Self::TOP_LEVEL,
1142        )
1143    }
1144
1145    #[inline]
1146    pub fn module(
1147        name: Str,
1148        cfg: ErgConfig,
1149        shared: Option<SharedCompilerResource>,
1150        capacity: usize,
1151    ) -> Self {
1152        Self::with_capacity(
1153            name,
1154            cfg,
1155            ContextKind::Module,
1156            vec![],
1157            None,
1158            shared,
1159            capacity,
1160            Self::TOP_LEVEL,
1161        )
1162    }
1163
1164    #[inline]
1165    pub fn builtin_module<S: Into<Str>>(
1166        name: S,
1167        cfg: ErgConfig,
1168        shared: SharedCompilerResource,
1169        capacity: usize,
1170    ) -> Self {
1171        Self::module(name.into(), cfg, Some(shared), capacity)
1172    }
1173
1174    #[inline]
1175    pub fn instant(
1176        name: Str,
1177        cfg: ErgConfig,
1178        capacity: usize,
1179        shared: Option<SharedCompilerResource>,
1180        outer: Context,
1181    ) -> Self {
1182        Self::with_capacity(
1183            name,
1184            cfg,
1185            ContextKind::Instant,
1186            vec![],
1187            Some(outer),
1188            shared,
1189            capacity,
1190            Self::TOP_LEVEL,
1191        )
1192    }
1193
1194    pub(crate) fn module_path(&self) -> &Path {
1195        self.cfg.input.path()
1196    }
1197
1198    pub(crate) fn absolutize(&self, loc: Location) -> AbsLocation {
1199        AbsLocation::new(Some(NormalizedPathBuf::from(self.module_path())), loc)
1200    }
1201
1202    #[inline]
1203    pub fn caused_by(&self) -> String {
1204        String::from(&self.name[..])
1205    }
1206
1207    /// use `get_outer_scope` for getting the outer scope
1208    pub(crate) fn get_outer(&self) -> Option<&Context> {
1209        self.outer.as_ref().map(|x| x.as_ref())
1210    }
1211
1212    /// If both `self` and `outer` are modules, returns `None` because the outer namespace is different from the current context
1213    pub(crate) fn get_outer_scope(&self) -> Option<&Context> {
1214        let outer = self.get_outer()?;
1215        if outer.name != "<builtins>" && outer.kind.is_module() && self.kind.is_module() {
1216            None
1217        } else {
1218            Some(outer)
1219        }
1220    }
1221
1222    pub(crate) fn get_outer_scope_or_builtins(&self) -> Option<&Context> {
1223        self.get_outer_scope()
1224            .or_else(|| self.get_builtins_not_self())
1225    }
1226
1227    pub(crate) fn get_mut_outer(&mut self) -> Option<&mut Context> {
1228        self.outer.as_mut().map(|x| x.as_mut())
1229    }
1230
1231    pub(crate) fn impl_of(&self) -> Option<Type> {
1232        if let ContextKind::MethodDefs(Some(tr)) = &self.kind {
1233            Some(tr.clone())
1234        } else {
1235            None
1236        }
1237    }
1238
1239    pub fn is_empty(&self) -> bool {
1240        let default_locals = if ERG_MODE { 4 } else { 3 };
1241        self.super_classes.is_empty()
1242            && self.super_traits.is_empty()
1243            && self.methods_list.is_empty()
1244            && self.const_param_defaults.is_empty()
1245            && self.method_to_traits.is_empty()
1246            && self.method_to_classes.is_empty()
1247            && self.method_impl_patches.is_empty()
1248            && self.params.is_empty()
1249            && self.params_spec.is_empty()
1250            && self.decls.is_empty()
1251            && self.future_defined_locals.is_empty()
1252            && self.deleted_locals.is_empty()
1253            && self.consts.is_empty()
1254            && self.mono_types.is_empty()
1255            && self.poly_types.is_empty()
1256            && self.patches.is_empty()
1257            && self.locals.len() <= default_locals
1258    }
1259
1260    pub(crate) fn path(&self) -> Str {
1261        // NOTE: maybe this need to be changed if we want to support nested classes/traits
1262        if self.kind == ContextKind::Module {
1263            self.name.replace(".__init__", "").into()
1264        } else if let Some(outer) = self.get_outer() {
1265            outer.path()
1266        } else {
1267            self.name.replace(".__init__", "").into()
1268        }
1269    }
1270
1271    /// Returns None if self is `<builtins>`.
1272    /// This avoids infinite loops.
1273    pub(crate) fn get_builtins_not_self(&self) -> Option<&Context> {
1274        if &self.path()[..] != "<builtins>" {
1275            self.get_builtins()
1276        } else {
1277            None
1278        }
1279    }
1280
1281    /// Be careful with infinite loops. See also `get_builtins_not_self`.
1282    pub(crate) fn get_builtins(&self) -> Option<&Context> {
1283        // builtins中で定義した型等はmod_cacheがNoneになっている
1284        self.shared
1285            .as_ref()
1286            .map(|shared| shared.mod_cache.raw_ref_builtins_ctx().unwrap())
1287            .map(|mod_ctx| &mod_ctx.context)
1288    }
1289
1290    pub(crate) fn get_module(&self) -> Option<&Context> {
1291        self.get_outer()
1292            .and_then(|outer| {
1293                if outer.kind == ContextKind::Module {
1294                    Some(outer)
1295                } else {
1296                    outer.get_module()
1297                }
1298            })
1299            .or_else(|| {
1300                if self.kind == ContextKind::Module {
1301                    Some(self)
1302                } else {
1303                    None
1304                }
1305            })
1306    }
1307
1308    pub(crate) fn get_module_from_stack(&self, path: &NormalizedPathBuf) -> Option<&Context> {
1309        if self.kind == ContextKind::Module && &NormalizedPathBuf::from(self.module_path()) == path
1310        {
1311            return Some(self);
1312        }
1313        self.get_outer()
1314            .and_then(|outer| outer.get_module_from_stack(path))
1315    }
1316
1317    /// This method is intended to be called __only__ in the top-level module.
1318    /// `.cfg` is not initialized and is used around.
1319    pub fn initialize(&mut self) {
1320        let mut shared = mem::take(&mut self.shared);
1321        if let Some(mod_cache) = shared.as_mut().map(|s| &mut s.mod_cache) {
1322            mod_cache.initialize();
1323        }
1324        if let Some(py_mod_cache) = shared.as_mut().map(|s| &mut s.py_mod_cache) {
1325            py_mod_cache.initialize();
1326        }
1327        *self = Self::new(
1328            self.name.clone(),
1329            self.cfg.clone(),
1330            self.kind.clone(),
1331            vec![],
1332            None,
1333            shared,
1334            self.level,
1335        );
1336    }
1337
1338    pub(crate) fn grow(
1339        &mut self,
1340        name: &str,
1341        kind: ContextKind,
1342        vis: VisibilityModifier,
1343        tv_cache: Option<TyVarCache>,
1344    ) {
1345        let name = if kind.is_module() {
1346            name.into()
1347        } else if vis.is_public() {
1348            format!("{parent}.{name}", parent = self.name)
1349        } else {
1350            format!("{parent}::{name}", parent = self.name)
1351        };
1352        log!(info "{}: current namespace: {name}", fn_name!());
1353        self.outer = Some(Box::new(mem::take(self)));
1354        // self.level += 1;
1355        self.cfg = self.get_outer().unwrap().cfg.clone();
1356        self.shared = self.get_outer().unwrap().shared.clone();
1357        self.higher_order_caller = self.get_outer().unwrap().higher_order_caller.clone();
1358        self.tv_cache = tv_cache;
1359        self.name = name.into();
1360        self.kind = kind;
1361    }
1362
1363    pub(crate) fn replace(&mut self, new: Self) {
1364        let old = mem::take(self);
1365        *self = new;
1366        self.outer = Some(Box::new(old));
1367        self.cfg = self.get_outer().unwrap().cfg.clone();
1368        self.shared = self.get_outer().unwrap().shared.clone();
1369        self.higher_order_caller = self.get_outer().unwrap().higher_order_caller.clone();
1370    }
1371
1372    pub(crate) fn clear_invalid_vars(&mut self) {
1373        self.locals.retain(|_, v| v.t != Failure);
1374        self.decls.retain(|_, v| v.t != Failure);
1375        self.params.retain(|(_, v)| v.t != Failure);
1376    }
1377
1378    /// Note that the popped context is detached and `outer == None`.
1379    pub fn pop(&mut self) -> Context {
1380        self.check_types();
1381        if let Some(parent) = self.outer.take() {
1382            let ctx = mem::take(self);
1383            *self = *parent;
1384            log!(info "{}: current namespace: {}", fn_name!(), self.name);
1385            ctx
1386        } else {
1387            panic!("cannot pop the top-level context (or use `pop_mod`)");
1388        }
1389    }
1390
1391    /// unlike `pop`, `outer` must be `None`.
1392    pub fn pop_mod(&mut self) -> Option<Context> {
1393        self.check_types();
1394        if self.outer.is_some() {
1395            log!(err "not in the top-level context");
1396            if self.kind.is_module() {
1397                Some(self.pop())
1398            } else {
1399                None
1400            }
1401        } else {
1402            log!(info "{}: current namespace: <builtins>", fn_name!());
1403            // toplevel
1404            Some(mem::take(self))
1405        }
1406    }
1407
1408    pub(crate) fn check_decls_and_pop(&mut self) -> (Context, TyCheckErrors) {
1409        match self.check_decls() {
1410            Ok(_) => (self.pop(), TyCheckErrors::empty()),
1411            Err(errs) => (self.pop(), errs),
1412        }
1413    }
1414
1415    pub(crate) fn check_decls(&mut self) -> Result<(), TyCheckErrors> {
1416        let mut uninited_errs = TyCheckErrors::empty();
1417        for (name, vi) in self.decls.iter() {
1418            uninited_errs.push(TyCheckError::uninitialized_error(
1419                self.cfg.input.clone(),
1420                line!() as usize,
1421                name.loc(),
1422                self.caused_by(),
1423                name.inspect(),
1424                &vi.t,
1425            ));
1426        }
1427        if !uninited_errs.is_empty() {
1428            Err(uninited_errs)
1429        } else {
1430            Ok(())
1431        }
1432    }
1433
1434    /// enumerates all the variables/methods in the current context & super contexts.
1435    pub(crate) fn type_dir<'t>(&'t self, namespace: &'t Context) -> Dict<&'t VarName, &'t VarInfo> {
1436        let mut attrs = self.locals.iter().collect::<Dict<_, _>>();
1437        attrs.guaranteed_extend(
1438            self.params
1439                .iter()
1440                .filter_map(|(k, v)| k.as_ref().map(|k| (k, v))),
1441        );
1442        attrs.guaranteed_extend(self.decls.iter());
1443        attrs.guaranteed_extend(
1444            self.methods_list
1445                .iter()
1446                .flat_map(|ctx| ctx.type_dir(namespace)),
1447        );
1448        if let Some(tv_cache) = &self.tv_cache {
1449            attrs.guaranteed_extend(tv_cache.var_infos.iter());
1450        }
1451        for sup in self.super_classes.iter() {
1452            if let Some(sup_ctx) = namespace.get_nominal_type_ctx(sup) {
1453                if sup_ctx.name == self.name {
1454                    continue;
1455                }
1456                attrs.guaranteed_extend(sup_ctx.type_dir(namespace));
1457            }
1458        }
1459        for sup in self.super_traits.iter() {
1460            if let Some(sup_ctx) = namespace.get_nominal_type_ctx(sup) {
1461                if sup_ctx.name == self.name {
1462                    continue;
1463                }
1464                attrs.guaranteed_extend(sup_ctx.type_impl_dir(namespace));
1465            }
1466        }
1467        attrs
1468    }
1469
1470    fn type_impl_dir<'t>(&'t self, namespace: &'t Context) -> Dict<&'t VarName, &'t VarInfo> {
1471        let mut attrs = self.locals.iter().collect::<Dict<_, _>>();
1472        attrs.guaranteed_extend(
1473            self.methods_list
1474                .iter()
1475                .flat_map(|ctx| ctx.type_impl_dir(namespace)),
1476        );
1477        for sup in self.super_classes.iter().chain(self.super_traits.iter()) {
1478            if let Some(sup_ctx) = namespace.get_nominal_type_ctx(sup) {
1479                if sup_ctx.name == self.name {
1480                    continue;
1481                }
1482                attrs.guaranteed_extend(sup_ctx.type_impl_dir(namespace));
1483            }
1484        }
1485        attrs
1486    }
1487
1488    pub fn local_dir(&self) -> Dict<&VarName, &VarInfo> {
1489        self.type_dir(self)
1490    }
1491
1492    pub(crate) fn opt_mod_cache(&self) -> Option<&SharedModuleCache> {
1493        self.shared.as_ref().map(|s| &s.mod_cache)
1494    }
1495
1496    pub(crate) fn mod_cache(&self) -> &SharedModuleCache {
1497        &self.shared().mod_cache
1498    }
1499
1500    pub(crate) fn opt_py_mod_cache(&self) -> Option<&SharedModuleCache> {
1501        self.shared.as_ref().map(|s| &s.py_mod_cache)
1502    }
1503
1504    pub(crate) fn py_mod_cache(&self) -> &SharedModuleCache {
1505        &self.shared().py_mod_cache
1506    }
1507
1508    pub(crate) fn opt_index(&self) -> Option<&SharedModuleIndex> {
1509        self.shared.as_ref().map(|s| &s.index)
1510    }
1511
1512    pub fn index(&self) -> &SharedModuleIndex {
1513        &self.shared().index
1514    }
1515
1516    pub fn graph(&self) -> &SharedModuleGraph {
1517        &self.shared().graph
1518    }
1519
1520    pub fn trait_impls(&self) -> &SharedTraitImpls {
1521        &self.shared().trait_impls
1522    }
1523
1524    pub fn shared(&self) -> &SharedCompilerResource {
1525        self.shared.as_ref().unwrap()
1526    }
1527
1528    pub fn promises(&self) -> &SharedPromises {
1529        &self.shared().promises
1530    }
1531
1532    pub fn current_control_flow(&self) -> Option<ControlKind> {
1533        self.higher_order_caller
1534            .last()
1535            .and_then(|name| ControlKind::try_from(&name[..]).ok())
1536    }
1537
1538    pub fn control_kind(&self) -> Option<ControlKind> {
1539        for caller in self.higher_order_caller.iter().rev() {
1540            if let Ok(control) = ControlKind::try_from(&caller[..]) {
1541                return Some(control);
1542            }
1543        }
1544        None
1545    }
1546
1547    /// Context of the function that actually creates the scope.
1548    /// Control flow function blocks do not create actual scopes.
1549    pub fn current_true_function_ctx(&self) -> Option<&Context> {
1550        if self.kind.is_subr() && self.current_control_flow().is_none() {
1551            Some(self)
1552        } else if let Some(outer) = self.get_outer_scope() {
1553            outer.current_true_function_ctx()
1554        } else {
1555            None
1556        }
1557    }
1558
1559    pub(crate) fn check_types(&self) {
1560        if DEBUG_MODE {
1561            for (_, ctx) in self.poly_types.iter() {
1562                if ctx.typ.has_undoable_linked_var() {
1563                    panic!("{} has undoable linked vars", ctx.typ);
1564                }
1565                ctx.check_types();
1566            }
1567            for methods in self.methods_list.iter() {
1568                if methods.typ.get_class().has_undoable_linked_var() {
1569                    panic!("{} has undoable linked vars", methods.typ);
1570                }
1571                if methods
1572                    .typ
1573                    .get_impl_trait()
1574                    .is_some_and(|t| t.has_undoable_linked_var())
1575                {
1576                    panic!("{} has undoable linked vars", methods.typ);
1577                }
1578                methods.check_types();
1579            }
1580            if let Some(outer) = self.get_outer() {
1581                outer.check_types();
1582            }
1583        }
1584    }
1585
1586    pub(crate) fn get_tv_ctx(&self, ident: &ast::Identifier, args: &ast::Args) -> TyVarCache {
1587        let mut tv_ctx = TyVarCache::new(self.level, self);
1588        if let Some(ctx) = self.get_type_ctx(ident.inspect()) {
1589            let arg_ts = ctx.params.iter().map(|(_, vi)| &vi.t);
1590            for ((tp, arg), arg_t) in ctx.typ.typarams().iter().zip(args.pos_args()).zip(arg_ts) {
1591                let tp = self.detach_tp(tp.clone(), &mut tv_ctx);
1592                if let Some(ident) = &arg.expr.as_ident() {
1593                    if self.subtype_of(arg_t, &Type::Type) {
1594                        if let Ok(tv) = self.convert_tp_into_type(tp.clone()) {
1595                            let _ = tv_ctx.push_or_init_tyvar(&ident.name, &tv, self);
1596                            continue;
1597                        }
1598                    }
1599                    let _ = tv_ctx.push_or_init_typaram(&ident.name, &tp, self);
1600                }
1601            }
1602        }
1603        tv_ctx
1604    }
1605}
1606
1607#[derive(Debug, Clone, Default)]
1608pub struct ModuleContext {
1609    pub context: Context,
1610    pub scope: Dict<Str, Context>,
1611}
1612
1613impl ModuleContext {
1614    pub const fn new(toplevel: Context, scope: Dict<Str, Context>) -> Self {
1615        Self {
1616            context: toplevel,
1617            scope,
1618        }
1619    }
1620
1621    pub fn get_top_cfg(&self) -> ErgConfig {
1622        self.context.cfg.clone()
1623    }
1624
1625    pub fn is_empty(&self) -> bool {
1626        self.context.is_empty()
1627    }
1628}