diff --git a/crates/cairo-lang-semantic/src/db.rs b/crates/cairo-lang-semantic/src/db.rs index 59f63b6900b..02e7b390371 100644 --- a/crates/cairo-lang-semantic/src/db.rs +++ b/crates/cairo-lang-semantic/src/db.rs @@ -371,9 +371,11 @@ pub trait SemanticGroup: ) -> Diagnostics; /// Returns the generic parameters of a trait. #[salsa::invoke(items::trt::trait_generic_params)] + #[salsa::cycle(items::trt::trait_generic_params_cycle)] fn trait_generic_params(&self, trait_id: TraitId) -> Maybe>; /// Returns the generic parameters data of a trait. #[salsa::invoke(items::trt::trait_generic_params_data)] + #[salsa::cycle(items::trt::trait_generic_params_data_cycle)] fn trait_generic_params_data(&self, trait_id: TraitId) -> Maybe; /// Returns the attributes of a trait. #[salsa::invoke(items::trt::trait_attributes)] diff --git a/crates/cairo-lang-semantic/src/items/enm.rs b/crates/cairo-lang-semantic/src/items/enm.rs index 5ec57b7d78c..08eafbba247 100644 --- a/crates/cairo-lang-semantic/src/items/enm.rs +++ b/crates/cairo-lang-semantic/src/items/enm.rs @@ -114,7 +114,7 @@ pub fn enum_generic_params_data( &mut resolver, module_file_id, &enum_ast.generic_params(db.upcast()), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, enum_ast.stable_ptr().untyped()); diff --git a/crates/cairo-lang-semantic/src/items/extern_function.rs b/crates/cairo-lang-semantic/src/items/extern_function.rs index 900ebd71e19..6bf1b669bed 100644 --- a/crates/cairo-lang-semantic/src/items/extern_function.rs +++ b/crates/cairo-lang-semantic/src/items/extern_function.rs @@ -86,7 +86,7 @@ pub fn extern_function_declaration_generic_params_data( &mut resolver, module_file_id, &declaration.generic_params(syntax_db), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, extern_function_syntax.stable_ptr().untyped()); diff --git a/crates/cairo-lang-semantic/src/items/extern_type.rs b/crates/cairo-lang-semantic/src/items/extern_type.rs index 175149e9009..d4b5efe41bc 100644 --- a/crates/cairo-lang-semantic/src/items/extern_type.rs +++ b/crates/cairo-lang-semantic/src/items/extern_type.rs @@ -70,7 +70,7 @@ pub fn extern_type_declaration_generic_params_data( &mut resolver, module_file_id, &extern_type_syntax.generic_params(db.upcast()), - )?; + ); if let Some(param) = generic_params.iter().find(|param| param.kind() == GenericKind::Impl) { diagnostics.report( param.stable_ptr(db.upcast()).untyped(), diff --git a/crates/cairo-lang-semantic/src/items/free_function.rs b/crates/cairo-lang-semantic/src/items/free_function.rs index 4ba21eeede9..ec7725bf26b 100644 --- a/crates/cairo-lang-semantic/src/items/free_function.rs +++ b/crates/cairo-lang-semantic/src/items/free_function.rs @@ -97,7 +97,7 @@ pub fn free_function_generic_params_data( &mut resolver, module_file_id, &declaration.generic_params(syntax_db), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, free_function_syntax.stable_ptr().untyped()); diff --git a/crates/cairo-lang-semantic/src/items/generics.rs b/crates/cairo-lang-semantic/src/items/generics.rs index d7bcbd7d446..4724e531486 100644 --- a/crates/cairo-lang-semantic/src/items/generics.rs +++ b/crates/cairo-lang-semantic/src/items/generics.rs @@ -195,7 +195,7 @@ pub struct GenericParamImpl { #[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)] #[debug_db(dyn SemanticGroup + 'static)] pub struct GenericParamData { - pub generic_param: GenericParam, + pub generic_param: Maybe, pub diagnostics: Diagnostics, pub resolver_data: Arc, } @@ -216,7 +216,7 @@ pub fn generic_param_semantic( db: &dyn SemanticGroup, generic_param_id: GenericParamId, ) -> Maybe { - Ok(db.priv_generic_param_data(generic_param_id)?.generic_param) + db.priv_generic_param_data(generic_param_id)?.generic_param } /// Query implementation of [crate::db::SemanticGroup::generic_param_diagnostics]. @@ -329,7 +329,7 @@ pub fn priv_generic_param_data( let param_semantic = inference.rewrite(param_semantic).no_err(); let resolver_data = Arc::new(resolver.data); Ok(GenericParamData { - generic_param: param_semantic, + generic_param: Ok(param_semantic), diagnostics: diagnostics.build(), resolver_data, }) @@ -342,10 +342,17 @@ pub fn priv_generic_param_data_cycle( generic_param_id: &GenericParamId, ) -> Maybe { let mut diagnostics = SemanticDiagnostics::default(); - Err(diagnostics.report( - generic_param_id.stable_ptr(db.upcast()).untyped(), - SemanticDiagnosticKind::ImplRequirementCycle, - )) + Ok(GenericParamData { + generic_param: Err(diagnostics.report( + generic_param_id.stable_ptr(db.upcast()).untyped(), + SemanticDiagnosticKind::ImplRequirementCycle, + )), + diagnostics: diagnostics.build(), + resolver_data: Arc::new(ResolverData::new( + generic_param_id.module_file_id(db.upcast()), + InferenceId::GenericParam(*generic_param_id), + )), + }) } // --- Helpers --- @@ -372,26 +379,25 @@ pub fn semantic_generic_params( resolver: &mut Resolver<'_>, module_file_id: ModuleFileId, generic_params: &ast::OptionWrappedGenericParamList, -) -> Maybe> { +) -> Vec { let syntax_db = db.upcast(); - let res = match generic_params { - syntax::node::ast::OptionWrappedGenericParamList::Empty(_) => Ok(vec![]), + match generic_params { + syntax::node::ast::OptionWrappedGenericParamList::Empty(_) => vec![], syntax::node::ast::OptionWrappedGenericParamList::WrappedGenericParamList(syntax) => syntax .generic_params(syntax_db) .elements(syntax_db) .iter() - .map(|param_syntax| { + .filter_map(|param_syntax| { let generic_param_id = GenericParamLongId(module_file_id, param_syntax.stable_ptr()).intern(db); - let generic_param_data = db.priv_generic_param_data(generic_param_id)?; + let generic_param_data = db.priv_generic_param_data(generic_param_id).ok()?; let generic_param = generic_param_data.generic_param; diagnostics.extend(generic_param_data.diagnostics); resolver.add_generic_param(generic_param_id); - Ok(generic_param) + generic_param.ok() }) - .collect::, _>>(), - }; - res + .collect(), + } } /// Returns true if negative impls are enabled in the module. diff --git a/crates/cairo-lang-semantic/src/items/imp.rs b/crates/cairo-lang-semantic/src/items/imp.rs index 0c7a69dfe5e..ec54a22a1f4 100644 --- a/crates/cairo-lang-semantic/src/items/imp.rs +++ b/crates/cairo-lang-semantic/src/items/imp.rs @@ -382,7 +382,7 @@ pub fn impl_def_generic_params_data( &mut resolver, module_file_id, &impl_ast.generic_params(db.upcast()), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, impl_ast.stable_ptr().untyped()); @@ -2613,7 +2613,7 @@ pub fn priv_impl_function_generic_params_data( &mut resolver, module_file_id, &declaration.generic_params(syntax_db), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, function_syntax.stable_ptr().untyped()); diff --git a/crates/cairo-lang-semantic/src/items/impl_alias.rs b/crates/cairo-lang-semantic/src/items/impl_alias.rs index df8aa1e19b9..917705e237f 100644 --- a/crates/cairo-lang-semantic/src/items/impl_alias.rs +++ b/crates/cairo-lang-semantic/src/items/impl_alias.rs @@ -209,7 +209,7 @@ pub fn impl_alias_generic_params_data_helper( &mut resolver, module_file_id, &impl_alias_ast.generic_params(db.upcast()), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, impl_alias_ast.stable_ptr().untyped()); diff --git a/crates/cairo-lang-semantic/src/items/structure.rs b/crates/cairo-lang-semantic/src/items/structure.rs index 87ab6a48bf5..10545eaefe2 100644 --- a/crates/cairo-lang-semantic/src/items/structure.rs +++ b/crates/cairo-lang-semantic/src/items/structure.rs @@ -120,7 +120,7 @@ pub fn struct_generic_params_data( &mut resolver, module_file_id, &struct_ast.generic_params(db.upcast()), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, struct_ast.stable_ptr().untyped()); diff --git a/crates/cairo-lang-semantic/src/items/tests/trait b/crates/cairo-lang-semantic/src/items/tests/trait index a42f417c6ac..5a98d868432 100644 --- a/crates/cairo-lang-semantic/src/items/tests/trait +++ b/crates/cairo-lang-semantic/src/items/tests/trait @@ -1247,3 +1247,58 @@ fn bar(x: A) -> A { } //! > expected_diagnostics + +//! > ========================================================================== + +//! > trait cycle of generics. + +//! > test_runner_name +test_function_diagnostics(expect_diagnostics: *) + +//! > function +fn foo() -> felt252 { + 2 +} + +//! > function_name +foo + +//! > module_code +pub trait Tr<+Tr> {} + +//! > expected_diagnostics +error: Cycle detected while resolving generic param. Try specifying the generic impl parameter explicitly to break the cycle. + --> lib.cairo:1:14 +pub trait Tr<+Tr> {} + ^*^ + +//! > ========================================================================== + +//! > cycle with anonymous impl with impl alias instead of trait. + +//! > test_runner_name +test_function_diagnostics(expect_diagnostics: *) + +//! > function +fn foo() -> felt252 { + 2 +} + +//! > function_name +foo + +//! > module_code +trait Tr {} +impl I0 of Tr {} +impl Ifelt = I0; + +//! > expected_diagnostics +error: Trait not found. + --> lib.cairo:2:13 +impl I0 of Tr {} + ^******^ + +error: Cycle detected while resolving 'impls alias' items. + --> lib.cairo:3:6 +impl Ifelt = I0; + ^***^ diff --git a/crates/cairo-lang-semantic/src/items/trt.rs b/crates/cairo-lang-semantic/src/items/trt.rs index f3883f926fc..36bd5a9c5b1 100644 --- a/crates/cairo-lang-semantic/src/items/trt.rs +++ b/crates/cairo-lang-semantic/src/items/trt.rs @@ -343,6 +343,15 @@ pub fn trait_semantic_declaration_diagnostics( pub fn trait_generic_params(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe> { Ok(db.trait_generic_params_data(trait_id)?.generic_params) } +/// Cycle handling for [crate::db::SemanticGroup::trait_generic_params]. +pub fn trait_generic_params_cycle( + db: &dyn SemanticGroup, + _cycle: &[String], + trait_id: &TraitId, +) -> Maybe> { + // Forwarding cycle handling to `priv_generic_param_data` handler. + trait_generic_params(db, *trait_id) +} /// Query implementation of [crate::db::SemanticGroup::trait_generic_params_data]. pub fn trait_generic_params_data( @@ -365,7 +374,7 @@ pub fn trait_generic_params_data( &mut resolver, module_file_id, &trait_ast.generic_params(syntax_db), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, trait_ast.stable_ptr().untyped()); @@ -374,7 +383,15 @@ pub fn trait_generic_params_data( let resolver_data = Arc::new(resolver.data); Ok(GenericParamsData { diagnostics: diagnostics.build(), generic_params, resolver_data }) } - +/// Cycle handling for [crate::db::SemanticGroup::trait_generic_params_data]. +pub fn trait_generic_params_data_cycle( + db: &dyn SemanticGroup, + _cycle: &[String], + trait_id: &TraitId, +) -> Maybe { + // Forwarding cycle handling to `priv_generic_param_data` handler. + trait_generic_params_data(db, *trait_id) +} /// Query implementation of [crate::db::SemanticGroup::trait_attributes]. pub fn trait_attributes(db: &dyn SemanticGroup, trait_id: TraitId) -> Maybe> { Ok(db.priv_trait_declaration_data(trait_id)?.attributes) @@ -788,7 +805,7 @@ pub fn priv_trait_type_generic_params_data( &mut resolver, module_file_id, &generic_params_node, - )?; + ); let type_generic_params = resolver.inference().rewrite(type_generic_params).no_err(); // TODO(yuval): support generics in impls (including validation), then remove this. @@ -1085,7 +1102,7 @@ pub fn priv_trait_function_generic_params_data( &mut resolver, module_file_id, &declaration.generic_params(syntax_db), - )?; + ); let function_generic_params = resolver.inference().rewrite(function_generic_params).no_err(); let resolver_data = Arc::new(resolver.data); Ok(GenericParamsData { diff --git a/crates/cairo-lang-semantic/src/items/type_aliases.rs b/crates/cairo-lang-semantic/src/items/type_aliases.rs index cff00aa1b7f..5c5fa3fa5a2 100644 --- a/crates/cairo-lang-semantic/src/items/type_aliases.rs +++ b/crates/cairo-lang-semantic/src/items/type_aliases.rs @@ -50,7 +50,7 @@ pub fn type_alias_generic_params_data_helper( &mut resolver, module_file_id, &type_alias_ast.generic_params(db.upcast()), - )?; + ); let inference = &mut resolver.inference(); inference.finalize(&mut diagnostics, type_alias_ast.stable_ptr().untyped());