1use std::collections::BTreeSet;
77use std::sync::Arc;
78
79use beck_diag::{Diagnostic, Span};
80use beck_syntax::{sym, Node, ScopeSet, Symbol};
81
82use super::{BindKind, Binding, Checker};
83use crate::core::{Const, Core, CoreKind};
84use crate::ty::{ImplSig, MethodSig, Row, Scheme, TraitSig, Ty, TyDecl};
85
86pub(crate) fn mangle(trait_name: &str, method: &str, target: &str) -> Arc<str> {
92 Arc::from(format!("{trait_name}::{method}@{target}"))
93}
94
95pub fn is_impl_method(name: &str) -> bool {
97 name.contains("::") && name.contains('@')
98}
99
100#[derive(Clone, Debug)]
106pub(super) struct TraitDecl {
107 pub methods: Vec<TraitMethod>,
108 pub sig: TraitSig,
112 pub span: Span,
113}
114
115#[derive(Clone, Debug)]
116pub(super) struct TraitMethod {
117 pub name: Arc<str>,
118 pub params: Node,
119 pub returns: Node,
120 pub uses: Node,
121 pub span: Span,
122}
123
124#[derive(Clone, Debug)]
126pub(super) struct ImplDecl {
127 pub target: Arc<str>,
130 pub sig: ImplSig,
132 pub span: Span,
133}
134
135const SELF: &str = "Self";
137
138const FN_TYPE: &str = "fn-type";
140
141#[derive(Clone, Debug)]
143pub(super) struct DictParam {
144 pub param: Arc<str>,
146 pub trait_name: Arc<str>,
147 pub method: Arc<str>,
148}
149
150pub(super) fn typaram_name(p: &Node) -> Option<Arc<str>> {
152 if p.is_form(sym::ANNOT) {
153 return p
154 .args
155 .first()
156 .and_then(|n| n.as_var())
157 .map(|s| s.name.clone());
158 }
159 p.as_var().map(|s| s.name.clone())
160}
161
162pub(super) fn bounds_of(typarams: &Node) -> Vec<(Arc<str>, Vec<Arc<str>>)> {
164 if !typarams.is_form(sym::TYPARAMS) {
165 return Vec::new();
166 }
167 typarams
168 .args
169 .iter()
170 .filter(|p| p.is_form(sym::ANNOT) && p.args.len() >= 2)
171 .filter_map(|p| {
172 let name = typaram_name(p)?;
173 let traits: Vec<Arc<str>> = p.args[1..]
174 .iter()
175 .filter_map(|b| b.as_var().map(|s| s.name.clone()))
176 .collect();
177 Some((name, traits))
178 })
179 .collect()
180}
181
182impl Checker<'_> {
183 pub(super) fn collect_traits(&mut self, items: &[&Node]) {
186 for item in items {
187 let (item, _) = self.undecorate(item);
188 if !item.is_form(sym::TRAIT) || item.args.is_empty() {
189 continue;
190 }
191 let Some(name) = item.args[0].as_var().map(|s| s.name.clone()) else {
192 continue;
193 };
194 if self.types.contains_key(&name) {
195 self.error(
196 "B0380",
197 format!("`{name}` is already a type, so it cannot also be a trait"),
198 item.span(),
199 );
200 continue;
201 }
202 let mut methods: Vec<TraitMethod> = Vec::new();
203 for m in &item.args[1..] {
204 let Some(method) = self.trait_method(m, &name) else {
205 continue;
206 };
207 if methods.iter().any(|x| x.name == method.name) {
208 self.error(
209 "B0381",
210 format!("`{name}` declares `{}` twice", method.name),
211 method.span,
212 );
213 continue;
214 }
215 methods.push(method);
216 }
217 if methods.is_empty() {
218 self.diags.push(
219 Diagnostic::error(
220 "B0381",
221 format!("`{name}` declares no methods"),
222 item.span(),
223 )
224 .with_note(
225 "a trait with nothing in it can be implemented and never used, which is a \
226 marker rather than an abstraction; Beck has no marker traits because \
227 placement and effects are already properties of the signature",
228 ),
229 );
230 continue;
231 }
232 let sig = self.trait_sig(&name, &methods);
233 let decl = TraitDecl {
234 methods,
235 sig,
236 span: item.span(),
237 };
238 for m in &decl.methods {
239 if let Some(other) = self.trait_methods.get(&m.name) {
243 self.error(
244 "B0381",
245 format!("`{}` is already a method of trait `{other}`", m.name),
246 m.span,
247 );
248 continue;
249 }
250 if self.schemes.contains_key(&m.name) || self.prims.contains_key(&m.name) {
251 self.error(
252 "B0381",
253 format!(
254 "`{}` is already a definition, so `{name}` cannot declare it",
255 m.name
256 ),
257 m.span,
258 );
259 continue;
260 }
261 self.trait_methods.insert(m.name.clone(), name.clone());
262 self.globals.push(Binding {
263 name: m.name.clone(),
264 scopes: ScopeSet::empty(),
265 kind: BindKind::TraitMethod(m.name.clone()),
266 });
267 }
268 self.own_traits.push(name.clone());
269 if self.traits.insert(name.clone(), decl).is_some() {
270 self.error(
271 "B0380",
272 format!("trait `{name}` is declared twice"),
273 item.span(),
274 );
275 }
276 }
277 }
278
279 fn trait_sig(&mut self, name: &Arc<str>, methods: &[TraitMethod]) -> TraitSig {
285 let placeholder = TyDecl::Newtype {
286 name: Arc::from(SELF),
287 params: Vec::new(),
288 inner: Ty::unit(),
289 };
290 self.types.insert(Arc::from(SELF), placeholder);
291 let out = TraitSig {
292 name: name.clone(),
293 methods: methods
294 .iter()
295 .map(|m| MethodSig {
296 name: m.name.clone(),
297 params: m
298 .params
299 .args
300 .iter()
301 .map(|p| {
302 (
303 p.args[0]
304 .as_var()
305 .map(|s| s.name.clone())
306 .unwrap_or_else(|| Arc::from("?")),
307 self.ty_from_node(&p.args[1]),
308 )
309 })
310 .collect(),
311 ret: self.ty_from_node(&m.returns.args[0]),
312 effects: self.declared_row(Some(&m.uses)).atoms.into_iter().collect(),
313 })
314 .collect(),
315 };
316 self.types.remove(SELF);
317 out
318 }
319
320 fn trait_method(&mut self, m: &Node, trait_name: &str) -> Option<TraitMethod> {
322 let (m, _) = self.undecorate(m);
323 if !m.is_form(sym::DEF) || m.args.len() < 5 {
324 self.error(
325 "B0381",
326 format!("`{trait_name}` may only contain `def` signatures"),
327 m.span(),
328 );
329 return None;
330 }
331 let name = m.args[0].as_var()?.name.clone();
332 if !m.args[1].args.is_empty() {
333 self.error(
334 "B0381",
335 format!("`{name}` may not take type parameters of its own"),
336 m.args[1].span(),
337 );
338 return None;
339 }
340 if m.args.len() > 5 {
343 self.diags.push(
344 Diagnostic::error(
345 "B0381",
346 format!("`{name}` has a body, and a trait declares signatures"),
347 m.span(),
348 )
349 .with_note(
350 "a default method would have to be checked against an abstract `Self` rather \
351 than against each implementing type, which is not built",
352 ),
353 );
354 return None;
355 }
356 let params = self.trait_params(&m.args[2], &name)?;
357 if m.args[3].args.is_empty() {
358 self.error(
359 "B0381",
360 format!("`{name}` needs a return type"),
361 m.args[0].span(),
362 );
363 return None;
364 }
365 Some(TraitMethod {
366 name,
367 params,
368 returns: m.args[3].clone(),
369 uses: m.args[4].clone(),
370 span: m.span(),
371 })
372 }
373
374 fn trait_params(&mut self, params: &Node, method: &str) -> Option<Node> {
379 let mut out = Vec::new();
380 let mut mentions_self = false;
381 for p in ¶ms.args {
382 let (name, ty) = if p.is_form(sym::ANNOT) && p.args.len() == 2 {
383 (p.args[0].clone(), p.args[1].clone())
384 } else if p.as_var().map(|s| s.name.as_ref() == "self") == Some(true) {
385 (p.clone(), Node::sym(SELF, p.span()))
388 } else {
389 self.error(
390 "B0381",
391 format!("`{method}`'s parameters need types, and only `self` is implicit"),
392 p.span(),
393 );
394 return None;
395 };
396 if mentions(&ty, SELF) {
397 mentions_self = true;
398 }
399 let span = name.span().to(ty.span());
400 out.push(Node::form(sym::ANNOT, vec![name, ty], span));
401 }
402 if !mentions_self {
403 self.diags.push(
404 Diagnostic::error(
405 "B0381",
406 format!("`{method}` never mentions `Self`, so nothing dispatches on it"),
407 params.span(),
408 )
409 .with_note(
410 "a trait method is resolved from the type of an argument; one that mentions \
411 `Self` only in its return type would need the call site to say which impl it \
412 meant, and there is no notation for that",
413 ),
414 );
415 return None;
416 }
417 Some(Node::form(sym::PARAMS, out, params.span()))
418 }
419
420 pub(super) fn expand_impls(&mut self, items: &[&Node]) -> Vec<Node> {
425 let mut out = Vec::new();
426 for item in items {
427 let (item, _) = self.undecorate(item);
428 if !item.is_form(sym::IMPL) || item.args.len() < 3 {
429 continue;
430 }
431 self.expand_impl(item, &mut out);
432 }
433 out
434 }
435
436 fn expand_impl(&mut self, item: &Node, out: &mut Vec<Node>) {
437 let span = item.span();
438 let Some(trait_name) = item.args[0].as_var().map(|s| s.name.clone()) else {
439 return;
440 };
441 let Some(decl) = self.traits.get(&trait_name).cloned() else {
442 self.error("B0383", format!("cannot find trait `{trait_name}`"), span);
443 return;
444 };
445 let target_node = &item.args[2];
446 let Some(target) = target_node.head_name().map(Arc::<str>::from) else {
447 self.error("B0383", "expected a type to implement the trait for", span);
448 return;
449 };
450
451 let typarams = item.args[1].clone();
455 let param_names = Self::typaram_names(item);
456
457 if !self.types.contains_key(&target)
458 && crate::prelude::builtin_arity(&target).is_none()
459 && !param_names.contains(&target)
460 {
461 self.error(
462 "B0383",
463 format!("cannot find type `{target}`"),
464 target_node.span(),
465 );
466 return;
467 }
468 if param_names.contains(&target) {
469 self.diags.push(
470 Diagnostic::error(
471 "B0384",
472 format!("`{target}` is a type parameter, so this impl covers every type"),
473 target_node.span(),
474 )
475 .with_note(
476 "a blanket impl makes coherence a search rather than a lookup, and Beck's \
477 orphan rule is written for one impl per trait per type constructor",
478 ),
479 );
480 return;
481 }
482 let key = (trait_name.clone(), target.clone());
486 if let Some(prev) = self.impls.get(&key) {
487 self.diags.push(
488 Diagnostic::error(
489 "B0384",
490 format!("`{trait_name}` is already implemented for `{target}`"),
491 span,
492 )
493 .with_label(prev.span, "the first implementation")
494 .with_note(
495 "coherence: one impl per trait per type, so that what a call means never \
496 depends on which impls happen to be in scope",
497 ),
498 );
499 return;
500 }
501 let owns_trait = self.own_traits.contains(&trait_name);
507 let owns_type = self.own_types.contains(&target);
508 if !owns_trait && !owns_type {
509 self.diags.push(
510 Diagnostic::error(
511 "B0385",
512 format!("neither `{trait_name}` nor `{target}` is declared in this module"),
513 span,
514 )
515 .with_note(
516 "the orphan rule: an impl belongs with the trait or with the type, so that two \
517 modules cannot both supply one and disagree",
518 ),
519 );
520 return;
521 }
522
523 let sig = {
526 let before = std::mem::take(&mut self.typarams);
527 self.typarams = param_names.iter().cloned().collect();
528 let target_ty = self.ty_from_node(target_node);
529 self.typarams = before;
530 ImplSig {
531 trait_name: trait_name.clone(),
532 params: param_names.clone(),
533 target: target_ty,
534 effects: Vec::new(),
537 }
538 };
539
540 if self.mode == super::Mode::Interface {
545 let mut sig = sig;
546 for m in &item.args[3..] {
547 let (m, _) = self.undecorate(m);
548 if !m.is_form(sym::DEF) || m.args.len() > 5 {
551 self.diags.push(
552 Diagnostic::error(
553 "B0382",
554 "an impl in a `.becki` publishes its methods' effects, not their bodies",
555 m.span(),
556 )
557 .with_note(
558 "the implementation stays in the module that wrote it; what crosses is \
559 that it exists and what it performs, which is what a call in another \
560 module needs to resolve",
561 ),
562 );
563 continue;
564 }
565 let Some(name) = m.args[0].as_var().map(|s| s.name.clone()) else {
566 continue;
567 };
568 let row = self.declared_row(m.args.get(4));
569 if !row.atoms.is_empty() {
570 sig.effects.push((name, row.atoms.into_iter().collect()));
571 }
572 }
573 self.register_impl(key, target.clone(), sig, span);
574 return;
575 }
576 if item.args.len() == 3 {
577 self.diags.push(
578 Diagnostic::error("B0382", "this impl has no methods", span).with_note(
579 "a header with nothing behind it is a declaration, which is what a `.becki` \
580 interface is made of; an ordinary module has to implement what it claims",
581 ),
582 );
583 return;
584 }
585
586 let mut seen: BTreeSet<Arc<str>> = BTreeSet::new();
587 for m in &item.args[3..] {
588 let (m, _) = self.undecorate(m);
589 if !m.is_form(sym::DEF) || m.args.len() < 6 {
590 self.error(
591 "B0382",
592 "an impl may only contain `def`s with bodies",
593 m.span(),
594 );
595 continue;
596 }
597 let Some(name) = m.args[0].as_var().map(|s| s.name.clone()) else {
598 continue;
599 };
600 let Some(sig) = decl.methods.iter().find(|x| x.name == name) else {
601 self.diags.push(
602 Diagnostic::error(
603 "B0382",
604 format!("`{trait_name}` has no method `{name}`"),
605 m.args[0].span(),
606 )
607 .with_label(decl.span, "the trait is declared here"),
608 );
609 continue;
610 };
611 if !seen.insert(name.clone()) {
612 self.error(
613 "B0382",
614 format!("`{name}` is implemented twice for `{target}`"),
615 m.span(),
616 );
617 continue;
618 }
619 if let Some(def) =
620 self.impl_method(m, sig, &trait_name, &target, target_node, &typarams)
621 {
622 if let Some(s) = def.args[0].as_var() {
623 self.impl_methods.insert(s.name.clone());
624 }
625 let def = self.expand_bounds(&def).unwrap_or(def);
631 out.push(def);
632 }
633 }
634
635 let missing: Vec<String> = decl
636 .methods
637 .iter()
638 .filter(|m| !seen.contains(&m.name))
639 .map(|m| m.name.to_string())
640 .collect();
641 if !missing.is_empty() {
642 self.diags.push(
643 Diagnostic::error(
644 "B0382",
645 format!("`{target}` does not implement all of `{trait_name}`"),
646 span,
647 )
648 .with_primary_label(format!("missing: {}", missing.join(", ")))
649 .with_label(decl.span, "declared here"),
650 );
651 }
652 self.register_impl(key, target, sig, span);
653 }
654
655 fn register_impl(
656 &mut self,
657 key: (Arc<str>, Arc<str>),
658 target: Arc<str>,
659 sig: ImplSig,
660 span: Span,
661 ) {
662 self.own_impls.push(key.clone());
663 self.impls.insert(key, ImplDecl { target, sig, span });
664 }
665
666 fn impl_method(
668 &mut self,
669 m: &Node,
670 sig: &TraitMethod,
671 trait_name: &str,
672 target: &str,
673 target_node: &Node,
674 typarams: &Node,
675 ) -> Option<Node> {
676 if !m.args[1].args.is_empty() {
677 self.error(
678 "B0382",
679 format!("`{}` takes its type parameters from the impl", sig.name),
680 m.args[1].span(),
681 );
682 return None;
683 }
684 if !m.args[3].args.is_empty() || !m.args[4].args.is_empty() {
685 self.diags.push(
686 Diagnostic::error(
687 "B0382",
688 format!(
689 "`{}` may not restate its return type or its effects",
690 sig.name
691 ),
692 m.args[0].span(),
693 )
694 .with_label(sig.span, "the trait already said both")
695 .with_note(
696 "an impl writes the body; the signature is the trait's, and a second copy of \
697 it is a second place for it to be wrong",
698 ),
699 );
700 return None;
701 }
702 let written = &m.args[2].args;
703 if written.len() != sig.params.args.len() {
704 self.error(
705 "B0382",
706 format!(
707 "`{}` takes {} parameter(s), got {}",
708 sig.name,
709 sig.params.args.len(),
710 written.len()
711 ),
712 m.args[2].span(),
713 );
714 return None;
715 }
716 let mut params = Vec::new();
718 for (w, s) in written.iter().zip(&sig.params.args) {
719 if w.is_form(sym::ANNOT) {
720 self.diags.push(
721 Diagnostic::error(
722 "B0382",
723 format!("`{}`'s parameter types come from the trait", sig.name),
724 w.span(),
725 )
726 .with_label(sig.span, "declared here"),
727 );
728 return None;
729 }
730 let Some(name) = w.as_var() else {
731 self.error("B0382", "expected a parameter name", w.span());
732 return None;
733 };
734 let ty = substitute_self(&s.args[1], target_node);
735 let span = w.span().to(ty.span());
736 params.push(Node::form(
737 sym::ANNOT,
738 vec![Node::sym(&name.name, w.span()), ty],
739 span,
740 ));
741 }
742 let name = mangle(trait_name, &sig.name, target);
743 Some(Node::form(
744 sym::DEF,
745 vec![
746 Node::sym(&name, m.args[0].span()),
747 typarams.clone(),
748 Node::form(sym::PARAMS, params, m.args[2].span()),
749 substitute_self(&sig.returns, target_node),
750 sig.uses.clone(),
751 m.args[5].clone(),
752 ],
753 m.span(),
754 ))
755 }
756
757 pub(super) fn expand_bounds(&mut self, item: &Node) -> Option<Node> {
765 if item.is_form(sym::DECORATE) && item.args.len() == 2 {
766 let inner = self.expand_bounds(&item.args[1])?;
767 let mut out = item.clone();
768 out.args[1] = inner;
769 return Some(out);
770 }
771 if !item.is_form(sym::DEF) || item.args.len() < 5 {
772 return None;
773 }
774 let bounds = bounds_of(&item.args[1]);
775 if bounds.is_empty() {
776 return None;
777 }
778 let name = item.args[0].as_var().map(|s| s.name.clone())?;
779 let mut extra = Vec::new();
780 let mut specs = Vec::new();
781 for (param, traits) in &bounds {
782 let param_node = Node::sym(param, item.args[1].span());
783 for t in traits {
784 let Some(decl) = self.traits.get(t).cloned() else {
785 self.error(
786 "B0383",
787 format!("cannot find trait `{t}`"),
788 item.args[1].span(),
789 );
790 continue;
791 };
792 for m in &decl.methods {
793 let dict = mangle(t, &m.name, param);
794 let span = item.args[1].span();
795 let mut fn_ty: Vec<Node> = m
799 .params
800 .args
801 .iter()
802 .map(|p| substitute_self(&p.args[1], ¶m_node))
803 .collect();
804 fn_ty.push(substitute_self(&m.returns.args[0], ¶m_node));
805 extra.push(Node::form(
806 sym::ANNOT,
807 vec![Node::sym(&dict, span), Node::form(FN_TYPE, fn_ty, span)],
808 span,
809 ));
810 specs.push(DictParam {
811 param: param.clone(),
812 trait_name: t.clone(),
813 method: m.name.clone(),
814 });
815 }
816 }
817 }
818 if specs.is_empty() {
819 return None;
820 }
821 self.dicts.insert(name, specs);
822 let mut out = item.clone();
823 out.args[1] = Node::form(
826 sym::TYPARAMS,
827 bounds_of(&item.args[1])
828 .iter()
829 .map(|(p, _)| Node::sym(p, item.args[1].span()))
830 .chain(
831 item.args[1]
832 .args
833 .iter()
834 .filter(|p| !p.is_form(sym::ANNOT))
835 .cloned(),
836 )
837 .collect(),
838 item.args[1].span(),
839 );
840 out.args[2].args.extend(extra);
841 Some(out)
842 }
843
844 pub(super) fn bounds_of_def(&self, name: &Arc<str>) -> Vec<(Arc<str>, Vec<Arc<str>>)> {
850 let Some(specs) = self.dicts.get(name) else {
851 return Vec::new();
852 };
853 let mut out: Vec<(Arc<str>, Vec<Arc<str>>)> = Vec::new();
854 for s in specs {
855 match out.iter_mut().find(|(p, _)| *p == s.param) {
856 Some((_, traits)) => {
857 if !traits.contains(&s.trait_name) {
858 traits.push(s.trait_name.clone());
859 }
860 }
861 None => out.push((s.param.clone(), vec![s.trait_name.clone()])),
862 }
863 }
864 out
865 }
866
867 pub(super) fn apply_bounded(
875 &mut self,
876 name: &Arc<str>,
877 specs: &[DictParam],
878 args: &[Node],
879 expected: Option<&Ty>,
880 span: Span,
881 ) -> Core {
882 let Some(scheme) = self.schemes.get(name).cloned() else {
883 return Core::new(CoreKind::Const(Const::Unit), self.subst.fresh(), span);
884 };
885 let (ty, named) = self.subst.instantiate_named(&scheme);
886 let func = Core::new(CoreKind::Global(name.clone()), ty.clone(), span);
887 let Ty::Fun(param_tys, ret, latent) = ty else {
888 return self.apply_fn(func, args, span);
889 };
890 self.perform(&latent);
891 let ordinary = param_tys.len().saturating_sub(specs.len());
892 if args.len() != ordinary {
893 self.error(
894 "B0351",
895 format!("expected {ordinary} argument(s), got {}", args.len()),
896 span,
897 );
898 }
899 let mut checked = self.check_args(args, ¶m_tys[..ordinary]);
900 if let Some(want) = expected {
901 let _ = self.subst.unify(&ret, want);
904 }
905 for (i, spec) in specs.iter().enumerate() {
906 let at = named
907 .get(&spec.param)
908 .map(|t| self.subst.resolve(t))
909 .unwrap_or_else(|| self.subst.fresh());
910 let Some(dict) = self.dictionary_at(&spec.trait_name, &spec.method, &at, span, 0)
911 else {
912 continue;
913 };
914 if let Some(want) = param_tys.get(ordinary + i) {
915 self.unify(&dict.ty, want, span, "implementation");
916 }
917 checked.push(dict);
918 }
919 Core::new(
920 CoreKind::App {
921 func: Box::new(func),
922 args: checked,
923 },
924 *ret,
925 span,
926 )
927 }
928
929 pub(super) fn dictionary(
936 &mut self,
937 trait_name: &Arc<str>,
938 method: &Arc<str>,
939 ty: &Ty,
940 span: Span,
941 ) -> Option<Core> {
942 let head = ty.con_name().map(Arc::<str>::from);
943 if let Some(head) = &head {
944 if self.typarams.contains(head) {
945 let want = mangle(trait_name, method, head);
946 if let Some(BindKind::Local(id, t)) =
947 self.resolve(&Symbol::new(&want)).map(|b| b.kind.clone())
948 {
949 return Some(Core::new(CoreKind::Var(id), t, span));
950 }
951 self.diags.push(
952 Diagnostic::error(
953 "B0386",
954 format!("`{head}` is not known to implement `{trait_name}`"),
955 span,
956 )
957 .with_primary_label(format!("`{method}` needs it"))
958 .with_fix(format!("bound it: `[{head}: {trait_name}]`")),
959 );
960 return None;
961 }
962 }
963 let Some(head) = head else {
964 self.diags.push(
965 Diagnostic::error(
966 "B0386",
967 format!("cannot tell which type `{method}` dispatches on here"),
968 span,
969 )
970 .with_primary_label("the type is not determined at this call")
971 .with_fix("annotate it, or pass an argument that fixes it")
972 .with_note(
973 "an implementation is chosen from a concrete type or from a bound on a type \
974 parameter; this is neither yet, and the choice is made where the call is \
975 written rather than after the whole body has been read",
976 ),
977 );
978 return None;
979 };
980 let Some(found) = self.impls.get(&(trait_name.clone(), head.clone())) else {
981 let decl = self.traits.get(trait_name).map(|d| d.span);
982 let mut d = Diagnostic::error(
983 "B0387",
984 format!("`{head}` does not implement `{trait_name}`"),
985 span,
986 )
987 .with_primary_label(format!(
988 "`{method}` needs an `impl {trait_name} for {head}`"
989 ));
990 if let Some(at) = decl {
991 d = d.with_label(at, "the trait is declared here");
992 }
993 self.diags.push(d);
994 return None;
995 };
996 let name = mangle(trait_name, method, &found.target);
997 let ty = self
998 .schemes
999 .get(&name)
1000 .map(|sc| self.subst.instantiate(sc))?;
1001 Some(Core::new(CoreKind::Global(name), ty, span))
1002 }
1003
1004 pub(super) fn import_trait_decls(&mut self, traits: &[TraitSig]) {
1018 for t in traits {
1019 let methods: Vec<TraitMethod> = t
1020 .methods
1021 .iter()
1022 .map(|m| TraitMethod {
1023 name: m.name.clone(),
1024 params: Node::form(
1025 sym::PARAMS,
1026 m.params
1027 .iter()
1028 .map(|(n, ty)| {
1029 Node::form(
1030 sym::ANNOT,
1031 vec![Node::sym(n, Span::NONE), ty_to_node(ty)],
1032 Span::NONE,
1033 )
1034 })
1035 .collect(),
1036 Span::NONE,
1037 ),
1038 returns: Node::form(sym::RETURNS, vec![ty_to_node(&m.ret)], Span::NONE),
1039 uses: Node::form(
1040 "uses",
1041 m.effects
1042 .iter()
1043 .map(|e| Node::sym(e.name(), Span::NONE))
1044 .collect(),
1045 Span::NONE,
1046 ),
1047 span: Span::NONE,
1048 })
1049 .collect();
1050 for m in &methods {
1051 self.trait_methods.insert(m.name.clone(), t.name.clone());
1052 self.globals.push(Binding {
1053 name: m.name.clone(),
1054 scopes: ScopeSet::empty(),
1055 kind: BindKind::TraitMethod(m.name.clone()),
1056 });
1057 }
1058 self.traits.insert(
1059 t.name.clone(),
1060 TraitDecl {
1061 methods,
1062 sig: t.clone(),
1063 span: Span::NONE,
1064 },
1065 );
1066 }
1067 }
1068
1069 pub(super) fn import_impls(&mut self, module: &str, impls: &[ImplSig]) {
1083 for i in impls {
1084 let head = i.head();
1085 let Some(decl) = self.traits.get(&i.trait_name).cloned() else {
1086 self.diags.push(
1087 Diagnostic::warning(
1088 "B0388",
1089 format!(
1090 "`{module}` implements `{}`, which this program does not import",
1091 i.trait_name
1092 ),
1093 Span::NONE,
1094 )
1095 .with_note(format!(
1098 "`impl {} for {}` is dropped, so its methods cannot be called here",
1099 i.trait_name,
1100 i.head()
1101 ))
1102 .with_note(
1103 "a trait is a name, and a name is visible where its module is imported \
1104 directly rather than through somebody else's import",
1105 )
1106 .with_fix(format!(
1107 "import the module that declares `{}`",
1108 i.trait_name
1109 )),
1110 );
1111 continue;
1112 };
1113 for m in &decl.sig.methods {
1114 let name = mangle(&i.trait_name, &m.name, &head);
1120 let row = i
1121 .effects
1122 .iter()
1123 .find(|(n, _)| *n == m.name)
1124 .map(|(_, r)| Row::of(r.iter().cloned()))
1125 .unwrap_or_else(|| Row::of(m.effects.iter().cloned()));
1126 let params: Vec<Ty> = m
1127 .params
1128 .iter()
1129 .map(|(_, t)| substitute_self_ty(t, &i.target))
1130 .collect();
1131 let ret = substitute_self_ty(&m.ret, &i.target);
1132 let ty = Ty::fun_eff(params, ret, row);
1133 self.schemes
1134 .insert(name.clone(), Scheme::generic(i.params.clone(), ty));
1135 }
1136 self.impls.insert(
1137 (i.trait_name.clone(), head.clone()),
1138 ImplDecl {
1139 target: head,
1140 sig: i.clone(),
1141 span: Span::NONE,
1142 },
1143 );
1144 }
1145 }
1146
1147 pub(super) fn import_bounded(
1154 &mut self,
1155 name: &Arc<str>,
1156 bounds: &[(Arc<str>, Vec<Arc<str>>)],
1157 scheme: Scheme,
1158 ) -> Scheme {
1159 let Ty::Fun(mut params, ret, row) = scheme.ty.clone() else {
1160 return scheme;
1161 };
1162 let mut specs = Vec::new();
1163 for (param, traits) in bounds {
1164 let at = Ty::con(param);
1165 for t in traits {
1166 let Some(decl) = self.traits.get(t).cloned() else {
1167 continue;
1168 };
1169 for m in &decl.sig.methods {
1170 let row = self.subst.fresh_row();
1175 params.push(Ty::fun_eff(
1176 m.params
1177 .iter()
1178 .map(|(_, ty)| substitute_self_ty(ty, &at))
1179 .collect(),
1180 substitute_self_ty(&m.ret, &at),
1181 row,
1182 ));
1183 specs.push(DictParam {
1184 param: param.clone(),
1185 trait_name: t.clone(),
1186 method: m.name.clone(),
1187 });
1188 }
1189 }
1190 }
1191 if specs.is_empty() {
1192 return scheme;
1193 }
1194 self.dicts.insert(name.clone(), specs);
1195 Scheme::generic(scheme.params.clone(), Ty::Fun(params, ret, row))
1196 }
1197
1198 pub(super) fn trait_call(&mut self, method: &Arc<str>, args: &[Node], span: Span) -> Core {
1200 let unit = || Core::new(CoreKind::Const(Const::Unit), Ty::unit(), span);
1201 let Some(trait_name) = self.trait_methods.get(method).cloned() else {
1202 return unit();
1203 };
1204 let Some(decl) = self.traits.get(&trait_name).cloned() else {
1205 return unit();
1206 };
1207 let Some(sig) = decl.methods.iter().find(|m| &m.name == method) else {
1208 return unit();
1209 };
1210 let at = sig
1213 .params
1214 .args
1215 .iter()
1216 .position(|p| mentions(&p.args[1], SELF))
1217 .unwrap_or(0);
1218 if args.len() <= at {
1219 self.error(
1220 "B0351",
1221 format!(
1222 "`{method}` takes {} argument(s), got {}",
1223 sig.params.args.len(),
1224 args.len()
1225 ),
1226 span,
1227 );
1228 return unit();
1229 }
1230 let receiver = self.expr(&args[at], None);
1231 let ty = self.subst.resolve(&receiver.ty);
1232 if let Some(call) = self.apply_bounded_impl(&trait_name, method, &receiver, at, args, span)
1236 {
1237 return call;
1238 }
1239 let Some(func) = self.dictionary(&trait_name, method, &ty, args[at].span()) else {
1242 return unit();
1243 };
1244 self.apply_fn_with(func, receiver, at, args, span)
1245 }
1246}
1247
1248fn ty_to_node(t: &Ty) -> Node {
1255 let span = Span::NONE;
1256 match t {
1257 Ty::Con(n, args) if args.is_empty() => Node::sym(n, span),
1258 Ty::Con(n, args) => Node::form_sym(
1259 beck_syntax::Symbol::new(n),
1260 args.iter().map(ty_to_node).collect(),
1261 span,
1262 ),
1263 Ty::Fun(ps, r, _) => {
1264 let mut parts: Vec<Node> = ps.iter().map(ty_to_node).collect();
1265 parts.push(ty_to_node(r));
1266 Node::form(FN_TYPE, parts, span)
1267 }
1268 Ty::Var(_) => Node::sym(Ty::UNIT, span),
1272 }
1273}
1274
1275fn mentions(n: &Node, name: &str) -> bool {
1277 n.head_name() == Some(name) || n.args.iter().any(|a| mentions(a, name))
1278}
1279
1280fn substitute_self_ty(t: &Ty, target: &Ty) -> Ty {
1282 match t {
1283 Ty::Con(n, args) if n.as_ref() == SELF && args.is_empty() => target.clone(),
1284 Ty::Con(n, args) => Ty::Con(
1285 n.clone(),
1286 args.iter().map(|a| substitute_self_ty(a, target)).collect(),
1287 ),
1288 Ty::Fun(ps, r, row) => Ty::Fun(
1289 ps.iter().map(|p| substitute_self_ty(p, target)).collect(),
1290 Box::new(substitute_self_ty(r, target)),
1291 row.clone(),
1292 ),
1293 Ty::Var(_) => t.clone(),
1294 }
1295}
1296
1297fn substitute_self(n: &Node, target: &Node) -> Node {
1299 if n.head_name() == Some(SELF) && n.args.is_empty() {
1300 let mut t = target.clone();
1301 t.meta = n.meta.clone();
1302 return t;
1303 }
1304 let mut out = n.clone();
1305 out.args = n.args.iter().map(|a| substitute_self(a, target)).collect();
1306 out
1307}
1308
1309#[cfg(test)]
1310mod tests {
1311 use std::sync::Arc;
1312
1313 use crate::check_str;
1314
1315 fn codes(src: &str) -> Vec<&'static str> {
1316 let (_, d, _) = check_str("t.beck", src);
1317 d.iter().map(|x| x.code).collect()
1318 }
1319
1320 fn errors(src: &str) -> String {
1321 let (_, d, map) = check_str("t.beck", src);
1322 d.render(&map)
1323 }
1324
1325 const SHOW: &str = "\
1326trait Show:
1327 def show(self) -> Str
1328
1329model Point:
1330 x: Int
1331
1332impl Show for Point:
1333 def show(self):
1334 return str(self.x)
1335";
1336
1337 #[test]
1338 fn a_trait_and_an_impl_check() {
1339 assert_eq!(codes(SHOW), Vec::<&str>::new());
1340 }
1341
1342 #[test]
1343 fn a_call_resolves_to_the_impl_for_the_receivers_type() {
1344 let src = format!(
1345 "{SHOW}
1346def label(p: Point) -> Str:
1347 return p.show()
1348
1349def same(p: Point) -> Str:
1350 return show(p)
1351"
1352 );
1353 assert_eq!(codes(&src), Vec::<&str>::new());
1354
1355 let (program, _, _) = check_str("t.beck", &src);
1358 assert!(
1359 program.defs.contains_key("Show::show@Point"),
1360 "{:?}",
1361 program.defs.keys().collect::<Vec<_>>()
1362 );
1363 assert!(super::is_impl_method("Show::show@Point"));
1364 assert!(!super::is_impl_method("label"));
1365 }
1366
1367 #[test]
1368 fn one_impl_covers_every_argument_of_a_parameterised_type() {
1369 let src = "\
1372trait Show:
1373 def show(self) -> Str
1374
1375union Tree[T]:
1376 Leaf(value: T)
1377
1378impl[T] Show for Tree[T]:
1379 def show(self):
1380 return \"leaf\"
1381
1382def a() -> Str:
1383 return Leaf(value=1).show()
1384
1385def b() -> Str:
1386 return Leaf(value=\"x\").show()
1387";
1388 assert_eq!(codes(src), Vec::<&str>::new());
1389 }
1390
1391 #[test]
1392 fn a_type_with_no_impl_is_refused_by_name() {
1393 let src = format!(
1394 "{SHOW}
1395model Other:
1396 y: Int
1397
1398def f(o: Other) -> Str:
1399 return o.show()
1400"
1401 );
1402 let text = errors(&src);
1403 assert!(text.contains("B0387"), "{text}");
1404 assert!(text.contains("impl Show for Other"), "{text}");
1405 }
1406
1407 #[test]
1408 fn coherence_is_one_impl_per_trait_per_type() {
1409 let dup =
1410 format!("{SHOW}\nimpl Show for Point:\n def show(self):\n return \"\"\n");
1411 assert!(codes(&dup).contains(&"B0384"), "{:?}", codes(&dup));
1412
1413 let blanket = "\
1415trait Show:
1416 def show(self) -> Str
1417
1418impl[T] Show for T:
1419 def show(self):
1420 return \"\"
1421";
1422 assert!(codes(blanket).contains(&"B0384"), "{:?}", codes(blanket));
1423 }
1424
1425 #[test]
1426 fn the_orphan_rule_needs_the_trait_or_the_type() {
1427 let src = "\
1429impl Show for Int:
1430 def show(self):
1431 return \"\"
1432";
1433 assert!(codes(src).contains(&"B0383"), "{:?}", codes(src));
1435
1436 let owns_trait = "\
1439trait Show:
1440 def show(self) -> Str
1441
1442impl Show for Int:
1443 def show(self):
1444 return str(self)
1445";
1446 assert_eq!(codes(owns_trait), Vec::<&str>::new());
1447 }
1448
1449 #[test]
1450 fn an_impl_must_be_complete_and_no_more() {
1451 let two = "\
1452trait Show:
1453 def show(self) -> Str
1454 def tag(self) -> Str
1455
1456model Point:
1457 x: Int
1458
1459impl Show for Point:
1460 def show(self):
1461 return \"\"
1462";
1463 let text = errors(two);
1464 assert!(text.contains("B0382"), "{text}");
1465 assert!(text.contains("missing: tag"), "{text}");
1466
1467 let extra = SHOW.replace(
1470 " def show(self):\n return str(self.x)\n",
1471 " def show(self):\n return str(self.x)\n\n def nope(self):\n return \"\"\n",
1472 );
1473 let text = errors(&extra);
1474 assert!(text.contains("B0382"), "{text}");
1475 assert!(text.contains("has no method `nope`"), "{text}");
1476 }
1477
1478 #[test]
1479 fn an_impl_writes_the_body_and_the_trait_writes_the_signature() {
1480 for (src, why) in [
1481 (
1482 " def show(self: Point):\n return \"\"\n",
1483 "a parameter type",
1484 ),
1485 (
1486 " def show(self) -> Str:\n return \"\"\n",
1487 "a return type",
1488 ),
1489 (
1490 " def show(self) uses log:\n return \"\"\n",
1491 "an effect row",
1492 ),
1493 ] {
1494 let program = SHOW.replace(" def show(self):\n return str(self.x)\n", src);
1495 assert!(
1496 codes(&program).contains(&"B0382"),
1497 "{why}: {:?}",
1498 codes(&program)
1499 );
1500 }
1501 }
1502
1503 #[test]
1510 fn an_impl_may_perform_more_than_its_trait_declares_and_the_caller_inherits_it() {
1511 let src = "\
1512trait Show:
1513 def show(self) -> Str
1514
1515model Point:
1516 x: Int
1517
1518impl Show for Point:
1519 def show(self):
1520 return str(uuid())
1521
1522def label(p: Point) -> Str:
1523 return p.show()
1524";
1525 let (program, d, map) = crate::check_str("t.beck", src);
1526 assert!(!d.has_errors(), "{}", d.render(&map));
1527 let row: Vec<String> = program
1528 .defs
1529 .get("label")
1530 .expect("label")
1531 .effects
1532 .iter()
1533 .map(|e| e.name())
1534 .collect();
1535 assert_eq!(
1536 row,
1537 vec!["nondet"],
1538 "a caller of a trait method performs what the *impl* performs"
1539 );
1540 }
1541
1542 #[test]
1545 fn a_bounded_definition_inherits_the_row_of_whichever_impl_it_is_given() {
1546 let src = "\
1547trait Show:
1548 def show(self) -> Str
1549
1550model Quiet:
1551 x: Int
1552
1553model Loud:
1554 x: Int
1555
1556impl Show for Quiet:
1557 def show(self):
1558 return str(self.x)
1559
1560impl Show for Loud:
1561 def show(self):
1562 return str(uuid())
1563
1564def label[T: Show](x: T) -> Str:
1565 return x.show()
1566
1567def quiet(q: Quiet) -> Str:
1568 return label(q)
1569
1570def loud(l: Loud) -> Str:
1571 return label(l)
1572";
1573 let (program, d, map) = crate::check_str("t.beck", src);
1574 assert!(!d.has_errors(), "{}", d.render(&map));
1575 let row = |name: &str| -> Vec<String> {
1576 program
1577 .defs
1578 .get(name)
1579 .unwrap_or_else(|| panic!("no `{name}`"))
1580 .effects
1581 .iter()
1582 .map(|e| e.name())
1583 .collect()
1584 };
1585 assert!(
1586 row("quiet").is_empty(),
1587 "a pure impl leaves its caller pure: {:?}",
1588 row("quiet")
1589 );
1590 assert_eq!(row("loud"), vec!["nondet"]);
1591 }
1592
1593 #[test]
1594 fn an_unbounded_type_parameter_cannot_call_a_trait_method() {
1595 let generic = format!(
1598 "{SHOW}
1599def twice[T](x: T) -> Str:
1600 return x.show()
1601"
1602 );
1603 let text = errors(&generic);
1604 assert!(text.contains("B0386"), "{text}");
1605 assert!(text.contains("not known to implement"), "{text}");
1606 assert!(text.contains("[T: Show]"), "the fix names itself:\n{text}");
1607 }
1608
1609 #[test]
1610 fn a_bound_lets_a_generic_body_call_a_trait_method() {
1611 let src = format!(
1612 "{SHOW}
1613def label[T: Show](x: T) -> Str:
1614 return \"<\" + x.show() + \">\"
1615
1616def a() -> Str:
1617 return label(Point(x=1))
1618"
1619 );
1620 assert_eq!(codes(&src), Vec::<&str>::new());
1621
1622 let (program, _, _) = check_str("t.beck", &src);
1625 let label = &program.defs["label"];
1626 assert_eq!(label.params.len(), 2, "{:?}", label.params);
1627 assert_eq!(label.params[1].1.as_ref(), "Show::show@T");
1628 assert_eq!(
1629 label.bounds,
1630 vec![(Arc::<str>::from("T"), vec![Arc::<str>::from("Show")])]
1631 );
1632 }
1633
1634 #[test]
1635 fn a_bounded_definition_passes_its_own_dictionary_through() {
1636 let src = format!(
1639 "{SHOW}
1640def inner[T: Show](x: T) -> Str:
1641 return x.show()
1642
1643def outer[U: Show](x: U) -> Str:
1644 return inner(x)
1645
1646def used() -> Str:
1647 return outer(Point(x=1))
1648"
1649 );
1650 assert_eq!(codes(&src), Vec::<&str>::new());
1651 }
1652
1653 #[test]
1654 fn a_call_takes_its_implementation_from_the_context_when_the_arguments_do_not_say() {
1655 let src = format!(
1656 "{SHOW}
1657def none_of[T: Show](xs: list[T]) -> Option[T]:
1658 return None
1659
1660def nothing() -> Option[Point]:
1661 return none_of([])
1662"
1663 );
1664 assert_eq!(
1665 codes(&src),
1666 Vec::<&str>::new(),
1667 "the element type is in the return type, not in the argument"
1668 );
1669 }
1670
1671 #[test]
1672 fn a_call_whose_type_is_undetermined_says_so() {
1673 let src = format!(
1674 "{SHOW}
1675def none_of[T: Show](xs: list[T]) -> Option[T]:
1676 return None
1677
1678def nothing() -> Int:
1679 return list_len([none_of([])])
1680"
1681 );
1682 let text = errors(&src);
1683 assert!(text.contains("B0386"), "{text}");
1684 assert!(text.contains("not determined at this call"), "{text}");
1685 }
1686
1687 #[test]
1688 fn a_bound_names_a_trait_and_nothing_else() {
1689 let src = format!(
1690 "{SHOW}
1691def label[T: Nope](x: T) -> Str:
1692 return \"\"
1693"
1694 );
1695 assert!(codes(&src).contains(&"B0383"), "{:?}", codes(&src));
1696 }
1697
1698 #[test]
1699 fn neither_a_trait_method_nor_a_bounded_definition_is_a_value() {
1700 let method = format!(
1701 "{SHOW}
1702def all(ps: list[Point]) -> list[Str]:
1703 return map_list(ps, show)
1704"
1705 );
1706 let text = errors(&method);
1707 assert!(text.contains("B0386"), "{text}");
1708 assert!(text.contains("cannot be used as a value"), "{text}");
1709
1710 let bounded = format!(
1713 "{SHOW}
1714def label[T: Show](x: T) -> Str:
1715 return x.show()
1716
1717def all(ps: list[Point]) -> list[Str]:
1718 return map_list(ps, label)
1719"
1720 );
1721 let text = errors(&bounded);
1722 assert!(text.contains("B0386"), "{text}");
1723 assert!(text.contains("has a bound"), "{text}");
1724 }
1725
1726 #[test]
1727 fn a_bounded_definition_publishes_its_bound_and_not_its_dictionaries() {
1728 let src = format!(
1732 "{SHOW}
1733def label[T: Show](x: T) -> Str:
1734 return x.show()
1735"
1736 );
1737 let (placed, d, map) = crate::compile_or_library_str("t.beck", &src);
1738 assert!(!d.has_errors(), "{}", d.render(&map));
1739 let iface = crate::iface::Interface::of(&placed.expect("compiles").program);
1740 let text = iface.render();
1741 assert!(text.contains("trait Show:"), "{text}");
1742 assert!(text.contains(" def show(self) -> Str"), "{text}");
1743 assert!(text.contains("impl Show for Point"), "{text}");
1744 assert!(text.contains("def label[T: Show](x: T) -> Str"), "{text}");
1745 assert!(
1746 !text.contains("Show::show@"),
1747 "a dictionary parameter is not part of the contract:\n{text}"
1748 );
1749 }
1750
1751 #[test]
1752 fn a_declaration_cannot_bound_its_type_parameter() {
1753 let src = "trait Show:\n def show(self) -> Str\n\nmodel Box[T: Show]:\n held: T\n";
1756 let text = errors(src);
1757 assert!(text.contains("B0316"), "{text}");
1758 assert!(text.contains("has no body"), "{text}");
1759 assert!(
1764 !text.contains("B0310"),
1765 "the bound is the defect, and the parameter is still a parameter:\n{text}"
1766 );
1767 }
1768
1769 #[test]
1770 fn a_trait_an_impl_and_a_bound_cross_a_becki() {
1771 let lib = format!(
1774 "{SHOW}
1775def label[T: Show](x: T) -> Str:
1776 return x.show()
1777"
1778 );
1779 let (placed, d, map) = crate::compile_or_library_str("lib.beck", &lib);
1780 assert!(!d.has_errors(), "{}", d.render(&map));
1781 let published = crate::iface::Interface::of(&placed.expect("compiles").program);
1782
1783 let text = published.render();
1785 let mut m = beck_diag::SourceMap::new();
1786 let mut d = beck_diag::Diagnostics::new();
1787 let reread = crate::iface::Interface::parse("lib", &text, &mut m, &mut d);
1788 assert!(!d.has_errors(), "{}\n---\n{text}", d.render(&m));
1789 assert_eq!(published.digest(), reread.digest(), "rendered:\n{text}");
1790 assert_eq!(reread.traits.len(), 1);
1791 assert_eq!(reread.impls.len(), 1);
1792
1793 let app = "\
1796import lib
1797
1798def one() -> Str:
1799 return Point(x=1).show()
1800
1801def two() -> Str:
1802 return label(Point(x=2))
1803";
1804 let node = {
1805 let mut map = beck_diag::SourceMap::new();
1806 let file = map.add("app.beck", app);
1807 let mut d = beck_diag::Diagnostics::new();
1808 let n = beck_syntax::parse_file(file, "app", app, &mut d);
1809 assert!(!d.has_errors(), "{}", d.render(&map));
1810 n
1811 };
1812 let mut d = beck_diag::Diagnostics::new();
1813 let imports = vec![("lib".to_string(), reread)];
1814 let mut map = beck_diag::SourceMap::new();
1815 map.add("app.beck", app);
1816 crate::check::check_module_with(&node, crate::check::Mode::Module, &imports, &mut d);
1817 assert!(!d.has_errors(), "{}", d.render(&map));
1818 }
1819
1820 const RATIONAL: &str = "\
1823model Rational:
1824 numer: Int
1825 denom: Int
1826
1827impl Num for Rational:
1828 def add(self, other):
1829 return Rational(numer=self.numer + other.numer, denom=self.denom)
1830
1831 def sub(self, other):
1832 return self
1833
1834 def mul(self, other):
1835 return self
1836
1837 def div(self, other):
1838 return self
1839";
1840
1841 #[test]
1842 fn a_user_type_joins_the_numeric_tower_through_num() {
1843 let src = format!(
1844 "{RATIONAL}
1845def sum(a: Rational, b: Rational) -> Rational:
1846 return a + b
1847
1848def rest(a: Rational, b: Rational) -> Rational:
1849 return (a - b) * (a / b)
1850"
1851 );
1852 assert_eq!(codes(&src), Vec::<&str>::new());
1853
1854 let (program, _, _) = check_str("t.beck", &src);
1857 assert!(program.defs.contains_key("Num::add@Rational"));
1858 }
1859
1860 #[test]
1861 fn num_is_the_preludes_and_a_module_may_not_implement_it_for_a_type_it_does_not_own() {
1862 let src = "\
1865impl Num for Int:
1866 def add(self, other):
1867 return self
1868
1869 def sub(self, other):
1870 return self
1871
1872 def mul(self, other):
1873 return self
1874
1875 def div(self, other):
1876 return self
1877";
1878 assert!(codes(src).contains(&"B0385"), "{:?}", codes(src));
1879 }
1880
1881 #[test]
1882 fn a_declared_type_with_no_num_impl_is_told_how_to_join() {
1883 let src = "\
1884model Money:
1885 pence: Int
1886
1887def sum(a: Money, b: Money) -> Money:
1888 return a + b
1889";
1890 let text = errors(src);
1891 assert!(text.contains("B0387"), "{text}");
1892 assert!(text.contains("impl Num for Money"), "{text}");
1893 }
1894
1895 #[test]
1896 fn the_numeric_rule_is_unchanged_where_it_already_had_an_answer() {
1897 for (src, want) in [
1901 (
1902 "def f(n: Int, b: Bool) -> Int:\n return n + b\n",
1903 "found `Bool`",
1904 ),
1905 (
1906 "def f(n: Int, x: Float) -> Float:\n return n + x\n",
1907 "found `Float`",
1908 ),
1909 ] {
1910 let text = errors(src);
1911 assert!(text.contains("B0320"), "{text}");
1912 assert!(text.contains(want), "{text}");
1913 }
1914
1915 let ok = "def f(a: Str, b: Str) -> Str:\n return a + b\n";
1917 assert_eq!(codes(ok), Vec::<&str>::new());
1918 }
1919
1920 #[test]
1921 fn a_bounded_type_parameter_may_use_the_operators() {
1922 let src = format!(
1925 "{RATIONAL}
1926def twice[T: Num](x: T) -> T:
1927 return x + x
1928
1929def used(r: Rational) -> Rational:
1930 return twice(r)
1931"
1932 );
1933 assert_eq!(codes(&src), Vec::<&str>::new());
1934 }
1935
1936 #[test]
1937 fn a_method_name_belongs_to_one_trait() {
1938 let src = "\
1939trait Show:
1940 def show(self) -> Str
1941
1942trait Other:
1943 def show(self) -> Str
1944";
1945 assert!(codes(src).contains(&"B0381"), "{:?}", codes(src));
1946 }
1947
1948 #[test]
1949 fn a_trait_method_has_to_mention_self() {
1950 let src = "trait Show:\n def show(n: Int) -> Str\n";
1951 let text = errors(src);
1952 assert!(text.contains("B0381"), "{text}");
1953 assert!(text.contains("nothing dispatches on it"), "{text}");
1954 }
1955
1956 #[test]
1957 fn a_trait_declares_signatures_and_not_bodies() {
1958 let src = "trait Show:\n def show(self) -> Str:\n return \"\"\n";
1959 let text = errors(src);
1960 assert!(text.contains("B0381"), "{text}");
1961 assert!(text.contains("has a body"), "{text}");
1962 }
1963}