Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added indirect impl support for inference. #4420

Merged
merged 1 commit into from
Nov 19, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions crates/cairo-lang-semantic/src/db.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,7 @@ pub trait SemanticGroup:
/// Returns the impl definition pointed to by the impl alias, or an error if it points to
/// something else.
#[salsa::invoke(items::impl_alias::impl_alias_impl_def)]
#[salsa::cycle(items::impl_alias::impl_alias_impl_def_cycle)]
fn impl_alias_impl_def(&self, impl_alias_id: ImplAliasId) -> Maybe<ImplDefId>;
/// Private query to compute data about a type alias.
#[salsa::invoke(items::impl_alias::priv_impl_alias_semantic_data)]
Expand Down
24 changes: 1 addition & 23 deletions crates/cairo-lang-semantic/src/expr/compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -606,28 +606,6 @@ fn compute_expr_function_call_semantic(
ResolvedConcreteItem::Function(function) => {
expr_function_call(ctx, function, named_args, syntax.stable_ptr().into())
}
ResolvedConcreteItem::TraitFunction(trait_function) => {
let impl_lookup_context = ctx.resolver.impl_lookup_context();
let generic_function = ctx
.resolver
.inference()
.infer_trait_generic_function(
trait_function,
&impl_lookup_context,
Some(path.stable_ptr().untyped()),
)
.map_err(|err| err.report(ctx.diagnostics, path.stable_ptr().untyped()))?;
let function_id = ctx
.resolver
.inference()
.infer_generic_function(
generic_function,
&impl_lookup_context,
Some(path.stable_ptr().untyped()),
)
.map_err(|err| err.report(ctx.diagnostics, path.stable_ptr().untyped()))?;
expr_function_call(ctx, function_id, named_args, syntax.stable_ptr().into())
}
_ => Err(ctx.diagnostics.report(
&path,
UnexpectedElement { expected: vec![ElementKind::Function], actual: (&item).into() },
Expand Down Expand Up @@ -1070,7 +1048,7 @@ fn compute_method_function_call_data(
candidate_traits,
func_name.clone(),
self_expr.stable_ptr().untyped(),
)?;
);
let trait_function_id = match candidates[..] {
[] => {
return Err(ctx
Expand Down
23 changes: 14 additions & 9 deletions crates/cairo-lang-semantic/src/items/imp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use super::functions::{
use super::generics::{semantic_generic_params, GenericArgumentHead, GenericParamsData};
use super::structure::SemanticStructEx;
use super::trt::{ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId};
use crate::corelib::{copy_trait, core_module, drop_trait};
use crate::corelib::{copy_trait, drop_trait};
use crate::db::SemanticGroup;
use crate::diagnostic::SemanticDiagnosticKind::{self, *};
use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics};
Expand Down Expand Up @@ -720,8 +720,14 @@ pub fn module_impl_ids_for_trait_filter(
uninferred_impls.push(UninferredImpl::ImplAlias(impl_alias_id));
}
for use_id in db.module_uses_ids(module_id).unwrap_or_default().iter().copied() {
if let Ok(ResolvedGenericItem::Impl(impl_def_id)) = db.use_resolved_item(use_id) {
uninferred_impls.push(UninferredImpl::Def(impl_def_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));
}
_ => {}
}
}
let mut res = Vec::new();
Expand Down Expand Up @@ -917,8 +923,7 @@ pub fn find_candidates_at_context(
}
res.insert(UninferredImpl::GenericParam(*generic_param_id));
}
let core_module = core_module(db);
for module_id in chain!(lookup_context.modules.iter().map(|x| &x.0), [&core_module]) {
for module_id in chain!(lookup_context.modules.iter().map(|x| &x.0)) {
let Ok(imps) = db.module_impl_ids_for_trait_filter(*module_id, filter.clone()) else {
continue;
};
Expand All @@ -932,12 +937,12 @@ pub fn find_candidates_at_context(
/// Checks if an impl of a trait function with a given self_ty exists.
/// This function does not change the state of the inference context.
pub fn can_infer_impl_by_self(
ctx: &mut ComputationContext<'_>,
ctx: &ComputationContext<'_>,
trait_function_id: TraitFunctionId,
self_ty: TypeId,
stable_ptr: SyntaxStablePtrId,
) -> bool {
let mut temp_inference_data = ctx.resolver.inference().temporary_clone();
let mut temp_inference_data = ctx.resolver.data.inference_data.temporary_clone();
let mut temp_inference = temp_inference_data.inference(ctx.db);
let lookup_context = ctx.resolver.impl_lookup_context();
let Some((concrete_trait_id, _)) = temp_inference.infer_concrete_trait_by_self(
Expand Down Expand Up @@ -1020,7 +1025,7 @@ pub fn filter_candidate_traits(
candidate_traits: &[TraitId],
function_name: SmolStr,
stable_ptr: SyntaxStablePtrId,
) -> Maybe<Vec<TraitFunctionId>> {
) -> Vec<TraitFunctionId> {
let mut candidates = Vec::new();
for trait_id in candidate_traits.iter().copied() {
let Ok(trait_functions) = ctx.db.trait_functions(trait_id) else {
Expand All @@ -1034,7 +1039,7 @@ pub fn filter_candidate_traits(
}
}
}
Ok(candidates)
candidates
}

// === Impl Function Declaration ===
Expand Down
29 changes: 23 additions & 6 deletions crates/cairo-lang-semantic/src/items/impl_alias.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::sync::Arc;

use cairo_lang_defs::ids::{ImplAliasId, ImplDefId, LanguageElementId, LookupItemId, ModuleItemId};
use cairo_lang_diagnostics::{Diagnostics, Maybe, ToMaybe};
use cairo_lang_diagnostics::{skip_diagnostic, Diagnostics, Maybe, ToMaybe};
use cairo_lang_proc_macros::DebugWithDb;
use cairo_lang_syntax::attribute::structured::{Attribute, AttributeListStructurize};
use cairo_lang_syntax::node::TypedSyntaxNode;
Expand Down Expand Up @@ -203,9 +203,26 @@ pub fn impl_alias_impl_def(db: &dyn SemanticGroup, impl_alias_id: ImplAliasId) -

let impl_path_syntax = impl_alias_ast.impl_path(syntax_db);

resolver
.resolve_generic_path_with_args(&mut diagnostics, &impl_path_syntax, NotFoundItemType::Impl)
.ok()
.and_then(|generic_item| try_extract_matches!(generic_item, ResolvedGenericItem::Impl))
.ok_or_else(|| diagnostics.report(&impl_path_syntax, NotAnImpl))
match resolver.resolve_generic_path_with_args(
&mut diagnostics,
&impl_path_syntax,
NotFoundItemType::Impl,
) {
Ok(ResolvedGenericItem::Impl(imp)) => Ok(imp),
Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => db.impl_alias_impl_def(impl_alias),
// Skipping diagnostics since we will get these through when resolving in the
// `priv_impl_alias_semantic_data` query.
_ => Err(skip_diagnostic()),
}
}

/// Cycle handling for [crate::db::SemanticGroup::impl_alias_impl_def].
pub fn impl_alias_impl_def_cycle(
_db: &dyn SemanticGroup,
_cycle: &[String],
_impl_alias_id: &ImplAliasId,
) -> Maybe<ImplDefId> {
// Skipping diagnostics since we will get these through when resolving in the
// `priv_impl_alias_semantic_data` query.
Err(skip_diagnostic())
}
26 changes: 26 additions & 0 deletions tests/bug_samples/indirect_impl_alias.cairo
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
trait Trait1<T> {
fn func1(value: T);
}

trait Trait2<T> {
fn func2(value: T);
}

mod impls {
impl Impl1<T, +Drop<T>> of super::Trait1<T> {
fn func1(value: T) {}
}
impl ImplAlias1 = Impl1<felt252>;
impl Impl2<T, +Drop<T>> of super::Trait2<T> {
fn func2(value: T) {}
}
impl ImplAlias2 = Impl2<felt252>;
}

use impls::ImplAlias1;
impl Impl2 = impls::ImplAlias2;

fn foo() {
Trait1::func1(0_felt252);
Trait2::func2(0_felt252);
}
1 change: 1 addition & 0 deletions tests/bug_samples/lib.cairo
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod ecdsa_completeness;
mod indirect_impl_alias;
mod issue2114;
mod issue2147;
mod issue2152;
Expand Down
Loading