diff --git a/lib/classes.ml b/lib/classes.ml index bdf905d..f93c384 100644 --- a/lib/classes.ml +++ b/lib/classes.ml @@ -124,9 +124,15 @@ let collect (decls : Ast.decl list) = list: one call site reaches all of them, and it can only pass \ one number of arguments" m.Ast.mgen want (if want = 1 then "" else "s") n; + (* A class's name and its keyword are one dispatch value — a class + stands for the keyword its instances carry, which is the whole of + how the two dispatch styles share a mechanism — so [point] and + [:point] have to be compared as one or the second method is + accepted and is dead code. *) + let norm = function Ast.Dclass c -> Ast.Dkw c | k -> k in List.iter (fun (prev : Ast.methd) -> - if prev.Ast.mkey = m.Ast.mkey then + if norm prev.Ast.mkey = norm m.Ast.mkey then Loc.failk "check/duplicate-method" d.Ast.dloc "%s already has a method for %s. Two methods for one \ dispatch value is an ambiguity nothing resolves — there \ diff --git a/test/test_flan.ml b/test/test_flan.ml index a30703f..f271d2f 100644 --- a/test/test_flan.ml +++ b/test/test_flan.ml @@ -1803,6 +1803,16 @@ let () = (defmethod area point [p] 2)\n\ (defn main [] i32 0)" ~needle:"already has a method for point"; + (* A class's name and its keyword are one value: a class stands for the + keyword its instances carry, so these two methods are the same method + written twice and the second would be dead code. *) + rejects_check "a class and its keyword are one dispatch value" + "(defclass point [x y])\n\ + (defgeneric area [self] dyn)\n\ + (defmethod area point [p] 1)\n\ + (defmethod area :point [p] 2)\n\ + (defn main [] i32 0)" + ~needle:"already has a method for :point"; rejects_check "two :else methods for one generic" "(defmulti d [x] dyn x)\n\ (defmethod d :else [x] 1)\n\