diff --git a/crates/ailang-surface/src/parse.rs b/crates/ailang-surface/src/parse.rs index 2e9af37..ed68f69 100644 --- a/crates/ailang-surface/src/parse.rs +++ b/crates/ailang-surface/src/parse.rs @@ -373,8 +373,17 @@ impl<'a> Parser<'a> { loop { match self.peek_head_ident() { Some("doc") => { - let s = self.parse_doc()?; - doc = Some(s); + if doc.is_some() { + let pos = self.peek().map(|t| t.span.start).unwrap_or(0); + return Err(ParseError::Production { + production: "data-def", + message: format!( + "data `{name}` has duplicate `(doc ...)` clause" + ), + pos, + }); + } + doc = Some(self.parse_doc()?); } Some("ctor") => { ctors.push(self.parse_ctor()?); @@ -2474,4 +2483,23 @@ mod tests { "expected duplicate-body diagnostic, got: {msg}" ); } + + #[test] + fn parse_data_rejects_duplicate_doc_clause() { + let err = parse( + r#" + (module m + (data D + (doc "first") + (doc "second") + (ctor C))) + "#, + ) + .unwrap_err(); + let msg = format!("{err:?}"); + assert!( + msg.contains("data `D` has duplicate `(doc ...)` clause"), + "expected duplicate-doc diagnostic, got: {msg}" + ); + } }