plum

#treesitter#compiler#wasm

git clone https://git.pyrossh.dev/plum

A statically typed, imperative programming language inspired by rust, python


6270408 — Peter John 2026-11-01T17:04:10+05:30
fix: checker reports unknown methods on static consts
plum-checker/src/lib.rs CHANGED
@@ -3337,10 +3337,13 @@ fn inferMethodCall(
3337
3337
  // a declared type lacking the method is a real (duck-typing) error.
3338
3338
  // Builtin/primitive receivers too: their methods are those declared in
3339
3339
  // plum-std plus the compiler intrinsics handled before this lookup.
3340
+ // A fully concrete generic receiver (`Map[Str, Int]`) is checked in the
3341
+ // erased pass too, so a typo'd method is a positioned checker error
3342
+ // rather than a late codegen failure.
3340
- if INST_MODE.with(|m| m.get()) && !hasFreeVars(obj_ty) {
3343
+ if !hasFreeVars(obj_ty) && (INST_MODE.with(|m| m.get()) || matches!(obj_ty, PlumType::TApp(..))) {
3341
3344
  return Err(format!("{} has no method '{}'", obj_ty, name));
3342
3345
  }
3343
- // Outside an instantiation (erased pass): allow, the per-instance pass decides.
3346
+ // Otherwise (erased pass): allow, the per-instance pass decides.
3344
3347
  return Ok(PlumType::TVar("_".to_string()));
3345
3348
  };
3346
3349
  let PlumType::TFun(..) = sig else {
plum-checker/tests/checker_tests.rs CHANGED
@@ -2114,3 +2114,16 @@ fn comparing_an_optional_or_error_union_with_a_value_is_rejected() {
2114
2114
  assert!(msg.contains("cannot compare"), "{msg}");
2115
2115
  assert!(checkSource(&parseClean("fun f(a: Int?) -> Bool =\n a == null\n")).is_ok());
2116
2116
  }
2117
+
2118
+ #[test]
2119
+ fn unknown_method_on_heap_const_is_checker_error() {
2120
+ let src = |call: &str| {
2121
+ format!(
2122
+ "enum Box[T] =\n | Box(v: T)\n\n fun get(self) -> T =\n self.v\n\nenum Cfg =\n | Cfg(a: Int)\n\n CELL = Box(1)\n\nfun f() -> Int =\n {}\n",
2123
+ call
2124
+ )
2125
+ };
2126
+ let msg = errText(checkSrc(&src("Cfg.CELL.size()")));
2127
+ assert!(msg.contains("Box[Int] has no method 'size'"), "{}", msg);
2128
+ assert!(checkSrc(&src("Cfg.CELL.get()")).is_ok());
2129
+ }