Skip to content

Commit de24730

Browse files
committed
Reject duplicate type fields
1 parent 8b53bad commit de24730

4 files changed

Lines changed: 53 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ It currently implements:
2424
Implemented diagnostic classes include:
2525

2626
- file mode violations
27-
- duplicate top-level declarations that would make symbol resolution ambiguous
27+
- duplicate declarations that would make symbol or field resolution ambiguous
2828
- missing named arguments
2929
- unknown, missing, and duplicate call arguments for known signatures
3030
- unknown callees outside known functions, constructors, enum variants, and builtin signatures

src/analyzer.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,5 +189,6 @@ fn duplicate_symbol_label(kind: DuplicateSymbolKind) -> &'static str {
189189
DuplicateSymbolKind::Function => "function",
190190
DuplicateSymbolKind::Type => "type",
191191
DuplicateSymbolKind::Constructor => "callable",
192+
DuplicateSymbolKind::Field => "field",
192193
}
193194
}

src/hir.rs

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ pub enum DuplicateSymbolKind {
6767
Function,
6868
Type,
6969
Constructor,
70+
Field,
7071
}
7172

7273
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -104,6 +105,7 @@ impl Hir {
104105
hir.insert_function(function_sig_from_decl(function));
105106
}
106107
Item::Type(type_decl) => {
108+
record_duplicate_fields(&mut hir.duplicate_symbols, type_decl);
107109
record_duplicate_symbol(
108110
&mut hir.duplicate_symbols,
109111
&mut type_symbols,
@@ -223,6 +225,19 @@ fn record_duplicate_symbol(
223225
symbols.insert(name.to_string(), (kind, span.clone()));
224226
}
225227

228+
fn record_duplicate_fields(duplicates: &mut Vec<DuplicateSymbol>, type_decl: &TypeDecl) {
229+
let mut fields = HashMap::new();
230+
for field in &type_decl.fields {
231+
record_duplicate_symbol(
232+
duplicates,
233+
&mut fields,
234+
DuplicateSymbolKind::Field,
235+
&format!("{}.{}", type_decl.name, field.name),
236+
&field.span,
237+
);
238+
}
239+
}
240+
226241
fn duplicate_symbol_kind(
227242
first: DuplicateSymbolKind,
228243
duplicate: DuplicateSymbolKind,
@@ -232,6 +247,7 @@ fn duplicate_symbol_kind(
232247
DuplicateSymbolKind::Function
233248
}
234249
(DuplicateSymbolKind::Type, DuplicateSymbolKind::Type) => DuplicateSymbolKind::Type,
250+
(DuplicateSymbolKind::Field, DuplicateSymbolKind::Field) => DuplicateSymbolKind::Field,
235251
_ => DuplicateSymbolKind::Constructor,
236252
}
237253
}
@@ -786,4 +802,28 @@ fn Image(path: read Path) -> Image {
786802
assert_eq!(duplicate.first_span.line, 4);
787803
assert_eq!(duplicate.duplicate_span.line, 8);
788804
}
805+
806+
#[test]
807+
fn records_duplicate_fields() {
808+
let source = r#"
809+
mode: managed
810+
811+
struct Response {
812+
status: Int
813+
status: String
814+
}
815+
"#;
816+
817+
let program = parse_source("test.rss", source);
818+
let hir = Hir::from_syntax(&program);
819+
let duplicate = hir
820+
.duplicate_symbols()
821+
.first()
822+
.expect("duplicate field is recorded");
823+
824+
assert_eq!(duplicate.kind, DuplicateSymbolKind::Field);
825+
assert_eq!(duplicate.name, "Response.status");
826+
assert_eq!(duplicate.first_span.line, 5);
827+
assert_eq!(duplicate.duplicate_span.line, 6);
828+
}
789829
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
// expect: RS0005
2+
mode: managed
3+
4+
struct Response {
5+
status: Int
6+
status: String
7+
}
8+
9+
fn ok() -> Unit {
10+
return Unit
11+
}

0 commit comments

Comments
 (0)