diff --git a/crates/analyzer/src/namespace/items.rs b/crates/analyzer/src/namespace/items.rs index 8126314902..779c719664 100644 --- a/crates/analyzer/src/namespace/items.rs +++ b/crates/analyzer/src/namespace/items.rs @@ -1789,12 +1789,14 @@ impl ImplId { &self, db: &dyn AnalyzerDb, sink: &mut impl DiagnosticSink, - type_module: Option, + type_ingot: Option, ) { - let impl_module = self.data(db).module; - let is_allowed = match type_module { - None => impl_module == self.data(db).trait_id.module(db), - Some(val) => val == impl_module || self.data(db).trait_id.module(db) == impl_module, + let impl_ingot = self.data(db).module.ingot(db); + let is_allowed = match type_ingot { + None => impl_ingot == self.data(db).trait_id.module(db).ingot(db), + Some(val) => { + val == impl_ingot || self.data(db).trait_id.module(db).ingot(db) == impl_ingot + } }; if !is_allowed { @@ -1831,10 +1833,10 @@ impl ImplId { vec![], )), Type::Struct(id) => { - self.validate_type_or_trait_is_in_ingot(db, sink, Some(id.module(db))) + self.validate_type_or_trait_is_in_ingot(db, sink, Some(id.module(db).ingot(db))) } Type::Enum(id) => { - self.validate_type_or_trait_is_in_ingot(db, sink, Some(id.module(db))) + self.validate_type_or_trait_is_in_ingot(db, sink, Some(id.module(db).ingot(db))) } Type::Base(_) | Type::Array(_) | Type::Tuple(_) | Type::String(_) => { self.validate_type_or_trait_is_in_ingot(db, sink, None) diff --git a/crates/test-files/fixtures/ingots/trait_ingot_check/src/foo.fe b/crates/test-files/fixtures/ingots/trait_ingot_check/src/foo.fe new file mode 100644 index 0000000000..60294b19f3 --- /dev/null +++ b/crates/test-files/fixtures/ingots/trait_ingot_check/src/foo.fe @@ -0,0 +1,9 @@ +pub struct MyS { + fn x() -> u256 { + return 10 + } +} + +pub trait Trait { + fn x() -> u256; +} \ No newline at end of file diff --git a/crates/test-files/fixtures/ingots/trait_ingot_check/src/main.fe b/crates/test-files/fixtures/ingots/trait_ingot_check/src/main.fe new file mode 100644 index 0000000000..965a80c9f1 --- /dev/null +++ b/crates/test-files/fixtures/ingots/trait_ingot_check/src/main.fe @@ -0,0 +1,13 @@ +use foo::{MyS, Trait} + +impl Trait for MyS { + fn x() -> u256 { + return 10 + } +} + +contract Foo { + pub fn main() -> u256 { + return MyS::x() + } +} diff --git a/crates/tests-legacy/src/ingots.rs b/crates/tests-legacy/src/ingots.rs index aa628fcc45..99dfe80d58 100644 --- a/crates/tests-legacy/src/ingots.rs +++ b/crates/tests-legacy/src/ingots.rs @@ -30,6 +30,13 @@ fn test_trait_no_ambiguity() { }) } +#[test] +fn test_trait_ingot_check() { + with_executor(&|mut executor| { + let _harness = deploy_ingot(&mut executor, "trait_ingot_check", "Foo", &[]); + }) +} + #[test] fn test_ingot_pub_contract() { with_executor(&|mut executor| { diff --git a/newsfragments/863.feature.md b/newsfragments/863.feature.md new file mode 100644 index 0000000000..3d02725a7f --- /dev/null +++ b/newsfragments/863.feature.md @@ -0,0 +1,8 @@ +Fixed broken trait orphan rule + +Fe has an orphan rule for Traits similar to Rust's that requires +that either the trait or the type that we are implementing the trait for +are located in the same ingot as the `impl`. This rule was implemented +incorrectly so that instead of requiring them to be in the same ingot, +they were required to be in the same module. This change fixes this +so that the orphan rule is enforced correctly.