diff --git a/crates/formality-check/src/adts.rs b/crates/formality-check/src/adts.rs index dde84ab1..dcf8df85 100644 --- a/crates/formality-check/src/adts.rs +++ b/crates/formality-check/src/adts.rs @@ -1,3 +1,6 @@ +use std::collections::HashSet; + +use anyhow::bail; use formality_prove::Env; use formality_rust::grammar::{Adt, AdtBoundData, Field, Variant}; use formality_types::grammar::Fallible; @@ -6,6 +9,20 @@ impl super::Check<'_> { pub(super) fn check_adt(&self, adt: &Adt) -> Fallible<()> { let Adt { id: _, binder } = adt; + // names is used to check that there are no name conflicts + let mut names = HashSet::new(); + for Variant { name, fields } in &adt.binder.peek().variants { + if !names.insert((name, None)) { + bail!("variant \"{name:?}\" defined multiple times"); + } + let vname = name; + for Field { name, ty: _ } in fields { + if !names.insert((vname, Some(name))) { + bail!("field \"{name:?}\" of variant \"{vname:?}\" defined multiple times"); + } + } + } + let mut env = Env::default(); let AdtBoundData { @@ -15,8 +32,6 @@ impl super::Check<'_> { self.prove_where_clauses_well_formed(&env, &where_clauses, &where_clauses)?; - // FIXME: check names are unique or integers from 0..n - for Variant { name: _, fields } in &variants { for Field { name: _, ty } in fields { self.prove_goal(&env, &where_clauses, ty.well_formed())?; diff --git a/src/test/mod.rs b/src/test/mod.rs index 7a66c1be..0e5b3870 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -135,6 +135,42 @@ fn basic_where_clauses_fail() { ) } +#[test] +fn basic_adt_variant_dup() { + crate::assert_err!( + [ + crate Foo { + enum Bar { + Baz{}, + Baz{}, + } + } + ] + + [ r#"variant "Baz" defined multiple times"#, ] + + expect_test::expect![[r#"variant "Baz" defined multiple times"#]] + ) +} + +#[test] +fn basic_adt_field_dup() { + crate::assert_err!( + [ + crate Foo { + struct Bar { + baz: (), + baz: (), + } + } + ] + + [ r#"field "baz" of variant "struct" defined multiple times"#, ] + + expect_test::expect![[r#"field "baz" of variant "struct" defined multiple times"#]] + ) +} + #[test] fn trait_items_with_duplicate_fn_names() { crate::assert_err!(