Skip to content

Commit

Permalink
Use Star Impl Handling (#6765)
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomer-StarkWare authored Nov 28, 2024
1 parent 334dd97 commit 9309bba
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,13 @@ edition = "2024_07"
trait ATrait1<T> {
fn some_method(self: @T);
}
impl Felt252ATraitImpl of ATrait1<felt252> {
impl Felt252ATraitImpl1 of ATrait1<felt252> {
fn some_method(self: @felt252) {}
}
trait ATrait2<T> {
fn some_method(self: @T);
}
impl Felt252ATraitImpl of ATrait2<felt252> {
impl Felt252ATraitImpl2 of ATrait2<felt252> {
fn some_method(self: @felt252) {}
}

Expand Down
168 changes: 168 additions & 0 deletions crates/cairo-lang-semantic/src/expr/semantic_test_data/use
Original file line number Diff line number Diff line change
Expand Up @@ -1202,3 +1202,171 @@ Constant(
)

//! > expected_diagnostics

//! > ==========================================================================

//! > Trait import impl through use star.

//! > test_runner_name
test_expr_semantics(expect_diagnostics: false)

//! > crate_settings
edition = "2024_07"

//! > module_code
mod a {
pub trait MyTrait<T> {
fn foo(self: T) -> T;
}
}
mod b {
pub struct V {}
impl VMyTrait of super::a::MyTrait<V> {
fn foo(self: V) -> V {
self
}
}
}

use a::*;

//! > function_body

//! > expr_code
b::V {}.foo()

//! > expected_semantics
FunctionCall(
ExprFunctionCall {
function: test::b::VMyTrait::foo,
args: [
Value(
StructCtor(
ExprStructCtor {
concrete_struct_id: test::b::V,
members: [],
base_struct: None,
ty: test::b::V,
},
),
),
],
coupon_arg: None,
ty: test::b::V,
},
)

//! > expected_diagnostics

//! > ==========================================================================

//! > Impl import trait through use star.

//! > test_runner_name
test_expr_semantics(expect_diagnostics: false)

//! > crate_settings
edition = "2024_07"

//! > module_code
mod a {
pub trait MyTrait<T> {
fn foo(self: T) -> T;
}
}
mod b {
pub impl VMyTrait of super::a::MyTrait<super::c::V> {
fn foo(self: super::c::V) -> super::c::V {
self
}
}
}

mod c {
pub struct V {}
}

use b::*;

//! > function_body

//! > expr_code
c::V {}.foo()

//! > expected_semantics
FunctionCall(
ExprFunctionCall {
function: test::b::VMyTrait::foo,
args: [
Value(
StructCtor(
ExprStructCtor {
concrete_struct_id: test::c::V,
members: [],
base_struct: None,
ty: test::c::V,
},
),
),
],
coupon_arg: None,
ty: test::c::V,
},
)

//! > expected_diagnostics

//! > ==========================================================================

//! > Struct import impl through use star.

//! > test_runner_name
test_expr_semantics(expect_diagnostics: false)

//! > crate_settings
edition = "2024_07"

//! > module_code
pub trait MyTrait<T> {
fn foo(t: T) -> T;
}
mod b {
pub impl VMyTrait of super::MyTrait<super::c::V> {
fn foo(t: super::c::V) -> super::c::V {
t
}
}
}

mod c {
use super::b::*;
pub struct V {}
}

//! > function_body

//! > expr_code
MyTrait::foo(c::V {})

//! > expected_semantics
FunctionCall(
ExprFunctionCall {
function: test::b::VMyTrait::foo,
args: [
Value(
StructCtor(
ExprStructCtor {
concrete_struct_id: test::c::V,
members: [],
base_struct: None,
ty: test::c::V,
},
),
),
],
coupon_arg: None,
ty: test::c::V,
},
)

//! > expected_diagnostics
69 changes: 49 additions & 20 deletions crates/cairo-lang-semantic/src/items/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ use super::type_aliases::{
TypeAliasData, type_alias_generic_params_data_helper, type_alias_semantic_data_cycle_helper,
type_alias_semantic_data_helper,
};
use super::visibility::peek_visible_in;
use super::{TraitOrImplContext, resolve_trait_path};
use crate::corelib::{
CoreTraitContext, concrete_destruct_trait, concrete_drop_trait, copy_trait, core_crate,
Expand Down Expand Up @@ -1354,24 +1355,14 @@ pub fn module_impl_ids_for_trait_filter(
module_id: ModuleId,
trait_filter: TraitFilter,
) -> Maybe<Vec<UninferredImpl>> {
let mut uninferred_impls = Vec::new();
if let Ok(impl_ids) = db.module_impls_ids(module_id) {
uninferred_impls.extend(impl_ids.iter().copied().map(UninferredImpl::Def));
}
if let Ok(impl_aliases_ids) = db.module_impl_aliases_ids(module_id) {
uninferred_impls.extend(impl_aliases_ids.iter().copied().map(UninferredImpl::ImplAlias));
}
if let Ok(uses_ids) = db.module_uses_ids(module_id) {
for use_id in uses_ids.iter().copied() {
match db.use_resolved_item(use_id) {
Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
uninferred_impls.push(UninferredImpl::Def(impl_def_id));
}
Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
}
_ => {}
}
// Get the impls first from the module, do not change this order.
let mut uninferred_impls: OrderedHashSet<UninferredImpl> =
OrderedHashSet::from_iter(module_impl_ids(db, module_id, module_id)?);
for (user_module, containing_module) in &db.priv_module_use_star_modules(module_id).accessible {
if let Ok(star_module_uninferred_impls) =
module_impl_ids(db, *user_module, *containing_module)
{
uninferred_impls.extend(star_module_uninferred_impls);
}
}
let mut res = Vec::new();
Expand All @@ -1387,10 +1378,48 @@ pub fn module_impl_ids_for_trait_filter(
res.push(uninferred_impl);
}
}

Ok(res)
}

/// Returns the uninferred impls in a module.
fn module_impl_ids(
db: &dyn SemanticGroup,
user_module: ModuleId,
containing_module: ModuleId,
) -> Maybe<Vec<UninferredImpl>> {
let mut uninferred_impls = Vec::new();
for item in db.priv_module_semantic_data(containing_module)?.items.values() {
if !matches!(
item.item_id,
ModuleItemId::Impl(_) | ModuleItemId::ImplAlias(_) | ModuleItemId::Use(_)
) {
continue;
}
if !peek_visible_in(db.upcast(), item.visibility, containing_module, user_module) {
continue;
}
match item.item_id {
ModuleItemId::Impl(impl_def_id) => {
uninferred_impls.push(UninferredImpl::Def(impl_def_id));
}
ModuleItemId::ImplAlias(impl_alias_id) => {
uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
}
ModuleItemId::Use(use_id) => match db.use_resolved_item(use_id) {
Ok(ResolvedGenericItem::Impl(impl_def_id)) => {
uninferred_impls.push(UninferredImpl::Def(impl_def_id));
}
Ok(ResolvedGenericItem::GenericImplAlias(impl_alias_id)) => {
uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
}
_ => {}
},
_ => {}
}
}
Ok(uninferred_impls)
}

/// Cycle handling for [crate::db::SemanticGroup::module_impl_ids_for_trait_filter].
pub fn module_impl_ids_for_trait_filter_cycle(
_db: &dyn SemanticGroup,
Expand Down Expand Up @@ -1551,7 +1580,7 @@ impl ImplLookupContext {
}
}

/// An candidate impl for later inference.
/// A candidate impl for later inference.
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, SemanticObject)]
pub enum UninferredImpl {
Def(ImplDefId),
Expand Down
Loading

0 comments on commit 9309bba

Please sign in to comment.