From 5d3dbb5b575c03c907de6b14144e7108f9c88f21 Mon Sep 17 00:00:00 2001 From: FullyNonlinear Date: Mon, 1 Jul 2024 13:27:13 +0800 Subject: [PATCH 1/2] Check trait items for duplicate function names or duplicate associated type names --- crates/formality-check/src/traits.rs | 25 ++++++++++++++-- src/test/mod.rs | 45 ++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) diff --git a/crates/formality-check/src/traits.rs b/crates/formality-check/src/traits.rs index 22791031..d319f652 100644 --- a/crates/formality-check/src/traits.rs +++ b/crates/formality-check/src/traits.rs @@ -1,4 +1,6 @@ +use anyhow::bail; use fn_error_context::context; +use formality_core::Set; use formality_prove::Env; use formality_rust::grammar::{ AssociatedTy, AssociatedTyBoundData, Fn, Trait, TraitBoundData, TraitItem, WhereClause, @@ -31,8 +33,27 @@ impl super::Check<'_> { Ok(()) } - fn check_trait_items_have_unique_names(&self, _trait_items: &[TraitItem]) -> Fallible<()> { - // FIXME: + fn check_trait_items_have_unique_names(&self, trait_items: &[TraitItem]) -> Fallible<()> { + let mut functions = Set::new(); + let mut associated_types = Set::new(); + for trait_item in trait_items { + match trait_item { + TraitItem::Fn(f) => { + if !functions.insert(&f.id) { + bail!("the function name `{:?}` is defined multiple times", f.id); + } + } + TraitItem::AssociatedTy(associated_ty) => { + let AssociatedTy { id, .. } = associated_ty; + if !associated_types.insert(id) { + bail!( + "the associated type name `{:?}` is defined multiple times", + id + ); + } + } + } + } Ok(()) } diff --git a/src/test/mod.rs b/src/test/mod.rs index b525f96e..9fc7bd87 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -133,3 +133,48 @@ fn basic_where_clauses_fail() { expression evaluated to an empty collection: `decls.trait_invariants()`"#]] ) } + +#[test] +fn trait_items_with_duplicate_fn_names() { + crate::assert_err!( + [ + crate core { + trait A { + fn a() -> (); + fn a() -> (); + } + } + ] + + [ /* TODO */ ] + + expect_test::expect![[r#" + check_trait(A) + + Caused by: + the function name `a` is defined multiple times"#]] + + ); +} + +#[test] +fn trait_items_with_duplicate_associated_type_names() { + crate::assert_err!( + [ + crate core { + trait A { + type Assoc : []; + type Assoc : []; + } + } + ] + + [ /* TODO */ ] + + expect_test::expect![[r#" + check_trait(A) + + Caused by: + the associated type name `Assoc` is defined multiple times"#]] + ); +} From 1cff4c250d9d7acfe95102a96070724d01b88757 Mon Sep 17 00:00:00 2001 From: FullyNonlinear Date: Mon, 1 Jul 2024 23:08:36 +0800 Subject: [PATCH 2/2] Pass test specific error message to must_have --- src/test/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/test/mod.rs b/src/test/mod.rs index 9fc7bd87..8e6c1158 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -146,7 +146,7 @@ fn trait_items_with_duplicate_fn_names() { } ] - [ /* TODO */ ] + ["the function name `a` is defined multiple times",] expect_test::expect![[r#" check_trait(A) @@ -169,7 +169,7 @@ fn trait_items_with_duplicate_associated_type_names() { } ] - [ /* TODO */ ] + ["the associated type name `Assoc` is defined multiple times",] expect_test::expect![[r#" check_trait(A)