cairo_lang_semantic/items/
impl_alias.rs1use std::sync::Arc;
2
3use cairo_lang_defs::ids::{
4 ImplAliasId, ImplDefId, LanguageElementId, LookupItemId, ModuleFileId, ModuleItemId,
5};
6use cairo_lang_diagnostics::{Diagnostics, Maybe, ToMaybe, skip_diagnostic};
7use cairo_lang_proc_macros::DebugWithDb;
8use cairo_lang_syntax::attribute::structured::{Attribute, AttributeListStructurize};
9use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode, ast};
10use cairo_lang_utils::try_extract_matches;
11
12use super::generics::{GenericParamsData, semantic_generic_params};
13use super::imp::ImplId;
14use crate::db::SemanticGroup;
15use crate::diagnostic::SemanticDiagnosticKind::*;
16use crate::diagnostic::{NotFoundItemType, SemanticDiagnostics, SemanticDiagnosticsBuilder};
17use crate::expr::inference::InferenceId;
18use crate::expr::inference::canonic::ResultNoErrEx;
19use crate::resolve::{
20 ResolutionContext, ResolvedConcreteItem, ResolvedGenericItem, Resolver, ResolverData,
21};
22use crate::substitution::SemanticRewriter;
23use crate::{GenericParam, SemanticDiagnostic};
24
25#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
26#[debug_db(dyn SemanticGroup + 'static)]
27pub struct ImplAliasData {
28 pub diagnostics: Diagnostics<SemanticDiagnostic>,
29 pub resolved_impl: Maybe<ImplId>,
30 generic_params: Vec<GenericParam>,
31 attributes: Vec<Attribute>,
32 pub resolver_data: Arc<ResolverData>,
33}
34
35pub fn priv_impl_alias_semantic_data(
37 db: &dyn SemanticGroup,
38 impl_alias_id: ImplAliasId,
39 in_cycle: bool,
40) -> Maybe<ImplAliasData> {
41 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::ImplAlias(impl_alias_id));
42 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?.to_maybe()?;
43
44 let generic_params_data = db.impl_alias_generic_params_data(impl_alias_id)?;
45
46 if in_cycle {
47 impl_alias_semantic_data_cycle_helper(
48 db,
49 &impl_alias_ast,
50 lookup_item_id,
51 generic_params_data,
52 )
53 } else {
54 impl_alias_semantic_data_helper(db, &impl_alias_ast, lookup_item_id, generic_params_data)
55 }
56}
57
58pub fn impl_alias_semantic_data_helper(
60 db: &dyn SemanticGroup,
61 impl_alias_ast: &ast::ItemImplAlias,
62 lookup_item_id: LookupItemId,
63 generic_params_data: GenericParamsData,
64) -> Maybe<ImplAliasData> {
65 let mut diagnostics = SemanticDiagnostics::default();
66 let inference_id = InferenceId::LookupItemDeclaration(lookup_item_id);
71 let mut resolver = Resolver::with_data(
72 db,
73 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
74 );
75 diagnostics.extend(generic_params_data.diagnostics);
76
77 let item = resolver.resolve_concrete_path(
78 &mut diagnostics,
79 &impl_alias_ast.impl_path(db),
80 NotFoundItemType::Impl,
81 );
82 let resolved_impl = item.and_then(|item| {
83 try_extract_matches!(item, ResolvedConcreteItem::Impl).ok_or_else(|| {
84 diagnostics.report(impl_alias_ast.impl_path(db).stable_ptr(db), UnknownImpl)
85 })
86 });
87
88 let inference = &mut resolver.inference();
90 inference.finalize(&mut diagnostics, impl_alias_ast.stable_ptr(db).untyped());
91
92 let resolved_impl = inference.rewrite(resolved_impl).no_err();
93 let generic_params = inference.rewrite(generic_params_data.generic_params).no_err();
94
95 let attributes = impl_alias_ast.attributes(db).structurize(db);
96 let resolver_data = Arc::new(resolver.data);
97 Ok(ImplAliasData {
98 diagnostics: diagnostics.build(),
99 resolved_impl,
100 generic_params,
101 attributes,
102 resolver_data,
103 })
104}
105
106pub fn priv_impl_alias_semantic_data_cycle(
108 db: &dyn SemanticGroup,
109 _cycle: &salsa::Cycle,
110 impl_alias_id: &ImplAliasId,
111 _in_cycle: &bool,
112) -> Maybe<ImplAliasData> {
113 priv_impl_alias_semantic_data(db, *impl_alias_id, true)
114}
115
116pub fn impl_alias_semantic_data_cycle_helper(
118 db: &dyn SemanticGroup,
119 impl_alias_ast: &ast::ItemImplAlias,
120 lookup_item_id: LookupItemId,
121 generic_params_data: GenericParamsData,
122) -> Maybe<ImplAliasData> {
123 let mut diagnostics = SemanticDiagnostics::default();
124 let err = Err(diagnostics.report(impl_alias_ast.name(db).stable_ptr(db), ImplAliasCycle));
129 let generic_params = generic_params_data.generic_params.clone();
130 diagnostics.extend(generic_params_data.diagnostics);
131 let inference_id = InferenceId::LookupItemDeclaration(lookup_item_id);
132 let attributes = impl_alias_ast.attributes(db).structurize(db);
133 Ok(ImplAliasData {
134 diagnostics: diagnostics.build(),
135 resolved_impl: err,
136 generic_params,
137 attributes,
138 resolver_data: (*generic_params_data.resolver_data)
139 .clone_with_inference_id(db, inference_id)
140 .into(),
141 })
142}
143
144pub fn impl_alias_semantic_diagnostics(
146 db: &dyn SemanticGroup,
147 impl_alias_id: ImplAliasId,
148) -> Diagnostics<SemanticDiagnostic> {
149 db.priv_impl_alias_semantic_data(impl_alias_id, false)
150 .map(|data| data.diagnostics)
151 .unwrap_or_default()
152}
153
154pub fn impl_alias_resolved_impl(
156 db: &dyn SemanticGroup,
157 impl_alias_id: ImplAliasId,
158) -> Maybe<ImplId> {
159 db.priv_impl_alias_semantic_data(impl_alias_id, false)?.resolved_impl
160}
161
162pub fn impl_alias_resolved_impl_cycle(
164 db: &dyn SemanticGroup,
165 _cycle: &salsa::Cycle,
166 impl_alias_id: &ImplAliasId,
167) -> Maybe<ImplId> {
168 db.priv_impl_alias_semantic_data(*impl_alias_id, true)?.resolved_impl
170}
171
172pub fn impl_alias_generic_params(
174 db: &dyn SemanticGroup,
175 impl_alias_id: ImplAliasId,
176) -> Maybe<Vec<GenericParam>> {
177 Ok(db.impl_alias_generic_params_data(impl_alias_id)?.generic_params)
178}
179
180pub fn impl_alias_generic_params_data(
182 db: &dyn SemanticGroup,
183 impl_alias_id: ImplAliasId,
184) -> Maybe<GenericParamsData> {
185 let module_file_id = impl_alias_id.module_file_id(db);
186 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?.to_maybe()?;
187 impl_alias_generic_params_data_helper(
188 db,
189 module_file_id,
190 &impl_alias_ast,
191 LookupItemId::ModuleItem(ModuleItemId::ImplAlias(impl_alias_id)),
192 None,
193 )
194}
195
196pub fn impl_alias_generic_params_data_helper(
198 db: &dyn SemanticGroup,
199 module_file_id: ModuleFileId,
200 impl_alias_ast: &ast::ItemImplAlias,
201 lookup_item_id: LookupItemId,
202 parent_resolver_data: Option<Arc<ResolverData>>,
203) -> Maybe<GenericParamsData> {
204 let mut diagnostics = SemanticDiagnostics::default();
205 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
206
207 let mut resolver = match parent_resolver_data {
208 Some(parent_resolver_data) => {
209 Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id))
210 }
211 None => Resolver::new(db, module_file_id, inference_id),
212 };
213 resolver.set_feature_config(&lookup_item_id, impl_alias_ast, &mut diagnostics);
214 let generic_params = semantic_generic_params(
215 db,
216 &mut diagnostics,
217 &mut resolver,
218 module_file_id,
219 &impl_alias_ast.generic_params(db),
220 );
221
222 let inference = &mut resolver.inference();
223 inference.finalize(&mut diagnostics, impl_alias_ast.stable_ptr(db).untyped());
224
225 let generic_params = inference.rewrite(generic_params).no_err();
226 let resolver_data = Arc::new(resolver.data);
227 Ok(GenericParamsData { diagnostics: diagnostics.build(), generic_params, resolver_data })
228}
229
230pub fn impl_alias_resolver_data(
232 db: &dyn SemanticGroup,
233 impl_alias_id: ImplAliasId,
234) -> Maybe<Arc<ResolverData>> {
235 Ok(db.priv_impl_alias_semantic_data(impl_alias_id, false)?.resolver_data)
236}
237
238pub fn impl_alias_resolver_data_cycle(
240 db: &dyn SemanticGroup,
241 _cycle: &salsa::Cycle,
242 impl_alias_id: &ImplAliasId,
243) -> Maybe<Arc<ResolverData>> {
244 impl_alias_resolver_data(db, *impl_alias_id)
246}
247
248pub fn impl_alias_attributes(
250 db: &dyn SemanticGroup,
251 impl_alias_id: ImplAliasId,
252) -> Maybe<Vec<Attribute>> {
253 Ok(db.priv_impl_alias_semantic_data(impl_alias_id, false)?.attributes)
254}
255
256pub fn impl_alias_impl_def(db: &dyn SemanticGroup, impl_alias_id: ImplAliasId) -> Maybe<ImplDefId> {
258 let module_file_id = impl_alias_id.module_file_id(db);
259 let mut diagnostics = SemanticDiagnostics::default();
260 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?.to_maybe()?;
261 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
262
263 let mut resolver = Resolver::new(db, module_file_id, inference_id);
264 resolver.set_feature_config(&impl_alias_id, &impl_alias_ast, &mut diagnostics);
265
266 let impl_path_syntax = impl_alias_ast.impl_path(db);
267
268 match resolver.resolve_generic_path_with_args(
269 &mut diagnostics,
270 &impl_path_syntax,
271 NotFoundItemType::Impl,
272 ResolutionContext::Default,
273 ) {
274 Ok(ResolvedGenericItem::Impl(imp)) => Ok(imp),
275 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => db.impl_alias_impl_def(impl_alias),
276 _ => Err(skip_diagnostic()),
279 }
280}
281
282pub fn impl_alias_impl_def_cycle(
284 _db: &dyn SemanticGroup,
285 _cycle: &salsa::Cycle,
286 _impl_alias_id: &ImplAliasId,
287) -> Maybe<ImplDefId> {
288 Err(skip_diagnostic())
291}