1use std::option::Option; use 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 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 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 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 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 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 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 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 _ => 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 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 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 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 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 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); 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 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 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 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 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 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 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 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 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 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 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 #[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 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 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 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 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 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 *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 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 .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); 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 .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 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); 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 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 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 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 #[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 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 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 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 || (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 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, .. } = ¬_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 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 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 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 } 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 ¶m_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 ¶m_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 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 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 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 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 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 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 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); }
3179 idx += 1;
3180 }
3181 concatenated
3182 }
3183
3184 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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) }
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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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}