1use ecow::EcoString;
2
3use super::Parser;
4use crate::ast::{
5 Annotation, Attribute, AttributeArg, EnumFieldDefinition, EnumVariant, Expression, Generic,
6 Literal, ParentInterface, Span, StructFieldDefinition, StructKind, ValueEnumVariant,
7 VariantFields, Visibility,
8};
9use crate::lex::Token;
10use crate::lex::TokenKind::*;
11use crate::parse::error::ParseError;
12use crate::types::Type;
13
14impl<'source> Parser<'source> {
15 pub(crate) fn parse_attributes(&mut self) -> Vec<Attribute> {
16 let mut attributes = vec![];
17 loop {
18 self.advance_if(Semicolon);
19 if !self.is(Hash) {
20 break;
21 }
22 if let Some(attribute) = self.parse_attribute() {
23 attributes.push(attribute);
24 }
25 }
26 attributes
27 }
28
29 fn parse_attribute(&mut self) -> Option<Attribute> {
30 let start = self.current_token();
31 self.ensure(Hash);
32
33 if !self.is(LeftSquareBracket) {
34 self.track_error("expected `[` after `#`", "Add `[` to start the attribute");
35 return None;
36 }
37 self.next();
38
39 if !self.is(Identifier) {
40 self.track_error(
41 "expected attribute name",
42 "Add an attribute name like `json` or `db`",
43 );
44 while self.is_not(RightSquareBracket) && !self.at_eof() {
45 self.next();
46 }
47 self.advance_if(RightSquareBracket);
48 return None;
49 }
50
51 let name = self.read_identifier();
52 let args = if self.advance_if(LeftParen) {
53 self.parse_attribute_args()
54 } else {
55 vec![]
56 };
57
58 if !self.advance_if(RightSquareBracket) {
59 self.track_error("expected `]`", "Add `]` to close the attribute");
60 }
61
62 Some(Attribute {
63 name: name.to_string(),
64 args,
65 span: self.span_from_tokens(start),
66 })
67 }
68
69 fn parse_attribute_args(&mut self) -> Vec<AttributeArg> {
70 let mut args = vec![];
71
72 while self.is_not(RightParen) && !self.at_eof() {
73 if let Some(arg) = self.parse_attribute_arg() {
74 args.push(arg);
75 }
76
77 if !self.advance_if(Comma) {
78 break;
79 }
80 }
81
82 self.ensure(RightParen);
83 args
84 }
85
86 fn parse_attribute_arg(&mut self) -> Option<AttributeArg> {
87 if self.advance_if(Bang) {
88 if self.is(Identifier) {
89 return Some(AttributeArg::NegatedFlag(
90 self.read_identifier().to_string(),
91 ));
92 } else {
93 self.track_error(
94 "expected identifier after `!`",
95 "Add an identifier like `omitempty` after `!`",
96 );
97 return None;
98 }
99 }
100
101 if self.is(Identifier) {
102 return Some(AttributeArg::Flag(self.read_identifier().to_string()));
103 }
104
105 if self.is(String) {
106 let token = self.current_token();
107 self.next();
108 let text = token.text;
109 let value = if text.len() >= 2 {
110 &text[1..text.len() - 1]
111 } else {
112 text
113 };
114 return Some(AttributeArg::String(value.to_string()));
115 }
116
117 if self.is(Backtick) {
118 let token = self.current_token();
119 self.next();
120 let text = token.text;
121 let value = if text.len() >= 2 {
122 &text[1..text.len() - 1]
123 } else {
124 text
125 };
126 return Some(AttributeArg::Raw(value.to_string()));
127 }
128
129 self.track_error(
130 "expected attribute argument",
131 "Add a flag (e.g. `omitempty`), string (e.g. `\"name\"`), or raw tag (e.g. `` `json:\"name\"` ``)",
132 );
133 None
134 }
135
136 pub fn parse_enum_definition(
137 &mut self,
138 doc: Option<std::string::String>,
139 attributes: Vec<Attribute>,
140 ) -> Expression {
141 let start = self.current_token();
142
143 self.ensure(Enum);
144
145 let name_token = self.current_token();
146 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
147 let name = self.read_identifier();
148 let generics = self.parse_generics();
149
150 let underlying_start = self.current_token();
151 let underlying_ty = if self.advance_if(Colon) {
152 let annotation = self.parse_annotation();
153 Some((annotation, underlying_start))
154 } else {
155 None
156 };
157
158 self.ensure(LeftCurlyBrace);
159
160 if self.peek_is_value_enum_variant() {
161 if !generics.is_empty() {
162 let generics_span = generics.first().expect("non-empty").span;
163 let param_word = if generics.len() == 1 {
164 "parameter"
165 } else {
166 "parameters"
167 };
168 let error = ParseError::new(
169 "Value enum with generics",
170 generics_span,
171 "not allowed on value enums",
172 )
173 .with_parse_code("value_enum_generics")
174 .with_help(format!(
175 "Remove the generic {}. Value enums represent Go const groups, which cannot be generic.",
176 param_word
177 ));
178 self.errors.push(error);
179 }
180
181 let underlying_ty = underlying_ty.map(|(annotation, _)| annotation);
182 return self.parse_value_enum_body(doc, name, name_span, underlying_ty, start);
183 }
184
185 if let Some((_, underlying_token)) = underlying_ty {
186 let underlying_span = Span::new(
187 self.file_id,
188 underlying_token.byte_offset,
189 underlying_token.byte_length,
190 );
191 let error = ParseError::new(
192 "Underlying type on regular enum",
193 underlying_span,
194 "only allowed on value enums",
195 )
196 .with_parse_code("enum_underlying_type")
197 .with_help(
198 "Remove the `: type` annotation. Underlying types are allowed only on value enums, which represent Go const groups.",
199 );
200 self.errors.push(error);
201 }
202
203 self.parse_regular_enum_body(doc, attributes, name, name_span, generics, start)
204 }
205
206 fn peek_is_value_enum_variant(&self) -> bool {
207 if self.is(RightCurlyBrace) {
208 return false;
209 }
210
211 let mut offset = 0;
212 while self.stream.peek_ahead(offset).kind == DocComment {
213 offset += 1;
214 }
215
216 self.stream.peek_ahead(offset).kind == Identifier
217 && self.stream.peek_ahead(offset + 1).kind == Equal
218 }
219
220 fn parse_regular_enum_body(
221 &mut self,
222 doc: Option<std::string::String>,
223 attributes: Vec<Attribute>,
224 name: EcoString,
225 name_span: Span,
226 generics: Vec<Generic>,
227 start: Token<'source>,
228 ) -> Expression {
229 let mut variants = vec![];
230 let mut seen_variants: Vec<(EcoString, Span)> = vec![];
231
232 while self.is_not(RightCurlyBrace) {
233 let start_position = self.stream.position;
234
235 let variant_doc = self.collect_doc_comments().map(|(text, _)| text);
236 if let Some(variant) = self.parse_enum_variant_with_doc(variant_doc) {
237 if let Some((_, first_span)) =
238 seen_variants.iter().find(|(n, _)| n == &variant.name)
239 {
240 self.error_duplicate_enum_variant(
241 &variant.name,
242 *first_span,
243 variant.name_span,
244 );
245 } else {
246 seen_variants.push((variant.name.clone(), variant.name_span));
247 }
248 variants.push(variant);
249 }
250 self.expect_comma_or(RightCurlyBrace);
251 self.ensure_progress(start_position, RightCurlyBrace);
252 }
253
254 self.ensure(RightCurlyBrace);
255
256 Expression::Enum {
257 doc,
258 attributes,
259 name,
260 name_span,
261 generics,
262 variants,
263 visibility: Visibility::Private,
264 span: self.span_from_tokens(start),
265 }
266 }
267
268 fn parse_value_enum_body(
269 &mut self,
270 doc: Option<std::string::String>,
271 name: EcoString,
272 name_span: Span,
273 underlying_ty: Option<Annotation>,
274 start: Token<'source>,
275 ) -> Expression {
276 let mut variants = vec![];
277 let mut seen_variants: Vec<(EcoString, Span)> = vec![];
278
279 while self.is_not(RightCurlyBrace) {
280 let start_position = self.stream.position;
281
282 let variant_doc = self.collect_doc_comments().map(|(text, _)| text);
283 if let Some(variant) = self.parse_value_enum_variant_with_doc(variant_doc) {
284 if let Some((_, first_span)) =
285 seen_variants.iter().find(|(n, _)| n == &variant.name)
286 {
287 self.error_duplicate_enum_variant(
288 &variant.name,
289 *first_span,
290 variant.name_span,
291 );
292 } else {
293 seen_variants.push((variant.name.clone(), variant.name_span));
294 }
295 variants.push(variant);
296 }
297 self.expect_comma_or(RightCurlyBrace);
298 self.ensure_progress(start_position, RightCurlyBrace);
299 }
300
301 self.ensure(RightCurlyBrace);
302
303 Expression::ValueEnum {
304 doc,
305 name,
306 name_span,
307 underlying_ty,
308 variants,
309 visibility: Visibility::Public,
310 span: self.span_from_tokens(start),
311 }
312 }
313
314 fn parse_enum_variant_with_doc(
315 &mut self,
316 doc: Option<std::string::String>,
317 ) -> Option<EnumVariant> {
318 if self.is_not(Identifier) {
319 self.track_error(
320 "expected variant name",
321 "Variant names must be identifiers.",
322 );
323 return None;
324 }
325
326 let name_token = self.current_token();
327 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
328 let name = self.read_identifier();
329 let fields = self.parse_enum_variant_fields();
330
331 Some(EnumVariant {
332 doc,
333 name,
334 name_span,
335 fields,
336 })
337 }
338
339 fn parse_value_enum_variant_with_doc(
340 &mut self,
341 doc: Option<std::string::String>,
342 ) -> Option<ValueEnumVariant> {
343 if self.is_not(Identifier) {
344 self.track_error(
345 "expected variant name",
346 "Variant names must be identifiers.",
347 );
348 return None;
349 }
350
351 let name_token = self.current_token();
352 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
353 let name = self.read_identifier();
354
355 let (value, value_span) = if self.is(Equal) {
356 let eq_token = self.current_token();
357 let start_offset = eq_token.byte_offset;
358 self.next(); let (value, value_end) = self.parse_value_enum_variant_value();
360 let span = Span::new(self.file_id, start_offset, value_end - start_offset);
361 (value, span)
362 } else {
363 (
364 Literal::Integer {
365 value: 0,
366 text: None,
367 },
368 name_span,
369 )
370 };
371
372 Some(ValueEnumVariant {
373 doc,
374 name,
375 name_span,
376 value,
377 value_span,
378 })
379 }
380
381 fn parse_value_enum_variant_value(&mut self) -> (Literal, u32) {
382 const EMPTY: Literal = Literal::Integer {
383 value: 0,
384 text: None,
385 };
386
387 let token = self.current_token();
388
389 match token.kind {
390 Integer => {
391 let text = token.text;
392 let end = token.byte_offset + token.byte_length;
393 let literal = self.parse_integer_text_with(text, true);
394 self.next();
395 (literal, end)
396 }
397 String => {
398 let text = token.text;
399 let end = token.byte_offset + token.byte_length;
400 self.next();
401 (
402 Literal::String {
403 value: text[1..text.len() - 1].to_string(),
404 raw: false,
405 },
406 end,
407 )
408 }
409 Minus => {
410 let minus_offset = token.byte_offset;
411 self.next();
412 let next_token = self.current_token();
413 if next_token.kind != Integer {
414 self.track_error(
415 "expected integer after `-`",
416 "Use `-42` for negative integers.",
417 );
418 return (EMPTY, next_token.byte_offset);
419 }
420 let text = next_token.text;
421 let end = next_token.byte_offset + next_token.byte_length;
422 let neg_span = Span::new(self.file_id, minus_offset, end - minus_offset);
423 let literal = self.parse_integer_text_with(text, true);
424 self.next();
425 let Literal::Integer { value, text: orig } = literal else {
426 return (EMPTY, end);
427 };
428 if value > i64::MIN.unsigned_abs() {
429 self.track_error_at(
430 neg_span,
431 "negative integer out of range",
432 "Negative integer must be ≥ -9223372036854775808 (i64 minimum).",
433 );
434 return (EMPTY, end);
435 }
436 (
437 Literal::Integer {
438 value: value.wrapping_neg(),
439 text: orig.map(|t| format!("-{t}")),
440 },
441 end,
442 )
443 }
444 _ => {
445 self.track_error(
446 "expected integer or string literal",
447 "Value enum variants require integer or string values.",
448 );
449 (EMPTY, token.byte_offset)
450 }
451 }
452 }
453
454 fn parse_enum_variant_fields(&mut self) -> VariantFields {
455 if self.advance_if(LeftParen) {
456 return self.parse_tuple_variant_fields();
457 }
458
459 if self.advance_if(LeftCurlyBrace) {
460 return self.parse_struct_variant_fields();
461 }
462
463 VariantFields::Unit
464 }
465
466 fn parse_tuple_variant_fields(&mut self) -> VariantFields {
467 let mut fields = vec![];
468
469 loop {
470 if self.at_eof()
471 || self.is(RightParen)
472 || self.is(RightCurlyBrace)
473 || !self.can_start_annotation()
474 {
475 break;
476 }
477
478 let field = EnumFieldDefinition {
479 name: format!("field{}", fields.len()).into(),
480 name_span: Span::dummy(),
481 annotation: self.parse_annotation(),
482 ty: Type::uninferred(),
483 };
484
485 fields.push(field);
486
487 self.expect_comma_or(RightParen);
488 }
489
490 self.ensure(RightParen);
491
492 VariantFields::Tuple(fields)
493 }
494
495 fn parse_struct_variant_fields(&mut self) -> VariantFields {
496 let mut fields = vec![];
497 let mut seen_fields: Vec<(EcoString, Span)> = vec![];
498
499 loop {
500 if self.at_eof()
501 || self.is(RightCurlyBrace)
502 || self.at_item_boundary()
503 || self.is_not(Identifier)
504 {
505 break;
506 }
507
508 let name_token = self.current_token();
509 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
510 let name = self.read_identifier();
511 self.ensure(Colon);
512 let annotation = self.parse_annotation();
513
514 if let Some((_, first_span)) = seen_fields.iter().find(|(n, _)| n == &name) {
515 self.error_duplicate_struct_field(&name, *first_span, name_span);
516 } else {
517 seen_fields.push((name.clone(), name_span));
518 }
519
520 let field = EnumFieldDefinition {
521 name,
522 name_span,
523 annotation,
524 ty: Type::uninferred(),
525 };
526
527 fields.push(field);
528
529 self.expect_comma_or(RightCurlyBrace);
530 }
531
532 self.ensure(RightCurlyBrace);
533
534 VariantFields::Struct(fields)
535 }
536
537 pub fn parse_struct_definition(
538 &mut self,
539 doc: Option<std::string::String>,
540 attributes: Vec<Attribute>,
541 ) -> Expression {
542 let start = self.current_token();
543
544 self.ensure(Struct);
545
546 let name_token = self.current_token();
547 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
548 let name = self.read_identifier();
549 let generics = self.parse_generics();
550
551 if self.is(LeftParen) {
552 return self.parse_tuple_struct(doc, attributes, name, name_span, generics, start);
553 }
554
555 self.parse_named_struct(doc, attributes, name, name_span, generics, start)
556 }
557
558 fn parse_named_struct(
559 &mut self,
560 doc: Option<std::string::String>,
561 attributes: Vec<Attribute>,
562 name: EcoString,
563 name_span: Span,
564 generics: Vec<Generic>,
565 start: Token<'source>,
566 ) -> Expression {
567 let mut fields = vec![];
568 let mut seen_fields: Vec<(EcoString, Span)> = vec![];
569
570 self.ensure(LeftCurlyBrace);
571
572 while self.is_not(RightCurlyBrace) {
573 let start_position = self.stream.position;
574
575 let field_attributes = self.parse_attributes();
576 let field_doc = self.collect_doc_comments().map(|(text, _)| text);
577 if let Some(field) = self.parse_struct_field_with_doc(field_doc, field_attributes) {
578 if let Some((_, first_span)) = seen_fields.iter().find(|(n, _)| n == &field.name) {
579 self.error_duplicate_struct_field(&field.name, *first_span, field.name_span);
580 } else {
581 seen_fields.push((field.name.clone(), field.name_span));
582 }
583 fields.push(field);
584 }
585 self.expect_comma_or(RightCurlyBrace);
586 self.ensure_progress(start_position, RightCurlyBrace);
587 }
588
589 self.ensure(RightCurlyBrace);
590
591 Expression::Struct {
592 doc,
593 attributes,
594 name,
595 name_span,
596 generics,
597 fields,
598 kind: StructKind::Record,
599 visibility: Visibility::Private,
600 span: self.span_from_tokens(start),
601 }
602 }
603
604 fn parse_tuple_struct(
605 &mut self,
606 doc: Option<std::string::String>,
607 attributes: Vec<Attribute>,
608 name: EcoString,
609 name_span: Span,
610 generics: Vec<Generic>,
611 start: Token<'source>,
612 ) -> Expression {
613 self.ensure(LeftParen);
614
615 let mut fields = vec![];
616 let mut index = 0;
617
618 while self.is_not(RightParen) {
619 if self.at_eof() || self.at_item_boundary() || !self.can_start_annotation() {
620 break;
621 }
622
623 let field_start = self.current_token();
624 let annotation = self.parse_annotation();
625 let field_span = self.span_from_tokens(field_start);
626
627 fields.push(StructFieldDefinition {
628 doc: None,
629 attributes: vec![],
630 name: format!("_{}", index).into(),
631 name_span: field_span,
632 annotation,
633 visibility: Visibility::Private,
634 ty: Type::uninferred(),
635 });
636
637 index += 1;
638 self.expect_comma_or(RightParen);
639 }
640
641 self.ensure(RightParen);
642
643 Expression::Struct {
644 doc,
645 attributes,
646 name,
647 name_span,
648 generics,
649 fields,
650 kind: StructKind::Tuple,
651 visibility: Visibility::Private,
652 span: self.span_from_tokens(start),
653 }
654 }
655
656 fn parse_struct_field_with_doc(
657 &mut self,
658 doc: Option<std::string::String>,
659 attributes: Vec<Attribute>,
660 ) -> Option<StructFieldDefinition> {
661 let visibility = if self.advance_if(Pub) {
662 Visibility::Public
663 } else {
664 Visibility::Private
665 };
666
667 if self.is(Mut) {
668 self.track_error(
669 "fields cannot be marked `mut`",
670 "Fields cannot be marked `mut`; mutability applies to bindings (`let mut x = ...`).",
671 );
672 self.next();
673 }
674
675 if self.is_not(Identifier) {
676 self.track_error("expected field name", "Field names must be identifiers.");
677 return None;
678 }
679
680 let name_token = self.current_token();
681 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
682 let name = self.read_identifier();
683
684 self.ensure(Colon);
685
686 Some(StructFieldDefinition {
687 doc,
688 attributes,
689 visibility,
690 name,
691 name_span,
692 annotation: self.parse_annotation(),
693 ty: Type::uninferred(),
694 })
695 }
696
697 pub fn parse_const_definition(&mut self, doc: Option<std::string::String>) -> Expression {
698 let start = self.current_token();
699
700 self.ensure(Const);
701
702 let identifier_token = self.current_token();
703 let identifier_span = Span::new(
704 self.file_id,
705 identifier_token.byte_offset,
706 identifier_token.byte_length,
707 );
708 let identifier = self.read_identifier();
709 let annotation = if self.advance_if(Colon) {
710 Some(self.parse_annotation())
711 } else {
712 None
713 };
714
715 let expression = if self.advance_if(Equal) {
716 self.parse_expression()
717 } else {
718 Expression::NoOp
719 };
720
721 Expression::Const {
722 doc,
723 identifier,
724 identifier_span,
725 annotation,
726 expression: expression.into(),
727 visibility: Visibility::Private,
728 ty: Type::uninferred(),
729 span: self.span_from_tokens(start),
730 }
731 }
732
733 pub fn parse_var_declaration(&mut self, doc: Option<std::string::String>) -> Expression {
734 let start = self.current_token();
735
736 self.ensure(Var);
737
738 let name_token = self.current_token();
739 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
740 let name = self.read_identifier();
741
742 self.ensure(Colon);
743 let annotation = self.parse_annotation();
744
745 Expression::VariableDeclaration {
746 doc,
747 name,
748 name_span,
749 annotation,
750 visibility: Visibility::Private,
751 ty: Type::uninferred(),
752 span: self.span_from_tokens(start),
753 }
754 }
755
756 pub fn parse_impl_block(&mut self) -> Expression {
757 let start = self.current_token();
758
759 self.ensure(Impl);
760
761 let generics = self.parse_generics();
762
763 let receiver = self.parse_annotation(); let (receiver_name, annotation) = match &receiver {
766 Annotation::Constructor { name, .. } => (name.clone(), receiver),
767 _ => {
768 self.track_error("expected `impl` receiver", "Use `impl TypeName { ... }`.");
769 ("".into(), Annotation::Unknown)
770 }
771 };
772
773 if self.is(For) {
774 self.track_error(
775 "invalid syntax",
776 "Lisette types satisfy interfaces automatically by having the required methods. Use `impl Type { ... }` to add methods.",
777 );
778 self.next();
779 self.parse_annotation();
780 }
781
782 let mut methods = vec![];
783
784 self.ensure(LeftCurlyBrace);
785
786 while self.is_not(RightCurlyBrace) {
787 self.advance_if(Semicolon);
788 if self.is(RightCurlyBrace) {
789 break;
790 }
791
792 let method_doc = self.collect_doc_comments();
793 let method_attrs = self.parse_attributes();
794 let is_public = self.advance_if(Pub);
795
796 if self.is(Function) {
797 let method = self.parse_function(method_doc.map(|(text, _)| text), method_attrs);
798 let method = if is_public {
799 method.set_public()
800 } else {
801 method
802 };
803 methods.push(method);
804 } else {
805 if let Some((_, span)) = method_doc {
806 self.error_detached_doc_comment(span);
807 }
808 self.track_error(
809 "expected `fn` in impl block",
810 "Only functions are allowed in `impl` blocks.",
811 );
812 self.next();
813 }
814 }
815
816 self.ensure(RightCurlyBrace);
817
818 Expression::ImplBlock {
819 annotation,
820 methods,
821 receiver_name,
822 generics,
823 ty: Type::uninferred(),
824 span: self.span_from_tokens(start),
825 }
826 }
827
828 pub fn parse_interface_definition(&mut self, doc: Option<std::string::String>) -> Expression {
829 let start = self.current_token();
830
831 self.ensure(Interface);
832
833 let name_token = self.current_token();
834 let name_span = Span::new(self.file_id, name_token.byte_offset, name_token.byte_length);
835 let name = self.read_identifier();
836
837 let generics = self.parse_generics();
838
839 let mut parents = vec![];
840 let mut seen_parents: Vec<(EcoString, Span)> = vec![];
841 let mut method_signatures = vec![];
842 let mut seen_methods: Vec<(EcoString, Span)> = vec![];
843
844 self.ensure(LeftCurlyBrace);
845
846 while self.is_not(RightCurlyBrace) {
847 self.advance_if(Semicolon);
848 if self.is(RightCurlyBrace) {
849 break;
850 }
851
852 let item_doc = self.collect_doc_comments();
853 let method_attrs = self.parse_attributes();
854 match self.current_token().kind {
855 Function => {
856 let method =
857 self.parse_interface_method(item_doc.map(|(text, _)| text), method_attrs);
858 if let Expression::Function {
859 ref name,
860 ref name_span,
861 ..
862 } = method
863 {
864 if let Some((_, first_span)) = seen_methods.iter().find(|(n, _)| n == name)
865 {
866 self.error_duplicate_interface_method(name, *first_span, *name_span);
867 } else {
868 seen_methods.push((name.clone(), *name_span));
869 }
870 }
871 method_signatures.push(method);
872 self.advance_if(Semicolon);
873 }
874
875 Impl => {
876 if let Some((_, span)) = item_doc {
877 self.error_detached_doc_comment(span);
878 }
879 self.ensure(Impl);
880
881 let parent_start = self.current_token();
882 let annotation = self.parse_annotation();
883 let parent_span = self.span_from_tokens(parent_start);
884
885 if let Annotation::Constructor { name, .. } = &annotation {
886 if let Some((_, first_span)) =
887 seen_parents.iter().find(|(n, _)| n == name.as_str())
888 {
889 self.error_duplicate_impl_parent(*first_span, parent_span);
890 } else {
891 seen_parents.push((name.clone(), parent_span));
892 }
893 }
894
895 parents.push(ParentInterface {
896 annotation,
897 ty: Type::uninferred(),
898 span: parent_span,
899 });
900 self.advance_if(Semicolon);
901 }
902
903 _ => {
904 if let Some((_, span)) = item_doc {
905 self.error_detached_doc_comment(span);
906 }
907 self.track_error(
908 "expected `fn` or `impl`",
909 "Only functions and `impl` blocks are allowed in interfaces.",
910 );
911 self.next();
912 }
913 }
914 }
915
916 self.ensure(RightCurlyBrace);
917
918 Expression::Interface {
919 doc,
920 name,
921 name_span,
922 generics,
923 parents,
924 method_signatures,
925 visibility: Visibility::Private,
926 span: self.span_from_tokens(start),
927 }
928 }
929}