plum

#treesitter#compiler#wasm

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

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


0d64affPeter John 2026-07-24T11:23:34+05:30
fix(plum-core): derive trait method return type from type-kind child, not the wrong 'returns' field
plum-core/src/parser.rs CHANGED
@@ -154,7 +154,18 @@ impl<'a> AstParser<'a> {
154
154
  // trait_field (aliased to field): fn_identifier "(" params ")" ("->" type)?
155
155
  let name = node.named_child(0).map(|n| self.text(n)).unwrap_or_default();
156
156
  let params = self.collect_params_from(node);
157
+
158
+ // As with `parse_fn`'s `returns` field, the grammar's `returns` field
159
+ // wraps the whole `optional(seq("->", $.type))`, so
157
- let returns = node.child_by_field_name("returns").map(|n| self.parse_type(n));
160
+ // `child_by_field_name("returns")` resolves to the anonymous "->"
161
+ // token, not the `type` node. Unlike `parse_fn`, a trait method has
162
+ // no receiver annotation, so there's at most one `type`-kind named
163
+ // child here, and it's unambiguously the return type when present.
164
+ let returns = node
165
+ .named_children(&mut node.walk())
166
+ .find(|n| n.kind() == "type")
167
+ .map(|n| self.parse_type(n));
168
+
158
169
  TraitMethod { name, params, returns }
159
170
  }
160
171
 
plum-core/tests/parser_test.rs CHANGED
@@ -14,6 +14,10 @@ fn only_fn(source: &Source) -> &Fn {
14
14
  source.items.iter().find_map(|i| match i { Item::Fn(f) => Some(f), _ => None }).expect("expected a Fn item")
15
15
  }
16
16
 
17
+ fn only_trait(source: &Source) -> &Trait {
18
+ source.items.iter().find_map(|i| match i { Item::Trait(t) => Some(t), _ => None }).expect("expected a Trait item")
19
+ }
20
+
17
21
  #[test]
18
22
  fn closure_literal_parses_with_params_and_body() {
19
23
  let src = "\
@@ -76,6 +80,20 @@ fn fn_value_type_param_parses_with_positional_types_and_return() {
76
80
  assert_eq!(ret.as_ref().map(|t| t.name.clone()), Some("Bool".to_string()));
77
81
  }
78
82
 
83
+ #[test]
84
+ fn trait_method_return_type_is_not_mangled_to_arrow_token() {
85
+ let src = "trait Show =\n show() -> Str\n";
86
+ let source = parse(src);
87
+ let t = only_trait(&source);
88
+ let method = &t.methods[0];
89
+ assert_eq!(method.name, "show");
90
+ assert_eq!(
91
+ method.returns.as_ref().map(|r| r.name.clone()),
92
+ Some("Str".to_string()),
93
+ "trait method return type must be the real type, not the '->' token"
94
+ );
95
+ }
96
+
79
97
  #[test]
80
98
  fn fn_value_type_param_parses_with_no_return() {
81
99
  let src = "each(cb: fn(Int)) -> Bool =\n True\n";