1use crate::display::format_ty;
2use crate::env::{TypeEnv, collect_free_vars, generalize, instantiate, scheme, substitute_var};
3use crate::types::{InferContext, InferredSig, Scheme, Ty, is_arith_bound};
4use crate::unify::{UnifyError, unify};
5use crisp_ast::Span;
6use crisp_ast::count_holes;
7use crisp_ast::expr::{BinaryOp, Block, Expr, ExprKind, FieldInit, Stmt, UnaryOp};
8use crisp_ast::ident::Ident;
9use crisp_ast::is_hole_ident;
10use crisp_ast::item::{ExternBlock, FunctionDef, ImplBlock, Item, SourceFile, TypeBody};
11use crisp_ast::lift_holes;
12use crisp_ast::pat::{Pat, PatKind};
13use crisp_ast::ty::{Type, TypeKind};
14use crisp_resolve::module::load_module_graph;
15use crisp_resolve::{ResolvedRustImport, Resolver};
16use std::collections::{BTreeMap, BTreeSet};
17use std::path::Path;
18use thiserror::Error;
19
20#[derive(Debug, Error)]
21pub enum TypeError {
22 #[error("unification error: {0}")]
23 Unify(#[from] UnifyError),
24 #[error("[E0040] unknown type `{name}`")]
25 UnknownType { name: String, span: Span },
26 #[error("[E0041] unknown name `{name}`")]
27 UnknownName { name: String, span: Span },
28 #[error("[E0042] resolve error: {0}")]
29 Resolve(#[from] crisp_resolve::ResolveError),
30 #[error(
31 "[E0043] ambiguous field `{field}` on unresolved type; annotate the parameter (candidates: {candidates})"
32 )]
33 AmbiguousField {
34 field: String,
35 candidates: String,
36 span: Span,
37 },
38 #[error("[E0084] cannot instantiate `{func}` with `{ty}`: `{ty}` does not implement `{bound}`")]
39 UnsatisfiedBound {
40 func: String,
41 ty: String,
42 bound: String,
43 span: Span,
44 },
45 #[error(
46 "[E0085] implicit closure has {found} hole(s) `_` but a function of {expected} parameter(s) is expected; write `|x, y| …`"
47 )]
48 HoleArity {
49 expected: usize,
50 found: usize,
51 span: Span,
52 },
53 #[error(
54 "[E0086] hole `_` is only valid where a function value is expected; write `|x| …` or use `_` as a call argument"
55 )]
56 HoleMisplaced { span: Span },
57 #[error("unification error: {message}")]
58 UnifyAt { message: String, span: Span },
59}
60
61#[derive(Debug, Clone)]
62pub struct TypedCrate {
63 pub signatures: BTreeMap<String, InferredSig>,
64 pub inherent_methods: BTreeMap<String, BTreeMap<String, String>>,
66 pub rust_imports: Vec<ResolvedRustImport>,
68 pub impl_trait_args: BTreeMap<String, Vec<Ty>>,
70}
71
72#[derive(Debug, Clone)]
73struct TraitMethodStub {
74 params: Vec<(String, Option<Ty>)>,
75 ret: Option<Ty>,
76}
77
78#[derive(Debug, Clone)]
79struct CallInst {
80 args: Vec<Ty>,
81 span: Span,
82}
83
84pub struct TypeChecker {
85 ctx: InferContext,
86 env: TypeEnv,
87 structs: BTreeMap<String, BTreeMap<String, Ty>>,
88 shapes: BTreeSet<String>,
90 type_params: BTreeMap<String, Vec<String>>,
92 trait_generics: BTreeMap<String, Vec<String>>,
94 generic_params: BTreeMap<String, Ty>,
96 enums: BTreeMap<String, BTreeMap<String, Vec<Ty>>>,
98 traits: BTreeMap<String, BTreeMap<String, TraitMethodStub>>,
100 signatures: BTreeMap<String, InferredSig>,
101 inherent_methods: BTreeMap<String, BTreeMap<String, String>>,
103 loop_break_tys: Vec<Ty>,
105 impl_trait_fresh: BTreeMap<String, Vec<Ty>>,
107 impl_trait_args: BTreeMap<String, Vec<Ty>>,
109 fn_instantiations: BTreeMap<String, Vec<CallInst>>,
111 arith_named: BTreeMap<String, BTreeSet<String>>,
113 arith_vars: BTreeMap<u32, BTreeSet<String>>,
115 trait_impls: BTreeMap<String, BTreeSet<String>>,
117}
118
119impl TypeChecker {
120 pub fn check_crate(crate_root: &Path) -> Result<TypedCrate, TypeError> {
121 let resolved = Resolver::resolve_crate(crate_root)?;
122 let graph = load_module_graph(crate_root)?;
123 let mut checker = Self::new();
124 checker.register_prelude();
125 checker.register_rust_imports(&resolved.rust_imports);
126 for node in graph.modules.values() {
127 checker.collect_types(&node.module_path, &node.ast);
128 }
129 for node in graph.modules.values() {
132 checker.collect_fn_stubs(&node.module_path, &node.ast)?;
133 }
134 for node in graph.modules.values() {
135 checker.check_module(&node.module_path, &node.ast)?;
136 }
137 checker.seal_open_signatures();
140 checker.specialize_internal_functions()?;
141 Ok(TypedCrate {
142 signatures: checker.signatures,
143 inherent_methods: checker.inherent_methods,
144 rust_imports: resolved.rust_imports,
145 impl_trait_args: checker.impl_trait_args,
146 })
147 }
148
149 fn new() -> Self {
150 Self {
151 ctx: InferContext::new(),
152 env: TypeEnv::new(),
153 structs: BTreeMap::new(),
154 shapes: BTreeSet::new(),
155 type_params: BTreeMap::new(),
156 trait_generics: BTreeMap::new(),
157 generic_params: BTreeMap::new(),
158 enums: BTreeMap::new(),
159 traits: BTreeMap::new(),
160 signatures: BTreeMap::new(),
161 inherent_methods: BTreeMap::new(),
162 loop_break_tys: Vec::new(),
163 impl_trait_fresh: BTreeMap::new(),
164 impl_trait_args: BTreeMap::new(),
165 fn_instantiations: BTreeMap::new(),
166 arith_named: BTreeMap::new(),
167 arith_vars: BTreeMap::new(),
168 trait_impls: BTreeMap::new(),
169 }
170 }
171
172 fn register_rust_imports(&mut self, imports: &[ResolvedRustImport]) {
174 for imp in imports {
175 let (params, ret) = rust_import_fn_type(&imp.crate_name, &imp.item);
176 let fn_ty = Ty::Fn {
177 params: params.clone(),
178 ret: Box::new(ret.clone()),
179 };
180 self.env.insert(imp.local_name.clone(), scheme(fn_ty));
181 let module = format!("rust.{}", imp.crate_name);
182 let key = format!("{module}::{}", imp.local_name);
183 self.signatures.insert(
184 key,
185 InferredSig {
186 module,
187 name: imp.local_name.clone(),
188 impl_ty: None,
189 params: params
190 .into_iter()
191 .enumerate()
192 .map(|(i, t)| (format!("arg{i}"), t))
193 .collect(),
194 ret,
195 span: Span::new(0, 0),
196 generics: Vec::new(),
197 is_pub: false,
198 inferred_from_use: false,
199 instantiations: Vec::new(),
200 mono_args: None,
201 op_bounds: BTreeMap::new(),
202 },
203 );
204 }
205 }
206
207 fn register_prelude(&mut self) {
208 for (name, ty) in [
209 ("int", Ty::Int),
210 ("uint", Ty::UInt),
211 ("float", Ty::Float),
212 ("bool", Ty::Bool),
213 ("char", Ty::Char),
214 ("str", Ty::Str),
215 ("Never", Ty::Never),
216 (
217 "vec",
218 Ty::Named {
219 name: "vec".into(),
220 args: vec![],
221 },
222 ),
223 (
224 "map",
225 Ty::Named {
226 name: "map".into(),
227 args: vec![],
228 },
229 ),
230 (
231 "set",
232 Ty::Named {
233 name: "set".into(),
234 args: vec![],
235 },
236 ),
237 (
238 "log",
239 Ty::Fn {
240 params: vec![Ty::StrSlice],
241 ret: Box::new(Ty::Unit),
242 },
243 ),
244 (
245 "some",
246 Ty::Fn {
247 params: vec![self.ctx.fresh()],
248 ret: Box::new(Ty::Option(Box::new(self.ctx.fresh()))),
249 },
250 ),
251 (
252 "none",
253 Ty::Fn {
254 params: vec![],
255 ret: Box::new(Ty::Option(Box::new(self.ctx.fresh()))),
256 },
257 ),
258 ] {
259 self.env.insert(name, scheme(ty));
260 }
261 let p = self.ctx.fresh();
262 let assert_ty = Ty::Fn {
263 params: vec![p.clone(), p],
264 ret: Box::new(Ty::Unit),
265 };
266 let assert_scheme = generalize(&self.env, &mut self.ctx, &assert_ty);
267 self.env.insert("assert_eq", assert_scheme);
268
269 let pp = self.ctx.fresh();
270 let print_ty = Ty::Fn {
271 params: vec![pp.clone()],
272 ret: Box::new(Ty::Unit),
273 };
274 let print_scheme = generalize(&self.env, &mut self.ctx, &print_ty);
275 self.env.insert("print", print_scheme);
276
277 for (name, ty) in stdlib_fn_types() {
278 self.env.insert(name, scheme(ty));
279 }
280 self.register_prelude_traits();
281 }
282
283 fn register_prelude_traits(&mut self) {
284 self.traits.entry("Show".into()).or_insert_with(|| {
285 BTreeMap::from([(
286 "show".into(),
287 TraitMethodStub {
288 params: vec![("self".into(), None)],
289 ret: Some(Ty::Str),
290 },
291 )])
292 });
293 self.traits.entry("Eq".into()).or_insert_with(|| {
294 BTreeMap::from([(
295 "equal".into(),
296 TraitMethodStub {
297 params: vec![("self".into(), None), ("other".into(), None)],
298 ret: Some(Ty::Bool),
299 },
300 )])
301 });
302 self.traits.entry("Ord".into()).or_insert_with(|| {
303 BTreeMap::from([(
304 "compare".into(),
305 TraitMethodStub {
306 params: vec![("self".into(), None), ("other".into(), None)],
307 ret: Some(Ty::Int),
308 },
309 )])
310 });
311 }
312
313 fn collect_types(&mut self, module: &str, file: &SourceFile) {
314 for item in &file.items {
315 if let Item::TypeDef(td) = item {
316 let gens: Vec<String> = td.generics.iter().map(|g| g.name.clone()).collect();
317 if !gens.is_empty() {
318 self.type_params.insert(td.name.name.clone(), gens.clone());
319 }
320 let saved = self.bind_rigid_generics(&gens);
321 if let TypeBody::Struct(fields) = &td.body {
322 let mut field_map = BTreeMap::new();
323 for f in fields {
324 if let Ok(ty) = self.ast_type(&f.ty) {
325 field_map.insert(f.name.name.clone(), self.ctx.apply(&ty));
326 }
327 }
328 self.structs.insert(td.name.name.clone(), field_map);
329 self.env.insert(
330 td.name.name.clone(),
331 scheme(Ty::Named {
332 name: td.name.name.clone(),
333 args: vec![],
334 }),
335 );
336 } else if let TypeBody::Enum(variants) = &td.body {
337 let mut variant_map = BTreeMap::new();
338 for v in variants {
339 let mut fields = Vec::new();
340 for t in &v.fields {
341 if let Ok(ty) = self.ast_type(t) {
342 fields.push(self.ctx.apply(&ty));
343 }
344 }
345 variant_map.insert(v.name.name.clone(), fields);
346 }
347 self.enums.insert(td.name.name.clone(), variant_map);
348 self.env.insert(
349 td.name.name.clone(),
350 scheme(Ty::Named {
351 name: td.name.name.clone(),
352 args: vec![],
353 }),
354 );
355 } else if let TypeBody::Alias(ty) = &td.body
356 && let Ok(t) = self.ast_type(ty)
357 {
358 self.env.insert(td.name.name.clone(), scheme(t));
359 }
360 self.generic_params = saved;
361 } else if let Item::ShapeDef(shape) = item {
362 let gens: Vec<String> = shape.generics.iter().map(|g| g.name.clone()).collect();
364 if !gens.is_empty() {
365 self.type_params
366 .insert(shape.name.name.clone(), gens.clone());
367 }
368 let saved = self.bind_rigid_generics(&gens);
369 let mut field_map = BTreeMap::new();
370 for f in &shape.fields {
371 if let crisp_ast::item::ShapeField::Data { name, ty, .. } = f
372 && let Ok(field_ty) = self.ast_type(ty)
373 {
374 field_map.insert(name.name.clone(), self.ctx.apply(&field_ty));
375 }
376 }
377 self.shapes.insert(shape.name.name.clone());
378 self.structs.insert(shape.name.name.clone(), field_map);
379 self.env.insert(
380 shape.name.name.clone(),
381 scheme(Ty::Named {
382 name: shape.name.name.clone(),
383 args: vec![],
384 }),
385 );
386 self.generic_params = saved;
387 } else if let Item::TraitDef(td) = item {
388 let gens: Vec<String> = td.generics.iter().map(|g| g.name.clone()).collect();
389 if !gens.is_empty() {
390 self.trait_generics
391 .insert(td.name.name.clone(), gens.clone());
392 }
393 let saved = self.bind_rigid_generics(&gens);
394 let mut methods = BTreeMap::new();
395 for m in &td.items {
396 let mut params = Vec::new();
397 let mut ok = true;
398 for p in &m.params {
399 let ty = if p.name.name == "self" && p.ty.is_none() {
400 None
401 } else if let Some(ast_ty) = &p.ty {
402 match self.ast_type(ast_ty) {
403 Ok(t) => Some(t),
404 Err(_) => {
405 ok = false;
406 break;
407 }
408 }
409 } else {
410 Some(self.ctx.fresh())
411 };
412 params.push((p.name.name.clone(), ty));
413 }
414 if !ok {
415 continue;
416 }
417 let ret = match &m.ret_type {
418 Some(t) => match self.ast_type(t) {
419 Ok(t) => Some(t),
420 Err(_) => continue,
421 },
422 None => None,
423 };
424 methods.insert(m.name.name.clone(), TraitMethodStub { params, ret });
425 }
426 self.traits.insert(td.name.name.clone(), methods);
427 self.generic_params = saved;
428 }
429 }
430 let _ = module;
431 }
432
433 fn collect_fn_stubs(&mut self, module: &str, file: &SourceFile) -> Result<(), TypeError> {
434 for item in &file.items {
435 match item {
436 Item::Extern(ext) => {
437 self.check_extern(module, ext)?;
439 }
440 Item::Function(f) => {
441 let gens: Vec<String> = f.generics.iter().map(|g| g.name.clone()).collect();
442 let saved = self.bind_rigid_generics(&gens);
443 let mut params = Vec::new();
444 for p in &f.params {
445 let ty = if let Some(ast_ty) = &p.ty {
446 self.ast_type(ast_ty)?
447 } else {
448 self.ctx.fresh()
449 };
450 params.push(ty);
451 }
452 let ret = if let Some(t) = &f.ret_type {
453 self.ast_type(t)?
454 } else {
455 self.ctx.fresh()
456 };
457 let fn_ty = Ty::Fn {
458 params,
459 ret: Box::new(ret),
460 };
461 self.env.insert(
462 f.name.name.clone(),
463 generalize_named_params(&fn_ty, &gens, &mut self.ctx),
464 );
465 self.generic_params = saved;
466 }
467 Item::Impl(ib) => {
468 self.collect_impl_stubs(module, ib)?;
469 }
470 _ => {}
471 }
472 }
473 Ok(())
474 }
475
476 fn collect_impl_stubs(&mut self, module: &str, ib: &ImplBlock) -> Result<(), TypeError> {
477 let ty_name = match &ib.ty.kind {
478 TypeKind::Named(id) => id.name.clone(),
479 _ => {
480 return Err(TypeError::UnknownType {
481 name: "impl".into(),
482 span: ib.span,
483 });
484 }
485 };
486 let self_ty = Ty::Named {
487 name: ty_name.clone(),
488 args: vec![],
489 };
490 if let Some(tn) = &ib.trait_name {
491 self.trait_impls
492 .entry(ty_name.clone())
493 .or_default()
494 .insert(tn.name.clone());
495 }
496 let trait_subst = self.impl_trait_subst(module, ib, &ty_name)?;
497 for f in &ib.items {
498 let mut params = Vec::new();
499 for p in &f.params {
500 let ty = if p.name.name == "self" && p.ty.is_none() {
501 self_ty.clone()
502 } else if let Some(ast_ty) = &p.ty {
503 self.ast_type(ast_ty)?
504 } else {
505 self.ctx.fresh()
506 };
507 params.push(ty);
508 }
509 let mut ret = if let Some(t) = &f.ret_type {
510 self.ast_type(t)?
511 } else {
512 self.ctx.fresh()
513 };
514 if !trait_subst.is_empty() {
515 params = params
516 .into_iter()
517 .map(|t| subst_named_params(&t, &trait_subst))
518 .collect();
519 ret = subst_named_params(&ret, &trait_subst);
520 }
521 if let Some(tn) = &ib.trait_name
522 && let Some(methods) = self.traits.get(&tn.name)
523 && let Some(stub) = methods.get(&f.name.name)
524 && let Some(trait_ret) = &stub.ret
525 {
526 ret = subst_named_params(trait_ret, &trait_subst);
527 }
528 let key = format!("{module}::{ty_name}::{}", f.name.name);
529 self.inherent_methods
530 .entry(ty_name.clone())
531 .or_default()
532 .insert(f.name.name.clone(), key.clone());
533 self.signatures.insert(
535 key,
536 InferredSig {
537 module: module.to_string(),
538 name: f.name.name.clone(),
539 impl_ty: Some(ty_name.clone()),
540 params: f
541 .params
542 .iter()
543 .zip(params.iter())
544 .map(|(p, t)| (p.name.name.clone(), t.clone()))
545 .collect(),
546 ret,
547 span: f.span,
548 generics: Vec::new(),
549 is_pub: f.is_pub,
550 inferred_from_use: false,
551 instantiations: Vec::new(),
552 mono_args: None,
553 op_bounds: BTreeMap::new(),
554 },
555 );
556 }
557 if let Some(tn) = &ib.trait_name
559 && let Some(trait_methods) = self.traits.get(&tn.name).cloned()
560 {
561 for (mname, stub) in trait_methods {
562 let methods = self.inherent_methods.entry(ty_name.clone()).or_default();
563 if methods.contains_key(&mname) {
564 continue;
565 }
566 let key = format!("{module}::{ty_name}::{mname}");
567 methods.insert(mname.clone(), key.clone());
568 let sig_params: Vec<(String, Ty)> = stub
569 .params
570 .into_iter()
571 .map(|(pname, pty)| {
572 let ty = if pname == "self" {
573 self_ty.clone()
574 } else {
575 let t = pty.unwrap_or_else(|| self.ctx.fresh());
576 subst_named_params(&t, &trait_subst)
577 };
578 (pname, ty)
579 })
580 .collect();
581 let sig_ret =
582 subst_named_params(&stub.ret.unwrap_or_else(|| self.ctx.fresh()), &trait_subst);
583 self.signatures.insert(
584 key,
585 InferredSig {
586 module: module.to_string(),
587 name: mname,
588 impl_ty: Some(ty_name.clone()),
589 params: sig_params,
590 ret: sig_ret,
591 span: ib.span,
592 generics: Vec::new(),
593 is_pub: false,
594 inferred_from_use: false,
595 instantiations: Vec::new(),
596 mono_args: None,
597 op_bounds: BTreeMap::new(),
598 },
599 );
600 }
601 }
602 Ok(())
603 }
604
605 fn check_module(&mut self, module: &str, file: &SourceFile) -> Result<(), TypeError> {
606 for item in &file.items {
607 match item {
608 Item::Function(f) => self.check_function(module, f)?,
609 Item::Impl(ib) => self.check_impl(module, ib)?,
610 Item::Test(t) => self.check_test_block(module, &t.name, &t.body)?,
611 Item::TestCompileFail(_) | Item::Extern(_) => {}
612 _ => {}
613 }
614 }
615 Ok(())
616 }
617
618 fn env_for_generalize(&self, self_name: &str) -> TypeEnv {
622 let mut env = self.env.clone();
623 env.remove(self_name);
624 for sig in self.signatures.values() {
625 if sig.impl_ty.is_some() || sig.name.starts_with("test::") {
626 continue;
627 }
628 if sig.name != self_name {
629 env.remove(&sig.name);
630 }
631 }
632 env
633 }
634
635 fn seal_open_signatures(&mut self) {
637 let keys: Vec<String> = self.signatures.keys().cloned().collect();
638 for key in keys {
639 let Some(sig) = self.signatures.get(&key).cloned() else {
640 continue;
641 };
642 let param_types: Vec<(String, Ty)> = sig
643 .params
644 .iter()
645 .map(|(n, t)| (n.clone(), self.ctx.apply(t)))
646 .collect();
647 let ret = self.ctx.apply(&sig.ret);
648 if !sig.generics.is_empty() {
649 if let Some(s) = self.signatures.get_mut(&key) {
650 s.params = param_types;
651 s.ret = ret;
652 }
653 continue;
654 }
655 let fn_ty = Ty::Fn {
656 params: param_types.iter().map(|(_, t)| t.clone()).collect(),
657 ret: Box::new(ret.clone()),
658 };
659 let (named, inferred) = name_free_vars(&fn_ty);
660 if inferred.is_empty() {
661 if let Some(s) = self.signatures.get_mut(&key) {
662 s.params = param_types;
663 s.ret = ret;
664 }
665 continue;
666 }
667 let mut params = param_types;
668 let mut named_ret = ret;
669 if let Ty::Fn { params: ps, ret: r } = &named {
670 for (i, t) in ps.iter().enumerate() {
671 if let Some(slot) = params.get_mut(i) {
672 slot.1 = t.clone();
673 }
674 }
675 named_ret = r.as_ref().clone();
676 }
677 if let Some(s) = self.signatures.get_mut(&key) {
678 s.params = params;
679 s.ret = named_ret;
680 s.generics = inferred;
681 s.inferred_from_use = true;
682 }
683 }
684 }
685
686 fn check_impl(&mut self, module: &str, ib: &ImplBlock) -> Result<(), TypeError> {
687 let ty_name = match &ib.ty.kind {
688 TypeKind::Named(id) => id.name.clone(),
689 _ => {
690 return Err(TypeError::UnknownType {
691 name: "impl".into(),
692 span: ib.span,
693 });
694 }
695 };
696 for f in &ib.items {
697 self.check_impl_method(module, &ty_name, f)?;
698 }
699 self.finalize_impl_trait_args(module, ib, &ty_name)?;
700 Ok(())
701 }
702
703 fn check_impl_method(
704 &mut self,
705 module: &str,
706 ty_name: &str,
707 f: &FunctionDef,
708 ) -> Result<(), TypeError> {
709 let key = format!("{module}::{ty_name}::{}", f.name.name);
710 let stub = self.signatures.get(&key).cloned();
711 let (stub_params, stub_ret) = match stub {
712 Some(s) => (
713 s.params.iter().map(|(_, t)| t.clone()).collect::<Vec<_>>(),
714 Some(s.ret),
715 ),
716 None => (Vec::new(), None),
717 };
718 let self_ty = Ty::Named {
719 name: ty_name.to_string(),
720 args: vec![],
721 };
722
723 let mut local = self.env.clone();
724 let mut param_vars = Vec::new();
725 for (i, p) in f.params.iter().enumerate() {
726 let mut ty = stub_params
727 .get(i)
728 .cloned()
729 .unwrap_or_else(|| self.ctx.fresh());
730 if p.name.name == "self" && p.ty.is_none() {
731 unify(&mut self.ctx, &ty, &self_ty)?;
732 ty = self.ctx.apply(&self_ty);
733 } else if let Some(ast_ty) = &p.ty {
734 let ann = self.ast_type(ast_ty)?;
735 unify(&mut self.ctx, &ty, &ann)?;
736 ty = self.ctx.apply(&ann);
737 }
738 param_vars.push((p.name.name.clone(), ty.clone()));
739 local.insert(p.name.name.clone(), scheme(ty));
740 }
741 let ret_ann = f.ret_type.as_ref().map(|t| self.ast_type(t)).transpose()?;
742 let body_ty = self.infer_expr(&mut local, &f.body)?;
743 let param_types: Vec<(String, Ty)> = param_vars
744 .iter()
745 .map(|(n, t)| (n.clone(), self.ctx.apply(t)))
746 .collect();
747 let ret = if let Some(ann) = ret_ann {
748 unify(&mut self.ctx, &body_ty, &ann)?;
749 if let Some(stub_r) = &stub_ret {
750 unify(&mut self.ctx, &body_ty, stub_r)?;
751 }
752 self.ctx.apply(&ann)
753 } else if let Some(stub_r) = &stub_ret {
754 unify(&mut self.ctx, &body_ty, stub_r)?;
755 self.ctx.apply(&body_ty)
756 } else {
757 self.ctx.apply(&body_ty)
758 };
759 self.signatures.insert(
760 key.clone(),
761 InferredSig {
762 module: module.to_string(),
763 name: f.name.name.clone(),
764 impl_ty: Some(ty_name.to_string()),
765 params: param_types,
766 ret,
767 span: f.span,
768 generics: Vec::new(),
769 is_pub: f.is_pub,
770 inferred_from_use: false,
771 instantiations: Vec::new(),
772 mono_args: None,
773 op_bounds: BTreeMap::new(),
774 },
775 );
776 self.inherent_methods
777 .entry(ty_name.to_string())
778 .or_default()
779 .insert(f.name.name.clone(), key);
780 Ok(())
781 }
782
783 fn check_extern(&mut self, module: &str, ext: &ExternBlock) -> Result<(), TypeError> {
784 for f in &ext.functions {
785 let mut param_tys = Vec::new();
786 for p in &f.params {
787 let ty = if let Some(ast_ty) = &p.ty {
788 self.ast_type(ast_ty)?
789 } else {
790 Ty::Int
791 };
792 param_tys.push(ty);
793 }
794 let ret = if let Some(ast_ty) = &f.ret_type {
795 self.ast_type(ast_ty)?
796 } else {
797 Ty::Unit
798 };
799 let fn_ty = Ty::Fn {
800 params: param_tys.clone(),
801 ret: Box::new(ret.clone()),
802 };
803 self.env.insert(f.name.name.clone(), scheme(fn_ty));
804 let key = format!("{}::{}", module, f.name.name);
805 self.signatures.insert(
806 key,
807 InferredSig {
808 module: module.to_string(),
809 name: f.name.name.clone(),
810 impl_ty: None,
811 params: f
812 .params
813 .iter()
814 .enumerate()
815 .map(|(i, p)| (p.name.name.clone(), param_tys[i].clone()))
816 .collect(),
817 ret,
818 span: f.span,
819 generics: Vec::new(),
820 is_pub: false,
821 inferred_from_use: false,
822 instantiations: Vec::new(),
823 mono_args: None,
824 op_bounds: BTreeMap::new(),
825 },
826 );
827 }
828 let _ = ext;
829 Ok(())
830 }
831
832 fn check_test_block(
833 &mut self,
834 module: &str,
835 name: &str,
836 body: &Block,
837 ) -> Result<(), TypeError> {
838 let mut local = self.env.clone();
839 let body_ty = self.infer_block(&mut local, body)?;
840 unify(&mut self.ctx, &body_ty, &Ty::Unit)?;
841 let key = format!("{module}::test::{name}");
842 self.signatures.insert(
843 key,
844 InferredSig {
845 module: module.to_string(),
846 name: format!("test::{name}"),
847 impl_ty: None,
848 params: vec![],
849 ret: Ty::Unit,
850 span: body.span,
851 generics: Vec::new(),
852 is_pub: false,
853 inferred_from_use: false,
854 instantiations: Vec::new(),
855 mono_args: None,
856 op_bounds: BTreeMap::new(),
857 },
858 );
859 Ok(())
860 }
861
862 fn check_function(&mut self, module: &str, f: &FunctionDef) -> Result<(), TypeError> {
863 self.arith_named.clear();
864 self.arith_vars.clear();
865 let gens: Vec<String> = f.generics.iter().map(|g| g.name.clone()).collect();
866 let saved = self.bind_rigid_generics(&gens);
867 let stub = if gens.is_empty() {
870 self.env
871 .get(&f.name.name)
872 .map(|s| instantiate(&mut self.ctx, s))
873 .map(|t| self.ctx.apply(&t))
874 } else {
875 None
876 };
877 let (stub_params, stub_ret) = match stub {
878 Some(Ty::Fn { params, ret }) => (params, Some(*ret)),
879 _ => (Vec::new(), None),
880 };
881
882 let mut local = self.env.clone();
883 let mut param_vars = Vec::new();
884 for (i, p) in f.params.iter().enumerate() {
885 let mut ty = stub_params
886 .get(i)
887 .cloned()
888 .unwrap_or_else(|| self.ctx.fresh());
889 if let Some(ast_ty) = &p.ty {
890 let ann = self.ast_type(ast_ty)?;
891 unify(&mut self.ctx, &ty, &ann)?;
892 ty = self.ctx.apply(&ann);
893 }
894 param_vars.push((p.name.name.clone(), ty.clone()));
895 local.insert(p.name.name.clone(), scheme(ty));
896 }
897 let ret_ann = f.ret_type.as_ref().map(|t| self.ast_type(t)).transpose()?;
898 let body_ty = self.infer_expr(&mut local, &f.body)?;
899 let ret = if let Some(ann) = ret_ann {
900 unify(&mut self.ctx, &body_ty, &ann)?;
901 if let Some(stub_r) = &stub_ret {
902 unify(&mut self.ctx, &body_ty, stub_r)?;
903 }
904 self.ctx.apply(&ann)
905 } else if let Some(stub_r) = &stub_ret {
906 unify(&mut self.ctx, &body_ty, stub_r)?;
907 self.ctx.apply(&body_ty)
908 } else {
909 self.ctx.apply(&body_ty)
910 };
911 let param_types: Vec<(String, Ty)> = param_vars
912 .iter()
913 .map(|(n, t)| (n.clone(), self.ctx.apply(t)))
914 .collect();
915 let ret = self.ctx.apply(&ret);
916 let fn_params: Vec<Ty> = param_types.iter().map(|(_, t)| t.clone()).collect();
917 let mut fn_ty = Ty::Fn {
918 params: fn_params,
919 ret: Box::new(ret.clone()),
920 };
921 let mut gens = gens;
922 let mut param_types = param_types;
923 let mut ret = ret;
924 let mut inferred_from_use = false;
925 let pre_ty = fn_ty.clone();
931 if gens.is_empty() {
932 let env_wo = self.env_for_generalize(&f.name.name);
933 let gen_scheme = generalize(&env_wo, &mut self.ctx, &fn_ty);
934 if !gen_scheme.vars.is_empty() {
935 let (named, inferred) = name_vars(&fn_ty, &gen_scheme.vars);
936 if !inferred.is_empty() {
937 fn_ty = named;
938 gens = inferred;
939 inferred_from_use = true;
940 if let Ty::Fn { params, ret: r } = &fn_ty {
941 for (i, t) in params.iter().enumerate() {
942 if let Some(slot) = param_types.get_mut(i) {
943 slot.1 = t.clone();
944 }
945 }
946 ret = r.as_ref().clone();
947 }
948 }
949 }
950 }
951 let op_bounds = self.take_op_bounds(&pre_ty, &gens);
952 let key = format!("{module}::{}", f.name.name);
953 self.signatures.insert(
954 key,
955 InferredSig {
956 module: module.to_string(),
957 name: f.name.name.clone(),
958 impl_ty: None,
959 params: param_types,
960 ret: ret.clone(),
961 span: f.span,
962 generics: gens.clone(),
963 is_pub: f.is_pub,
964 inferred_from_use,
965 instantiations: Vec::new(),
966 mono_args: None,
967 op_bounds,
968 },
969 );
970 self.env.insert(
971 f.name.name.clone(),
972 if gens.is_empty() {
973 scheme(fn_ty)
974 } else {
975 generalize_named_params(&fn_ty, &gens, &mut self.ctx)
976 },
977 );
978 self.generic_params = saved;
979 Ok(())
980 }
981
982 fn specialize_internal_functions(&mut self) -> Result<(), TypeError> {
986 let insts = std::mem::take(&mut self.fn_instantiations);
987 self.check_instantiation_bounds(&insts)?;
988 let keys: Vec<String> = self.signatures.keys().cloned().collect();
989 for key in keys {
990 let Some(sig) = self.signatures.get(&key) else {
991 continue;
992 };
993 if let Some(uses) = insts.get(&sig.name) {
994 let mut labels: Vec<String> = uses
995 .iter()
996 .map(|u| u.args.iter().map(format_ty).collect::<Vec<_>>().join(", "))
997 .collect();
998 labels.sort();
999 labels.dedup();
1000 if let Some(sig) = self.signatures.get_mut(&key) {
1001 sig.instantiations = labels;
1002 }
1003 }
1004 let Some(sig) = self.signatures.get(&key) else {
1005 continue;
1006 };
1007 if sig.is_pub
1008 || !sig.inferred_from_use
1009 || sig.generics.is_empty()
1010 || sig.impl_ty.is_some()
1011 {
1012 continue;
1013 }
1014 let Some(uses) = insts.get(&sig.name) else {
1015 continue;
1016 };
1017 if uses.is_empty() {
1018 continue;
1019 }
1020 let first = &uses[0].args;
1021 if !first.iter().all(ty_is_ground) {
1022 continue;
1023 }
1024 if !uses.iter().all(|u| &u.args == first) {
1025 continue;
1026 }
1027 if let Some(sig) = self.signatures.get_mut(&key) {
1028 sig.mono_args = Some(first.clone());
1029 }
1030 }
1031 Ok(())
1032 }
1033
1034 fn infer_expr(&mut self, env: &mut TypeEnv, expr: &Expr) -> Result<Ty, TypeError> {
1035 match &expr.kind {
1036 ExprKind::Int(_) => Ok(Ty::Int),
1037 ExprKind::Float(_) => Ok(Ty::Float),
1038 ExprKind::Bool(_) => Ok(Ty::Bool),
1039 ExprKind::Char(_) => Ok(Ty::Char),
1040 ExprKind::Str(_) => Ok(Ty::Str),
1041 ExprKind::Unit => Ok(Ty::Unit),
1042 ExprKind::Ident(id) if is_hole_ident(&id.name) => {
1043 Err(TypeError::HoleMisplaced { span: id.span })
1044 }
1045 ExprKind::Ident(id) => self.lookup(env, &id.name, id.span),
1046 ExprKind::Block(b) => self.infer_block(env, b),
1047 ExprKind::If {
1048 cond,
1049 then_branch,
1050 else_branch,
1051 } => {
1052 let cty = self.infer_expr(env, cond)?;
1053 unify(&mut self.ctx, &cty, &Ty::Bool)?;
1054 let t = self.infer_expr(env, then_branch)?;
1055 if let Some(e) = else_branch {
1056 let e_ty = self.infer_expr(env, e)?;
1057 unify(&mut self.ctx, &t, &e_ty)?;
1058 }
1059 Ok(self.ctx.apply(&t))
1060 }
1061 ExprKind::Match { scrutinee, arms } => {
1062 let scrut = self.infer_expr(env, scrutinee)?;
1063 let mut local = env.clone();
1064 let mut result = None;
1065 for arm in arms {
1066 self.infer_pat(&mut local, &arm.pat, &scrut)?;
1067 if let Some(g) = &arm.guard {
1068 let gty = self.infer_expr(&mut local, g)?;
1069 unify(&mut self.ctx, >y, &Ty::Bool)?;
1070 }
1071 let body = self.infer_expr(&mut local, &arm.body)?;
1072 result = Some(match result {
1073 None => body,
1074 Some(prev) => {
1075 unify(&mut self.ctx, &prev, &body)?;
1076 prev
1077 }
1078 });
1079 }
1080 Ok(result.unwrap_or(Ty::Unit))
1081 }
1082 ExprKind::Lambda { params, body } => {
1083 let mut local = env.clone();
1084 let mut ptys = Vec::new();
1085 for p in params {
1086 let ty = if let Some(ast_ty) = &p.ty {
1087 self.ast_type(ast_ty)?
1088 } else {
1089 self.ctx.fresh()
1090 };
1091 ptys.push(self.ctx.apply(&ty));
1092 local.insert(p.name.name.clone(), scheme(ty));
1093 }
1094 let ret = self.infer_expr(&mut local, body)?;
1095 Ok(Ty::Fn {
1096 params: ptys,
1097 ret: Box::new(self.ctx.apply(&ret)),
1098 })
1099 }
1100 ExprKind::Call { func, args } => {
1101 if let ExprKind::Field { base, field } = &func.kind
1103 && let Some(ret) = self.try_infer_method_call(env, base, field, args)?
1104 {
1105 return Ok(ret);
1106 }
1107 let ft = self.infer_expr(env, func)?;
1108 let ft = self.ctx.apply(&ft);
1109 let (params, ret) = match ft {
1110 Ty::Fn { params, ret } => (params, ret),
1111 Ty::Var(v) => {
1112 let ps: Vec<_> = (0..args.len()).map(|_| self.ctx.fresh()).collect();
1113 let ret = self.ctx.fresh();
1114 unify(
1115 &mut self.ctx,
1116 &Ty::Var(v),
1117 &Ty::Fn {
1118 params: ps.clone(),
1119 ret: Box::new(ret.clone()),
1120 },
1121 )?;
1122 (ps, Box::new(ret))
1123 }
1124 other => {
1125 return Err(TypeError::UnifyAt {
1126 message: format!("type mismatch: expected function, found {other:?}"),
1127 span: expr.span,
1128 });
1129 }
1130 };
1131 if args.len() != params.len() {
1132 return Err(TypeError::Unify(UnifyError::Mismatch {
1133 expected: format!("{} arguments", params.len()),
1134 found: format!("{} arguments", args.len()),
1135 }));
1136 }
1137 for (arg, pty) in args.iter().zip(params.iter()) {
1138 let aty = self.infer_call_arg(env, arg, pty)?;
1139 self.unify_or_shape(&aty, pty)?;
1140 }
1141 if let ExprKind::Ident(id) = &func.kind {
1142 let applied: Vec<Ty> = params.iter().map(|p| self.ctx.apply(p)).collect();
1143 if applied.iter().all(ty_is_ground) {
1144 self.propagate_callee_bounds(&id.name, &applied);
1145 self.fn_instantiations
1146 .entry(id.name.clone())
1147 .or_default()
1148 .push(CallInst {
1149 args: applied,
1150 span: expr.span,
1151 });
1152 }
1153 }
1154 Ok(self.ctx.apply(&ret))
1155 }
1156 ExprKind::Field { base, field } => {
1157 if let ExprKind::Ident(id) = &base.kind
1159 && let Some(variants) = self.enums.get(&id.name)
1160 {
1161 return match variants.get(&field.name) {
1162 Some(payload) if payload.is_empty() => Ok(Ty::Named {
1163 name: id.name.clone(),
1164 args: vec![],
1165 }),
1166 Some(payload) => Ok(Ty::Fn {
1167 params: payload.clone(),
1168 ret: Box::new(Ty::Named {
1169 name: id.name.clone(),
1170 args: vec![],
1171 }),
1172 }),
1173 None => Err(TypeError::UnknownName {
1174 name: format!("{}.{}", id.name, field.name),
1175 span: field.span,
1176 }),
1177 };
1178 }
1179 if let ExprKind::Ident(id) = &base.kind
1181 && self.structs.contains_key(&id.name)
1182 && let Some(sig) = self.method_sig(&id.name, &field.name)
1183 {
1184 let has_self = sig
1185 .params
1186 .first()
1187 .map(|(n, _)| n == "self")
1188 .unwrap_or(false);
1189 if !has_self {
1190 let params: Vec<Ty> = sig.params.iter().map(|(_, t)| t.clone()).collect();
1191 return Ok(Ty::Fn {
1192 params,
1193 ret: Box::new(sig.ret.clone()),
1194 });
1195 }
1196 }
1197 let base_ty = self.infer_expr(env, base)?;
1198 self.field_type(&base_ty, &field.name, field.span)
1199 }
1200 ExprKind::Unary { op, expr } => match op {
1201 UnaryOp::Not => {
1202 let t = self.infer_expr(env, expr)?;
1203 unify(&mut self.ctx, &t, &Ty::Bool)?;
1204 Ok(Ty::Bool)
1205 }
1206 UnaryOp::Neg => {
1207 let t = self.infer_expr(env, expr)?;
1208 unify(&mut self.ctx, &t, &Ty::Int)?;
1209 Ok(Ty::Int)
1210 }
1211 },
1212 ExprKind::Binary { op, left, right } => self.infer_binary(env, *op, left, right),
1213 ExprKind::StructLit { name, fields } => self.check_struct_lit(env, name, fields),
1214 ExprKind::Bind { pat, value, .. } => {
1215 let ty = self.infer_value(env, value)?;
1216 let mut local = env.clone();
1217 self.infer_pat(&mut local, pat, &ty)?;
1218 Ok(Ty::Unit)
1219 }
1220 ExprKind::Pipe { left, right } => {
1221 let lt = self.infer_expr(env, left)?;
1222 let mut local = env.clone();
1223 let v = self.ctx.fresh();
1224 local.insert("_pipe".to_string(), scheme(v.clone()));
1225 unify(&mut self.ctx, <, &v)?;
1226 self.infer_expr(&mut local, right)
1227 }
1228 ExprKind::Return(Some(e)) => {
1229 self.infer_expr(env, e)?;
1230 Ok(Ty::Never)
1231 }
1232 ExprKind::Return(None) => Ok(Ty::Never),
1233 ExprKind::Try(inner) => {
1234 let t = self.infer_expr(env, inner)?;
1235 match self.ctx.apply(&t) {
1236 Ty::Option(inner) => Ok(*inner),
1237 other => {
1238 let fresh = self.ctx.fresh();
1239 unify(&mut self.ctx, &other, &Ty::Option(Box::new(fresh.clone())))?;
1240 Ok(self.ctx.apply(&fresh))
1241 }
1242 }
1243 }
1244 ExprKind::Catch { body, arms } => {
1245 let _ = self.infer_expr(env, body)?;
1246 let mut result = None;
1247 for arm in arms {
1248 let body_ty = self.infer_expr(env, &arm.body)?;
1249 result = Some(match result {
1250 None => body_ty,
1251 Some(prev) => {
1252 unify(&mut self.ctx, &prev, &body_ty)?;
1253 prev
1254 }
1255 });
1256 }
1257 Ok(result.unwrap_or(Ty::Unit))
1258 }
1259 ExprKind::Async(inner) => {
1260 let inner_ty = self.infer_expr(env, inner)?;
1261 Ok(Ty::Named {
1262 name: "Future".into(),
1263 args: vec![self.ctx.apply(&inner_ty)],
1264 })
1265 }
1266 ExprKind::Await(inner) => {
1267 let t = self.infer_expr(env, inner)?;
1268 match self.ctx.apply(&t) {
1269 Ty::Named { name, args } if name == "Future" && args.len() == 1 => {
1270 Ok(args[0].clone())
1271 }
1272 other => {
1273 let fresh = self.ctx.fresh();
1274 unify(
1275 &mut self.ctx,
1276 &other,
1277 &Ty::Named {
1278 name: "Future".into(),
1279 args: vec![fresh.clone()],
1280 },
1281 )?;
1282 Ok(self.ctx.apply(&fresh))
1283 }
1284 }
1285 }
1286 ExprKind::Unsafe(inner) => self.infer_expr(env, inner),
1287 ExprKind::Spawn(inner) => {
1288 self.infer_expr(env, inner)?;
1289 Ok(Ty::Named {
1290 name: "JoinHandle".into(),
1291 args: vec![],
1292 })
1293 }
1294 ExprKind::While { cond, body } => {
1295 let cty = self.infer_expr(env, cond)?;
1296 unify(&mut self.ctx, &cty, &Ty::Bool)?;
1297 self.infer_expr(env, body)?;
1298 Ok(Ty::Unit)
1299 }
1300 ExprKind::For { pat, iter, body } => {
1301 let iter_ty = self.infer_expr(env, iter)?;
1302 let vec_ty = Ty::Named {
1303 name: "vec".into(),
1304 args: vec![],
1305 };
1306 let item_ty = match self.ctx.apply(&iter_ty) {
1309 Ty::Named { name, .. } if name == "vec" => Ty::Int,
1310 other => {
1311 unify(&mut self.ctx, &other, &vec_ty)?;
1312 Ty::Int
1313 }
1314 };
1315 let mut local = env.clone();
1316 self.infer_pat(&mut local, pat, &item_ty)?;
1317 self.infer_expr(&mut local, body)?;
1318 Ok(Ty::Unit)
1319 }
1320 ExprKind::Loop(body) => {
1321 let break_ty = self.ctx.fresh();
1322 self.loop_break_tys.push(break_ty.clone());
1323 let _ = self.infer_expr(env, body)?;
1324 self.loop_break_tys.pop();
1325 Ok(self.ctx.apply(&break_ty))
1326 }
1327 ExprKind::Break(value) => {
1328 let vt = if let Some(v) = value {
1329 self.infer_expr(env, v)?
1330 } else {
1331 Ty::Unit
1332 };
1333 if let Some(expected) = self.loop_break_tys.last().cloned() {
1334 unify(&mut self.ctx, &vt, &expected)?;
1335 }
1336 Ok(Ty::Never)
1337 }
1338 ExprKind::Continue => Ok(Ty::Never),
1339 ExprKind::Assign { target, value } => {
1340 let expected = self.lookup(env, &target.name, target.span)?;
1341 let got = self.infer_value(env, value)?;
1342 unify(&mut self.ctx, &got, &expected).map_err(|e| TypeError::UnifyAt {
1343 message: e.to_string(),
1344 span: expr.span,
1345 })?;
1346 Ok(Ty::Unit)
1347 }
1348 _ => Ok(self.ctx.fresh()),
1349 }
1350 }
1351
1352 fn infer_binary(
1353 &mut self,
1354 env: &mut TypeEnv,
1355 op: BinaryOp,
1356 left: &Expr,
1357 right: &Expr,
1358 ) -> Result<Ty, TypeError> {
1359 let lt = self.infer_expr(env, left)?;
1360 let rt = self.infer_expr(env, right)?;
1361 match op {
1362 BinaryOp::Concat => {
1363 unify(&mut self.ctx, <, &Ty::Str)?;
1364 unify(&mut self.ctx, &rt, &Ty::StrSlice)?;
1365 Ok(Ty::Str)
1366 }
1367 BinaryOp::Mod => {
1368 unify(&mut self.ctx, <, &rt)?;
1369 unify(&mut self.ctx, <, &Ty::Int)?;
1370 Ok(Ty::Int)
1371 }
1372 BinaryOp::Add | BinaryOp::Sub | BinaryOp::Mul | BinaryOp::Div => {
1373 unify(&mut self.ctx, <, &rt)?;
1374 let t = self.ctx.apply(<);
1375 let r = self.ctx.apply(&rt);
1376 if matches!(t, Ty::Float) || matches!(r, Ty::Float) {
1377 unify(&mut self.ctx, &t, &Ty::Float)?;
1378 Ok(Ty::Float)
1379 } else if matches!(t, Ty::Int | Ty::UInt) || matches!(r, Ty::Int | Ty::UInt) {
1380 unify(&mut self.ctx, &t, &Ty::Int)?;
1381 Ok(Ty::Int)
1382 } else if let Some(op) = arith_trait_name(op) {
1383 self.record_arith(&t, op);
1384 Ok(t)
1385 } else {
1386 unify(&mut self.ctx, &t, &Ty::Int)?;
1387 Ok(Ty::Int)
1388 }
1389 }
1390 BinaryOp::Pow => {
1391 unify(&mut self.ctx, <, &Ty::Float)?;
1392 unify(&mut self.ctx, &rt, &Ty::Float)?;
1393 Ok(Ty::Float)
1394 }
1395 BinaryOp::Eq
1396 | BinaryOp::Ne
1397 | BinaryOp::Lt
1398 | BinaryOp::Le
1399 | BinaryOp::Gt
1400 | BinaryOp::Ge => {
1401 unify(&mut self.ctx, <, &rt)?;
1402 Ok(Ty::Bool)
1403 }
1404 BinaryOp::And | BinaryOp::Or => {
1405 unify(&mut self.ctx, <, &Ty::Bool)?;
1406 unify(&mut self.ctx, &rt, &Ty::Bool)?;
1407 Ok(Ty::Bool)
1408 }
1409 _ => Ok(self.ctx.fresh()),
1410 }
1411 }
1412
1413 fn infer_value(&mut self, env: &mut TypeEnv, expr: &Expr) -> Result<Ty, TypeError> {
1414 if count_holes(expr) > 0 {
1415 self.infer_hole_lambda(env, expr, None)
1416 } else {
1417 self.infer_expr(env, expr)
1418 }
1419 }
1420
1421 fn infer_call_arg(
1422 &mut self,
1423 env: &mut TypeEnv,
1424 arg: &Expr,
1425 expected: &Ty,
1426 ) -> Result<Ty, TypeError> {
1427 let expected = self.ctx.apply(expected);
1428 if count_holes(arg) > 0 {
1429 return self.infer_hole_lambda(env, arg, Some(&expected));
1430 }
1431 self.infer_expr(env, arg)
1432 }
1433
1434 fn infer_hole_lambda(
1435 &mut self,
1436 env: &mut TypeEnv,
1437 expr: &Expr,
1438 expected: Option<&Ty>,
1439 ) -> Result<Ty, TypeError> {
1440 let found = count_holes(expr);
1441 if found == 0 {
1442 return self.infer_expr(env, expr);
1443 }
1444 if let Some(exp) = expected {
1445 match self.ctx.apply(exp) {
1446 Ty::Fn { params, .. } if params.len() != found => {
1447 return Err(TypeError::HoleArity {
1448 expected: params.len(),
1449 found,
1450 span: expr.span,
1451 });
1452 }
1453 Ty::Fn { .. } => {}
1454 _ => return Err(TypeError::HoleMisplaced { span: expr.span }),
1455 }
1456 }
1457 let lifted = lift_holes(expr).expect("count_holes > 0");
1458 self.infer_expr(env, &lifted)
1459 }
1460
1461 fn infer_block(&mut self, env: &mut TypeEnv, block: &Block) -> Result<Ty, TypeError> {
1462 let mut local = env.clone();
1463 for stmt in &block.stmts {
1464 match stmt {
1465 Stmt::Bind { pat, value, .. } => {
1466 let ty = self.infer_value(&mut local, value)?;
1467 self.infer_pat(&mut local, pat, &ty)?;
1468 }
1469 Stmt::Assign { target, value } => {
1470 let expected = self.lookup(&local, &target.name, target.span)?;
1471 let got = self.infer_value(&mut local, value)?;
1472 unify(&mut self.ctx, &got, &expected)?;
1473 }
1474 Stmt::Expr(e) => {
1475 self.infer_expr(&mut local, e)?;
1476 }
1477 }
1478 }
1479 if let Some(tail) = &block.tail {
1480 self.infer_expr(&mut local, tail)
1481 } else {
1482 Ok(Ty::Unit)
1483 }
1484 }
1485
1486 fn infer_pat(&mut self, env: &mut TypeEnv, pat: &Pat, ty: &Ty) -> Result<(), TypeError> {
1487 match &pat.kind {
1488 PatKind::Wildcard => Ok(()),
1489 PatKind::Ident(id) => {
1490 env.insert(id.name.clone(), scheme(self.ctx.apply(ty)));
1492 Ok(())
1493 }
1494 PatKind::Tuple(pats) => {
1495 if let Ty::Tuple(ts) = self.ctx.apply(ty) {
1496 for (p, t) in pats.iter().zip(ts) {
1497 self.infer_pat(env, p, &t)?;
1498 }
1499 Ok(())
1500 } else {
1501 let vars: Vec<_> = (0..pats.len()).map(|_| self.ctx.fresh()).collect();
1502 unify(&mut self.ctx, ty, &Ty::Tuple(vars.clone()))?;
1503 for (p, t) in pats.iter().zip(vars) {
1504 self.infer_pat(env, p, &t)?;
1505 }
1506 Ok(())
1507 }
1508 }
1509 PatKind::Enum {
1510 name,
1511 variant,
1512 args,
1513 } => {
1514 let enum_ty = Ty::Named {
1515 name: name.name.clone(),
1516 args: vec![],
1517 };
1518 unify(&mut self.ctx, ty, &enum_ty)?;
1519 let Some(variants) = self.enums.get(&name.name) else {
1520 return Err(TypeError::UnknownType {
1521 name: name.name.clone(),
1522 span: name.span,
1523 });
1524 };
1525 let Some(payload) = variants.get(&variant.name) else {
1526 return Err(TypeError::UnknownName {
1527 name: format!("{}.{}", name.name, variant.name),
1528 span: variant.span,
1529 });
1530 };
1531 if args.len() != payload.len() {
1532 return Err(TypeError::Unify(UnifyError::Mismatch {
1533 expected: format!("{} payload fields", payload.len()),
1534 found: format!("{} pattern args", args.len()),
1535 }));
1536 }
1537 let payload = payload.clone();
1538 for (arg, field_ty) in args.iter().zip(payload) {
1539 self.infer_pat(env, arg, &field_ty)?;
1540 }
1541 Ok(())
1542 }
1543 _ => Ok(()),
1544 }
1545 }
1546
1547 fn check_struct_lit(
1548 &mut self,
1549 env: &mut TypeEnv,
1550 name: &Ident,
1551 fields: &[FieldInit],
1552 ) -> Result<Ty, TypeError> {
1553 let schema =
1554 self.structs
1555 .get(&name.name)
1556 .cloned()
1557 .ok_or_else(|| TypeError::UnknownType {
1558 name: name.name.clone(),
1559 span: name.span,
1560 })?;
1561 let gens = self
1562 .type_params
1563 .get(&name.name)
1564 .cloned()
1565 .unwrap_or_default();
1566 let subst: BTreeMap<String, Ty> =
1567 gens.iter().map(|g| (g.clone(), self.ctx.fresh())).collect();
1568 let schema: BTreeMap<String, Ty> = schema
1569 .iter()
1570 .map(|(k, v)| (k.clone(), subst_named_params(v, &subst)))
1571 .collect();
1572 let field_types: Vec<_> = fields
1573 .iter()
1574 .map(|field| {
1575 schema
1576 .get(&field.name.name)
1577 .cloned()
1578 .ok_or_else(|| TypeError::UnknownType {
1579 name: field.name.name.clone(),
1580 span: field.name.span,
1581 })
1582 })
1583 .collect::<Result<_, _>>()?;
1584 for (field, expected) in fields.iter().zip(field_types) {
1585 let got = self.infer_expr(env, &field.value)?;
1586 unify(&mut self.ctx, &got, &expected)?;
1587 }
1588 let args: Vec<Ty> = gens
1589 .iter()
1590 .map(|g| self.ctx.apply(subst.get(g).expect("generic subst")))
1591 .collect();
1592 Ok(Ty::Named {
1593 name: name.name.clone(),
1594 args,
1595 })
1596 }
1597
1598 fn method_sig(&self, ty_name: &str, method: &str) -> Option<&InferredSig> {
1599 let key = self.inherent_methods.get(ty_name)?.get(method)?;
1600 self.signatures.get(key)
1601 }
1602
1603 fn try_infer_method_call(
1606 &mut self,
1607 env: &mut TypeEnv,
1608 base: &Expr,
1609 field: &Ident,
1610 args: &[Expr],
1611 ) -> Result<Option<Ty>, TypeError> {
1612 if let ExprKind::Ident(id) = &base.kind
1614 && self.structs.contains_key(&id.name)
1615 && !self.enums.contains_key(&id.name)
1616 && let Some(sig) = self.method_sig(&id.name, &field.name).cloned()
1617 {
1618 let has_self = sig
1619 .params
1620 .first()
1621 .map(|(n, _)| n == "self")
1622 .unwrap_or(false);
1623 if has_self {
1624 return Err(TypeError::Unify(UnifyError::Mismatch {
1625 expected: format!("instance method `{}.{}(self, …)`", id.name, field.name),
1626 found: "associated call on type name".into(),
1627 }));
1628 }
1629 if args.len() != sig.params.len() {
1630 return Err(TypeError::Unify(UnifyError::Mismatch {
1631 expected: format!("{} arguments", sig.params.len()),
1632 found: format!("{} arguments", args.len()),
1633 }));
1634 }
1635 for (arg, (_, pty)) in args.iter().zip(sig.params.iter()) {
1636 let aty = self.infer_expr(env, arg)?;
1637 unify(&mut self.ctx, &aty, pty)?;
1638 }
1639 return Ok(Some(self.ctx.apply(&sig.ret)));
1640 }
1641
1642 let base_ty = self.infer_expr(env, base)?;
1644 let base_ty = self.ctx.apply(&base_ty);
1645 if self.is_bound_subject(&base_ty)
1646 && let Some(ret) = self.try_infer_bound_method(env, &base_ty, field, args)?
1647 {
1648 return Ok(Some(ret));
1649 }
1650
1651 let candidate_tys: Vec<String> = self
1652 .inherent_methods
1653 .iter()
1654 .filter_map(|(ty, methods)| {
1655 if methods.contains_key(&field.name) {
1656 Some(ty.clone())
1657 } else {
1658 None
1659 }
1660 })
1661 .collect();
1662 if candidate_tys.is_empty() {
1663 return Ok(None);
1664 }
1665
1666 let ty_name = match &base_ty {
1667 Ty::Named { name, .. } => name.clone(),
1668 Ty::Var(v) if candidate_tys.len() == 1 => {
1669 let name = candidate_tys[0].clone();
1670 unify(
1671 &mut self.ctx,
1672 &Ty::Var(*v),
1673 &Ty::Named {
1674 name: name.clone(),
1675 args: vec![],
1676 },
1677 )?;
1678 name
1679 }
1680 _ => return Ok(None),
1681 };
1682
1683 let Some(sig) = self.method_sig(&ty_name, &field.name).cloned() else {
1684 return Ok(None);
1685 };
1686 let has_self = sig
1687 .params
1688 .first()
1689 .map(|(n, _)| n == "self")
1690 .unwrap_or(false);
1691 if !has_self {
1692 return Ok(None);
1694 }
1695 let self_ty = Ty::Named {
1696 name: ty_name,
1697 args: vec![],
1698 };
1699 unify(&mut self.ctx, &base_ty, &self_ty)?;
1700 let param_tys: Vec<&Ty> = sig.params.iter().skip(1).map(|(_, t)| t).collect();
1701 if args.len() != param_tys.len() {
1702 return Err(TypeError::Unify(UnifyError::Mismatch {
1703 expected: format!("{} arguments", param_tys.len()),
1704 found: format!("{} arguments", args.len()),
1705 }));
1706 }
1707 for (arg, pty) in args.iter().zip(param_tys) {
1708 let aty = self.infer_expr(env, arg)?;
1709 unify(&mut self.ctx, &aty, pty)?;
1710 }
1711 Ok(Some(self.ctx.apply(&sig.ret)))
1712 }
1713
1714 fn field_type(&mut self, base: &Ty, field: &str, span: Span) -> Result<Ty, TypeError> {
1715 let base = self.ctx.apply(base);
1716 if let Ty::Named { name, args } = &base
1717 && let Some(fields) = self.instantiate_schema(name, args)
1718 {
1719 return fields.get(field).cloned().ok_or(TypeError::UnknownType {
1720 name: field.to_string(),
1721 span,
1722 });
1723 }
1724 if let Ty::Var(v) = base {
1728 let mut candidates: Vec<(&String, &Ty)> = self
1729 .structs
1730 .iter()
1731 .filter(|(name, _)| !self.shapes.contains(*name))
1732 .filter_map(|(name, fields)| fields.get(field).map(|ty| (name, ty)))
1733 .collect();
1734 candidates.sort_by(|a, b| a.0.cmp(b.0));
1735 match candidates.as_slice() {
1736 [(name, field_ty)] => {
1737 unify(
1738 &mut self.ctx,
1739 &Ty::Var(v),
1740 &Ty::Named {
1741 name: (*name).clone(),
1742 args: vec![],
1743 },
1744 )?;
1745 return Ok((*field_ty).clone());
1746 }
1747 [] => {}
1748 many => {
1749 let names = many
1750 .iter()
1751 .map(|(n, _)| n.as_str())
1752 .collect::<Vec<_>>()
1753 .join(", ");
1754 return Err(TypeError::AmbiguousField {
1755 field: field.to_string(),
1756 candidates: names,
1757 span,
1758 });
1759 }
1760 }
1761 }
1762 Err(TypeError::UnknownType {
1763 name: field.to_string(),
1764 span,
1765 })
1766 }
1767
1768 fn unify_or_shape(&mut self, actual: &Ty, expected: &Ty) -> Result<(), TypeError> {
1770 let expected = self.ctx.apply(expected);
1771 if let Ty::Named { name, args } = &expected
1772 && self.shapes.contains(name)
1773 {
1774 return self.check_shape_arg(actual, name, args);
1775 }
1776 unify(&mut self.ctx, actual, &expected)?;
1777 Ok(())
1778 }
1779
1780 fn check_shape_arg(
1781 &mut self,
1782 actual: &Ty,
1783 shape_name: &str,
1784 shape_args: &[Ty],
1785 ) -> Result<(), TypeError> {
1786 let actual = self.ctx.apply(actual);
1787 let Some(shape_fields) = self.instantiate_schema(shape_name, shape_args) else {
1788 return Err(TypeError::UnknownType {
1789 name: shape_name.to_string(),
1790 span: Span::new(0, 0),
1791 });
1792 };
1793 match &actual {
1794 Ty::Named { name, args } if name == shape_name => {
1795 if args.len() == shape_args.len() {
1796 for (a, b) in args.iter().zip(shape_args) {
1797 unify(&mut self.ctx, a, b)?;
1798 }
1799 }
1800 Ok(())
1801 }
1802 Ty::Named { name, args } => {
1803 let Some(fields) = self.instantiate_schema(name, args) else {
1804 return Err(TypeError::Unify(UnifyError::Mismatch {
1805 expected: format!("type satisfying shape `{shape_name}`"),
1806 found: name.clone(),
1807 }));
1808 };
1809 for (fname, fty) in &shape_fields {
1810 let Some(aty) = fields.get(fname) else {
1811 return Err(TypeError::Unify(UnifyError::Mismatch {
1812 expected: format!("shape `{shape_name}` (field `{fname}: {fty:?}`)"),
1813 found: name.clone(),
1814 }));
1815 };
1816 unify(&mut self.ctx, aty, fty).map_err(|err| {
1817 TypeError::Unify(UnifyError::Mismatch {
1818 expected: format!("shape `{shape_name}` (field `{fname}: {fty:?}`)"),
1819 found: format!("{name} ({err})"),
1820 })
1821 })?;
1822 }
1823 Ok(())
1824 }
1825 other => Err(TypeError::Unify(UnifyError::Mismatch {
1826 expected: format!("type satisfying shape `{shape_name}`"),
1827 found: format!("{other:?}"),
1828 })),
1829 }
1830 }
1831
1832 fn lookup(&mut self, env: &TypeEnv, name: &str, span: Span) -> Result<Ty, TypeError> {
1833 let scheme = env.get(name).ok_or_else(|| TypeError::UnknownName {
1834 name: name.to_string(),
1835 span,
1836 })?;
1837 Ok(instantiate(&mut self.ctx, scheme))
1838 }
1839
1840 fn record_arith(&mut self, ty: &Ty, op: &str) {
1841 self.record_bound(ty, op);
1842 }
1843
1844 fn record_bound(&mut self, ty: &Ty, bound: &str) {
1845 match self.ctx.apply(ty) {
1846 Ty::Named { name, args } if args.is_empty() => {
1847 self.arith_named
1848 .entry(name)
1849 .or_default()
1850 .insert(bound.into());
1851 }
1852 Ty::Var(v) => {
1853 self.arith_vars.entry(v).or_default().insert(bound.into());
1854 }
1855 _ => {}
1856 }
1857 }
1858
1859 fn take_op_bounds(&mut self, pre_ty: &Ty, gens: &[String]) -> BTreeMap<String, Vec<String>> {
1860 let mut named = std::mem::take(&mut self.arith_named);
1861 let vars = std::mem::take(&mut self.arith_vars);
1862 let mut applied_vars: BTreeMap<u32, BTreeSet<String>> = BTreeMap::new();
1863 for (v, ops) in vars {
1865 match self.ctx.apply(&Ty::Var(v)) {
1866 Ty::Named { name, args } if args.is_empty() => {
1867 named.entry(name).or_default().extend(ops);
1868 }
1869 Ty::Var(w) => {
1870 applied_vars.entry(w).or_default().extend(ops);
1871 }
1872 _ => {}
1873 }
1874 }
1875 let mut free = Vec::new();
1876 collect_free_vars(pre_ty, &mut free);
1877 free.sort_unstable();
1878 free.dedup();
1879 for (i, v) in free.iter().enumerate() {
1880 if let Some(ops) = applied_vars.get(v) {
1881 named
1882 .entry(generic_name(i))
1883 .or_default()
1884 .extend(ops.iter().cloned());
1885 }
1886 }
1887 let mut out = BTreeMap::new();
1888 for g in gens {
1889 if let Some(ops) = named.remove(g) {
1890 let mut list: Vec<String> = ops.into_iter().collect();
1891 list.sort();
1892 out.insert(g.clone(), list);
1893 }
1894 }
1895 out
1896 }
1897
1898 fn is_bound_subject(&self, ty: &Ty) -> bool {
1899 match ty {
1900 Ty::Var(_) => true,
1901 Ty::Named { name, args } if args.is_empty() => self.generic_params.contains_key(name),
1902 _ => false,
1903 }
1904 }
1905
1906 fn try_infer_bound_method(
1907 &mut self,
1908 env: &mut TypeEnv,
1909 base_ty: &Ty,
1910 field: &Ident,
1911 args: &[Expr],
1912 ) -> Result<Option<Ty>, TypeError> {
1913 let mut candidates: Vec<String> = self
1914 .traits
1915 .iter()
1916 .filter(|(name, methods)| {
1917 methods.contains_key(&field.name)
1918 && self
1919 .trait_generics
1920 .get(*name)
1921 .map(|g| g.is_empty())
1922 .unwrap_or(true)
1923 })
1924 .map(|(name, _)| name.clone())
1925 .collect();
1926 candidates.sort();
1927 match candidates.as_slice() {
1928 [] => Ok(None),
1929 [trait_name] => {
1930 let stub = self
1931 .traits
1932 .get(trait_name)
1933 .and_then(|m| m.get(&field.name))
1934 .cloned()
1935 .ok_or_else(|| TypeError::UnknownName {
1936 name: field.name.clone(),
1937 span: field.span,
1938 })?;
1939 self.record_bound(base_ty, trait_name);
1940 let param_tys: Vec<Ty> = stub
1941 .params
1942 .iter()
1943 .skip(1)
1944 .map(|(_, t)| t.clone().unwrap_or_else(|| base_ty.clone()))
1945 .collect();
1946 if args.len() != param_tys.len() {
1947 return Err(TypeError::Unify(UnifyError::Mismatch {
1948 expected: format!("{} arguments", param_tys.len()),
1949 found: format!("{} arguments", args.len()),
1950 }));
1951 }
1952 for (arg, pty) in args.iter().zip(param_tys.iter()) {
1953 let aty = self.infer_expr(env, arg)?;
1954 unify(&mut self.ctx, &aty, pty)?;
1955 }
1956 Ok(Some(stub.ret.unwrap_or_else(|| base_ty.clone())))
1957 }
1958 many => Err(TypeError::Unify(UnifyError::Mismatch {
1959 expected: format!("unique trait providing `{}`", field.name),
1960 found: many.join(", "),
1961 })),
1962 }
1963 }
1964
1965 fn free_fn_sig(&self, name: &str) -> Option<&InferredSig> {
1966 self.signatures
1967 .values()
1968 .find(|s| s.name == name && s.impl_ty.is_none())
1969 }
1970
1971 fn propagate_callee_bounds(&mut self, fname: &str, applied: &[Ty]) {
1972 let Some(sig) = self.free_fn_sig(fname) else {
1973 return;
1974 };
1975 if sig.op_bounds.is_empty() {
1976 return;
1977 }
1978 let bounds = sig.op_bounds.clone();
1979 let gens = sig.generics.clone();
1980 let params = sig.params.clone();
1981 let mut subst = BTreeMap::new();
1982 for ((_, scheme_ty), inst_ty) in params.iter().zip(applied.iter()) {
1983 collect_generic_subst(scheme_ty, inst_ty, &gens, &mut subst);
1984 }
1985 for (g, bs) in &bounds {
1986 if let Some(ty) = subst.get(g) {
1987 for b in bs {
1988 self.record_bound(ty, b);
1989 }
1990 }
1991 }
1992 }
1993
1994 fn check_instantiation_bounds(
1995 &self,
1996 insts: &BTreeMap<String, Vec<CallInst>>,
1997 ) -> Result<(), TypeError> {
1998 for (fname, uses) in insts {
1999 let Some(sig) = self.free_fn_sig(fname) else {
2000 continue;
2001 };
2002 if sig.op_bounds.is_empty() || sig.generics.is_empty() {
2003 continue;
2004 }
2005 for use_site in uses {
2006 let mut subst = BTreeMap::new();
2007 for ((_, scheme_ty), inst_ty) in sig.params.iter().zip(use_site.args.iter()) {
2008 collect_generic_subst(scheme_ty, inst_ty, &sig.generics, &mut subst);
2009 }
2010 for g in &sig.generics {
2011 let Some(bounds) = sig.op_bounds.get(g) else {
2012 continue;
2013 };
2014 let Some(ty) = subst.get(g) else {
2015 continue;
2016 };
2017 if !self.ty_is_checkable(ty) {
2018 continue;
2019 }
2020 for bound in bounds {
2021 if !self.ty_implements(ty, bound) {
2022 return Err(TypeError::UnsatisfiedBound {
2023 func: fname.clone(),
2024 ty: format_ty(ty),
2025 bound: bound.clone(),
2026 span: use_site.span,
2027 });
2028 }
2029 }
2030 }
2031 }
2032 }
2033 Ok(())
2034 }
2035
2036 fn ty_is_checkable(&self, ty: &Ty) -> bool {
2037 match ty {
2038 Ty::Int
2039 | Ty::UInt
2040 | Ty::Float
2041 | Ty::Bool
2042 | Ty::Char
2043 | Ty::Str
2044 | Ty::StrSlice
2045 | Ty::Unit
2046 | Ty::Never => true,
2047 Ty::Named { name, args } => {
2048 (self.structs.contains_key(name) || self.enums.contains_key(name))
2049 && !self.shapes.contains(name)
2050 && args.iter().all(|a| self.ty_is_checkable(a))
2051 }
2052 Ty::Option(inner) | Ty::Slice(inner) | Ty::Ref { inner, .. } => {
2053 self.ty_is_checkable(inner)
2054 }
2055 Ty::Tuple(ts) => ts.iter().all(|t| self.ty_is_checkable(t)),
2056 _ => false,
2057 }
2058 }
2059
2060 fn ty_implements(&self, ty: &Ty, bound: &str) -> bool {
2061 if is_arith_bound(bound) {
2062 return matches!(ty, Ty::Int | Ty::UInt | Ty::Float);
2063 }
2064 match ty {
2065 Ty::Named { name, args } if args.is_empty() => self
2066 .trait_impls
2067 .get(name)
2068 .is_some_and(|s| s.contains(bound)),
2069 _ => false,
2070 }
2071 }
2072
2073 fn bind_rigid_generics(&mut self, gens: &[String]) -> BTreeMap<String, Ty> {
2074 let saved = self.generic_params.clone();
2075 for g in gens {
2076 self.generic_params.insert(
2077 g.clone(),
2078 Ty::Named {
2079 name: g.clone(),
2080 args: vec![],
2081 },
2082 );
2083 }
2084 saved
2085 }
2086
2087 fn instantiate_schema(&self, name: &str, args: &[Ty]) -> Option<BTreeMap<String, Ty>> {
2088 let fields = self.structs.get(name)?.clone();
2089 let Some(gens) = self.type_params.get(name) else {
2090 return Some(fields);
2091 };
2092 if args.len() != gens.len() {
2093 return Some(fields);
2094 }
2095 let subst: BTreeMap<String, Ty> = gens.iter().cloned().zip(args.iter().cloned()).collect();
2096 Some(
2097 fields
2098 .iter()
2099 .map(|(k, v)| (k.clone(), subst_named_params(v, &subst)))
2100 .collect(),
2101 )
2102 }
2103
2104 fn impl_trait_key(module: &str, trait_name: &str, ty_name: &str) -> String {
2105 format!("{module}::{trait_name} for {ty_name}")
2106 }
2107
2108 fn impl_trait_subst(
2109 &mut self,
2110 module: &str,
2111 ib: &ImplBlock,
2112 ty_name: &str,
2113 ) -> Result<BTreeMap<String, Ty>, TypeError> {
2114 let Some(tn) = &ib.trait_name else {
2115 return Ok(BTreeMap::new());
2116 };
2117 let gens = self
2118 .trait_generics
2119 .get(&tn.name)
2120 .cloned()
2121 .unwrap_or_default();
2122 if gens.is_empty() {
2123 return Ok(BTreeMap::new());
2124 }
2125 if ib.trait_args.is_empty() {
2126 let mut subst = BTreeMap::new();
2127 let mut fresh = Vec::new();
2128 for g in &gens {
2129 let v = self.ctx.fresh();
2130 subst.insert(g.clone(), v.clone());
2131 fresh.push(v);
2132 }
2133 self.impl_trait_fresh
2134 .insert(Self::impl_trait_key(module, &tn.name, ty_name), fresh);
2135 return Ok(subst);
2136 }
2137 self.trait_arg_subst(&tn.name, &ib.trait_args)
2138 }
2139
2140 fn finalize_impl_trait_args(
2141 &mut self,
2142 module: &str,
2143 ib: &ImplBlock,
2144 ty_name: &str,
2145 ) -> Result<(), TypeError> {
2146 let Some(tn) = &ib.trait_name else {
2147 return Ok(());
2148 };
2149 let key = Self::impl_trait_key(module, &tn.name, ty_name);
2150 let Some(fresh) = self.impl_trait_fresh.remove(&key) else {
2151 return Ok(());
2152 };
2153 let mut args = Vec::new();
2154 for t in fresh {
2155 let applied = self.ctx.apply(&t);
2156 if matches!(applied, Ty::Var(_)) {
2157 return Err(TypeError::UnknownType {
2158 name: format!(
2159 "cannot infer `{}` type arguments for `{ty_name}`; write `impl {}<...> for {ty_name}`",
2160 tn.name, tn.name
2161 ),
2162 span: ib.span,
2163 });
2164 }
2165 args.push(applied);
2166 }
2167 self.impl_trait_args.insert(key, args);
2168 Ok(())
2169 }
2170
2171 fn trait_arg_subst(
2172 &mut self,
2173 trait_name: &str,
2174 args: &[Type],
2175 ) -> Result<BTreeMap<String, Ty>, TypeError> {
2176 let Some(gens) = self.trait_generics.get(trait_name).cloned() else {
2177 return Ok(BTreeMap::new());
2178 };
2179 if gens.is_empty() || args.is_empty() {
2180 return Ok(BTreeMap::new());
2181 }
2182 let mut subst = BTreeMap::new();
2183 for (g, ast_ty) in gens.iter().zip(args.iter()) {
2184 subst.insert(g.clone(), self.ast_type(ast_ty)?);
2185 }
2186 Ok(subst)
2187 }
2188
2189 fn ast_type(&mut self, ty: &Type) -> Result<Ty, TypeError> {
2190 match &ty.kind {
2191 TypeKind::Named(id) => {
2192 if let Some(bound) = self.generic_params.get(&id.name) {
2193 return Ok(bound.clone());
2194 }
2195 match id.name.as_str() {
2196 "Never" => Ok(Ty::Never),
2197 "()" => Ok(Ty::Unit),
2198 "int" => Ok(Ty::Int),
2199 "uint" => Ok(Ty::UInt),
2200 "float" => Ok(Ty::Float),
2201 "bool" => Ok(Ty::Bool),
2202 "char" => Ok(Ty::Char),
2203 "str" => Ok(Ty::Str),
2204 other => Ok(Ty::Named {
2205 name: other.to_string(),
2206 args: vec![],
2207 }),
2208 }
2209 }
2210 TypeKind::Never => Ok(Ty::Never),
2211 TypeKind::Unit => Ok(Ty::Unit),
2212 TypeKind::Option(inner) => Ok(Ty::Option(Box::new(self.ast_type(inner)?))),
2213 TypeKind::Ref { mutable, inner } => Ok(Ty::Ref {
2214 mutable: *mutable,
2215 inner: Box::new(self.ast_type(inner)?),
2216 }),
2217 TypeKind::Tuple(ts) => Ok(Ty::Tuple(
2218 ts.iter()
2219 .map(|t| self.ast_type(t))
2220 .collect::<Result<_, _>>()?,
2221 )),
2222 TypeKind::Array { elem, len } => Ok(Ty::Array {
2223 elem: Box::new(self.ast_type(elem)?),
2224 len: *len,
2225 }),
2226 TypeKind::Slice(inner) => Ok(Ty::Slice(Box::new(self.ast_type(inner)?))),
2227 TypeKind::Fn { params, ret } => Ok(Ty::Fn {
2228 params: params
2229 .iter()
2230 .map(|p| self.ast_type(p))
2231 .collect::<Result<_, _>>()?,
2232 ret: Box::new(self.ast_type(ret)?),
2233 }),
2234 TypeKind::Generic { base, args } => {
2235 let base_ty = self.ast_type(base)?;
2236 if let Ty::Named { name, .. } = base_ty {
2237 Ok(Ty::Named {
2238 name,
2239 args: args
2240 .iter()
2241 .map(|a| self.ast_type(a))
2242 .collect::<Result<_, _>>()?,
2243 })
2244 } else {
2245 Ok(base_ty)
2246 }
2247 }
2248 TypeKind::Constrained { inner, .. } => self.ast_type(inner),
2249 }
2250 }
2251}
2252
2253fn arith_trait_name(op: BinaryOp) -> Option<&'static str> {
2254 match op {
2255 BinaryOp::Add => Some("Add"),
2256 BinaryOp::Sub => Some("Sub"),
2257 BinaryOp::Mul => Some("Mul"),
2258 BinaryOp::Div => Some("Div"),
2259 _ => None,
2260 }
2261}
2262
2263fn subst_named_params(ty: &Ty, subst: &BTreeMap<String, Ty>) -> Ty {
2264 match ty {
2265 Ty::Named { name, args } if args.is_empty() => {
2266 subst.get(name).cloned().unwrap_or_else(|| ty.clone())
2267 }
2268 Ty::Named { name, args } => Ty::Named {
2269 name: name.clone(),
2270 args: args.iter().map(|a| subst_named_params(a, subst)).collect(),
2271 },
2272 Ty::Fn { params, ret } => Ty::Fn {
2273 params: params
2274 .iter()
2275 .map(|p| subst_named_params(p, subst))
2276 .collect(),
2277 ret: Box::new(subst_named_params(ret, subst)),
2278 },
2279 Ty::Option(inner) => Ty::Option(Box::new(subst_named_params(inner, subst))),
2280 Ty::Slice(inner) => Ty::Slice(Box::new(subst_named_params(inner, subst))),
2281 Ty::Array { elem, len } => Ty::Array {
2282 elem: Box::new(subst_named_params(elem, subst)),
2283 len: *len,
2284 },
2285 Ty::Ref { mutable, inner } => Ty::Ref {
2286 mutable: *mutable,
2287 inner: Box::new(subst_named_params(inner, subst)),
2288 },
2289 Ty::Tuple(ts) => Ty::Tuple(ts.iter().map(|t| subst_named_params(t, subst)).collect()),
2290 other => other.clone(),
2291 }
2292}
2293
2294fn ty_is_ground(ty: &Ty) -> bool {
2295 let mut vars = Vec::new();
2296 collect_free_vars(ty, &mut vars);
2297 vars.is_empty()
2298}
2299
2300fn collect_generic_subst(scheme: &Ty, inst: &Ty, gens: &[String], out: &mut BTreeMap<String, Ty>) {
2301 match (scheme, inst) {
2302 (Ty::Named { name, args }, inst) if args.is_empty() && gens.iter().any(|g| g == name) => {
2303 out.entry(name.clone()).or_insert_with(|| inst.clone());
2304 }
2305 (Ty::Named { name: n1, args: a1 }, Ty::Named { name: n2, args: a2 })
2306 if n1 == n2 && a1.len() == a2.len() =>
2307 {
2308 for (s, i) in a1.iter().zip(a2.iter()) {
2309 collect_generic_subst(s, i, gens, out);
2310 }
2311 }
2312 (
2313 Ty::Fn {
2314 params: p1,
2315 ret: r1,
2316 },
2317 Ty::Fn {
2318 params: p2,
2319 ret: r2,
2320 },
2321 ) if p1.len() == p2.len() => {
2322 for (s, i) in p1.iter().zip(p2.iter()) {
2323 collect_generic_subst(s, i, gens, out);
2324 }
2325 collect_generic_subst(r1, r2, gens, out);
2326 }
2327 (Ty::Option(a), Ty::Option(b)) | (Ty::Slice(a), Ty::Slice(b)) => {
2328 collect_generic_subst(a, b, gens, out);
2329 }
2330 (Ty::Array { elem: a, .. }, Ty::Array { elem: b, .. }) => {
2331 collect_generic_subst(a, b, gens, out);
2332 }
2333 (Ty::Ref { inner: a, .. }, Ty::Ref { inner: b, .. }) => {
2334 collect_generic_subst(a, b, gens, out);
2335 }
2336 (Ty::Tuple(a), Ty::Tuple(b)) if a.len() == b.len() => {
2337 for (s, i) in a.iter().zip(b.iter()) {
2338 collect_generic_subst(s, i, gens, out);
2339 }
2340 }
2341 _ => {}
2342 }
2343}
2344
2345fn generic_name(i: usize) -> String {
2346 match i {
2347 0 => "T".into(),
2348 1 => "U".into(),
2349 2 => "V".into(),
2350 3 => "W".into(),
2351 n => format!("T{n}"),
2352 }
2353}
2354
2355fn name_free_vars(ty: &Ty) -> (Ty, Vec<String>) {
2356 let mut vars = Vec::new();
2357 collect_free_vars(ty, &mut vars);
2358 vars.sort_unstable();
2359 vars.dedup();
2360 name_vars(ty, &vars)
2361}
2362
2363fn name_vars(ty: &Ty, vars: &[u32]) -> (Ty, Vec<String>) {
2364 let mut vars = vars.to_vec();
2365 vars.sort_unstable();
2366 vars.dedup();
2367 if vars.is_empty() {
2368 return (ty.clone(), Vec::new());
2369 }
2370 let names: Vec<String> = vars
2371 .iter()
2372 .enumerate()
2373 .map(|(i, _)| generic_name(i))
2374 .collect();
2375 let mut named = ty.clone();
2376 for (v, name) in vars.iter().zip(&names) {
2377 named = substitute_var(
2378 &named,
2379 *v,
2380 &Ty::Named {
2381 name: name.clone(),
2382 args: vec![],
2383 },
2384 );
2385 }
2386 (named, names)
2387}
2388
2389fn generalize_named_params(ty: &Ty, gens: &[String], ctx: &mut InferContext) -> Scheme {
2390 if gens.is_empty() {
2391 return scheme(ty.clone());
2392 }
2393 let mut subst = BTreeMap::new();
2394 let mut vars = Vec::new();
2395 for g in gens {
2396 let fresh = ctx.fresh();
2397 if let Ty::Var(v) = &fresh {
2398 vars.push(*v);
2399 }
2400 subst.insert(g.clone(), fresh);
2401 }
2402 Scheme {
2403 vars,
2404 ty: subst_named_params(ty, &subst),
2405 }
2406}
2407
2408fn stdlib_fn_types() -> Vec<(&'static str, Ty)> {
2409 vec![
2410 (
2411 "new",
2412 Ty::Fn {
2413 params: vec![],
2414 ret: Box::new(Ty::Named {
2415 name: "vec".into(),
2416 args: vec![],
2417 }),
2418 },
2419 ),
2420 (
2421 "push",
2422 Ty::Fn {
2423 params: vec![
2424 Ty::Named {
2425 name: "vec".into(),
2426 args: vec![],
2427 },
2428 Ty::Int,
2429 ],
2430 ret: Box::new(Ty::Unit),
2431 },
2432 ),
2433 (
2434 "len",
2435 Ty::Fn {
2436 params: vec![Ty::Named {
2437 name: "vec".into(),
2438 args: vec![],
2439 }],
2440 ret: Box::new(Ty::Int),
2441 },
2442 ),
2443 (
2444 "read_to_string",
2445 Ty::Fn {
2446 params: vec![Ty::StrSlice],
2447 ret: Box::new(Ty::Str),
2448 },
2449 ),
2450 (
2451 "sleep_ms",
2452 Ty::Fn {
2453 params: vec![Ty::Int],
2454 ret: Box::new(Ty::Unit),
2455 },
2456 ),
2457 (
2458 "parse_ip",
2459 Ty::Fn {
2460 params: vec![Ty::Str],
2461 ret: Box::new(Ty::Str),
2462 },
2463 ),
2464 ]
2465}
2466
2467fn rust_import_fn_type(crate_name: &str, item: &str) -> (Vec<Ty>, Ty) {
2469 let json_value = Ty::Named {
2470 name: "serde_json::Value".into(),
2471 args: vec![],
2472 };
2473 match (crate_name, item) {
2474 ("serde_json", "from_str") => (vec![Ty::Str], json_value),
2475 ("serde_json", "to_string" | "to_string_pretty" | "to_vec") => (vec![json_value], Ty::Str),
2476 ("serde_json", "from_value") => (vec![json_value.clone()], json_value),
2477 ("serde_json", "Value") => (vec![], json_value),
2479 ("ureq", "get") => (vec![Ty::Str], Ty::Str),
2480 _ => (
2481 vec![Ty::Str],
2482 Ty::Named {
2483 name: "RustValue".into(),
2484 args: vec![],
2485 },
2486 ),
2487 }
2488}
2489
2490pub fn rust_import_returns_result(crate_name: &str, item: &str) -> bool {
2493 matches!(
2494 (crate_name, item),
2495 (
2496 "serde_json",
2497 "from_str" | "to_string" | "to_string_pretty" | "to_vec" | "from_value"
2498 ) | ("ureq", "get")
2499 )
2500}