Skip to content

Commit

Permalink
Fix overly strict trait orphan rule
Browse files Browse the repository at this point in the history
  • Loading branch information
cburgdorf committed Mar 29, 2023
1 parent e63e1b4 commit 2ede8a3
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 7 deletions.
16 changes: 9 additions & 7 deletions crates/analyzer/src/namespace/items.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1789,12 +1789,14 @@ impl ImplId {
&self,
db: &dyn AnalyzerDb,
sink: &mut impl DiagnosticSink,
type_module: Option<ModuleId>,
type_ingot: Option<IngotId>,
) {
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 {
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
pub struct MyS {
fn x() -> u256 {
return 10
}
}

pub trait Trait {
fn x() -> u256;
}
13 changes: 13 additions & 0 deletions crates/test-files/fixtures/ingots/trait_ingot_check/src/main.fe
Original file line number Diff line number Diff line change
@@ -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()
}
}
7 changes: 7 additions & 0 deletions crates/tests-legacy/src/ingots.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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| {
Expand Down
8 changes: 8 additions & 0 deletions newsfragments/863.feature.md
Original file line number Diff line number Diff line change
@@ -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.

0 comments on commit 2ede8a3

Please sign in to comment.