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::{ResolvedConcreteItem, ResolvedGenericItem, Resolver, ResolverData};
20use crate::substitution::SemanticRewriter;
21use crate::{GenericParam, SemanticDiagnostic};
22
23#[derive(Clone, Debug, PartialEq, Eq, DebugWithDb)]
24#[debug_db(dyn SemanticGroup + 'static)]
25pub struct ImplAliasData {
26 pub diagnostics: Diagnostics<SemanticDiagnostic>,
27 pub resolved_impl: Maybe<ImplId>,
28 generic_params: Vec<GenericParam>,
29 attributes: Vec<Attribute>,
30 pub resolver_data: Arc<ResolverData>,
31}
32
33pub fn priv_impl_alias_semantic_data(
35 db: &(dyn SemanticGroup),
36 impl_alias_id: ImplAliasId,
37 in_cycle: bool,
38) -> Maybe<ImplAliasData> {
39 let lookup_item_id = LookupItemId::ModuleItem(ModuleItemId::ImplAlias(impl_alias_id));
40 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?.to_maybe()?;
41
42 let generic_params_data = db.impl_alias_generic_params_data(impl_alias_id)?;
43
44 if in_cycle {
45 impl_alias_semantic_data_cycle_helper(
46 db,
47 &impl_alias_ast,
48 lookup_item_id,
49 generic_params_data,
50 )
51 } else {
52 impl_alias_semantic_data_helper(db, &impl_alias_ast, lookup_item_id, generic_params_data)
53 }
54}
55
56pub fn impl_alias_semantic_data_helper(
58 db: &(dyn SemanticGroup),
59 impl_alias_ast: &ast::ItemImplAlias,
60 lookup_item_id: LookupItemId,
61 generic_params_data: GenericParamsData,
62) -> Maybe<ImplAliasData> {
63 let mut diagnostics = SemanticDiagnostics::default();
64 let syntax_db = db.upcast();
69 let inference_id = InferenceId::LookupItemDeclaration(lookup_item_id);
70 let mut resolver = Resolver::with_data(
71 db,
72 (*generic_params_data.resolver_data).clone_with_inference_id(db, inference_id),
73 );
74 diagnostics.extend(generic_params_data.diagnostics);
75
76 let item = resolver.resolve_concrete_path(
77 &mut diagnostics,
78 &impl_alias_ast.impl_path(syntax_db),
79 NotFoundItemType::Impl,
80 );
81 let resolved_impl = item.and_then(|item| {
82 try_extract_matches!(item, ResolvedConcreteItem::Impl)
83 .ok_or_else(|| diagnostics.report(&impl_alias_ast.impl_path(syntax_db), UnknownImpl))
84 });
85
86 let inference = &mut resolver.inference();
88 inference.finalize(&mut diagnostics, impl_alias_ast.stable_ptr().untyped());
89
90 let resolved_impl = inference.rewrite(resolved_impl).no_err();
91 let generic_params = inference.rewrite(generic_params_data.generic_params.clone()).no_err();
92
93 let attributes = impl_alias_ast.attributes(syntax_db).structurize(syntax_db);
94 let resolver_data = Arc::new(resolver.data);
95 Ok(ImplAliasData {
96 diagnostics: diagnostics.build(),
97 resolved_impl,
98 generic_params,
99 attributes,
100 resolver_data,
101 })
102}
103
104pub fn priv_impl_alias_semantic_data_cycle(
106 db: &dyn SemanticGroup,
107 _cycle: &salsa::Cycle,
108 impl_alias_id: &ImplAliasId,
109 _in_cycle: &bool,
110) -> Maybe<ImplAliasData> {
111 priv_impl_alias_semantic_data(db, *impl_alias_id, true)
112}
113
114pub fn impl_alias_semantic_data_cycle_helper(
116 db: &(dyn SemanticGroup),
117 impl_alias_ast: &ast::ItemImplAlias,
118 lookup_item_id: LookupItemId,
119 generic_params_data: GenericParamsData,
120) -> Maybe<ImplAliasData> {
121 let mut diagnostics = SemanticDiagnostics::default();
122 let syntax_db = db.upcast();
127 let err = Err(diagnostics.report(&impl_alias_ast.name(syntax_db), ImplAliasCycle));
128 let generic_params = generic_params_data.generic_params.clone();
129 diagnostics.extend(generic_params_data.diagnostics);
130 let inference_id = InferenceId::LookupItemDeclaration(lookup_item_id);
131 let attributes = impl_alias_ast.attributes(syntax_db).structurize(syntax_db);
132 Ok(ImplAliasData {
133 diagnostics: diagnostics.build(),
134 resolved_impl: err,
135 generic_params,
136 attributes,
137 resolver_data: (*generic_params_data.resolver_data)
138 .clone_with_inference_id(db, inference_id)
139 .into(),
140 })
141}
142
143pub fn impl_alias_semantic_diagnostics(
145 db: &dyn SemanticGroup,
146 impl_alias_id: ImplAliasId,
147) -> Diagnostics<SemanticDiagnostic> {
148 db.priv_impl_alias_semantic_data(impl_alias_id, false)
149 .map(|data| data.diagnostics)
150 .unwrap_or_default()
151}
152
153pub fn impl_alias_resolved_impl(
155 db: &dyn SemanticGroup,
156 impl_alias_id: ImplAliasId,
157) -> Maybe<ImplId> {
158 db.priv_impl_alias_semantic_data(impl_alias_id, false)?.resolved_impl
159}
160
161pub fn impl_alias_resolved_impl_cycle(
163 db: &dyn SemanticGroup,
164 _cycle: &salsa::Cycle,
165 impl_alias_id: &ImplAliasId,
166) -> Maybe<ImplId> {
167 db.priv_impl_alias_semantic_data(*impl_alias_id, true)?.resolved_impl
169}
170
171pub fn impl_alias_generic_params(
173 db: &dyn SemanticGroup,
174 impl_alias_id: ImplAliasId,
175) -> Maybe<Vec<GenericParam>> {
176 Ok(db.impl_alias_generic_params_data(impl_alias_id)?.generic_params)
177}
178
179pub fn impl_alias_generic_params_data(
181 db: &dyn SemanticGroup,
182 impl_alias_id: ImplAliasId,
183) -> Maybe<GenericParamsData> {
184 let module_file_id = impl_alias_id.module_file_id(db.upcast());
185 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?.to_maybe()?;
186 impl_alias_generic_params_data_helper(
187 db,
188 module_file_id,
189 &impl_alias_ast,
190 LookupItemId::ModuleItem(ModuleItemId::ImplAlias(impl_alias_id)),
191 None,
192 )
193}
194
195pub fn impl_alias_generic_params_data_helper(
197 db: &dyn SemanticGroup,
198 module_file_id: ModuleFileId,
199 impl_alias_ast: &ast::ItemImplAlias,
200 lookup_item_id: LookupItemId,
201 parent_resolver_data: Option<Arc<ResolverData>>,
202) -> Maybe<GenericParamsData> {
203 let mut diagnostics = SemanticDiagnostics::default();
204 let inference_id = InferenceId::LookupItemGenerics(lookup_item_id);
205
206 let mut resolver = match parent_resolver_data {
207 Some(parent_resolver_data) => {
208 Resolver::with_data(db, parent_resolver_data.clone_with_inference_id(db, inference_id))
209 }
210 None => Resolver::new(db, module_file_id, inference_id),
211 };
212 resolver.set_feature_config(&lookup_item_id, impl_alias_ast, &mut diagnostics);
213 let generic_params = semantic_generic_params(
214 db,
215 &mut diagnostics,
216 &mut resolver,
217 module_file_id,
218 &impl_alias_ast.generic_params(db.upcast()),
219 );
220
221 let inference = &mut resolver.inference();
222 inference.finalize(&mut diagnostics, impl_alias_ast.stable_ptr().untyped());
223
224 let generic_params = inference.rewrite(generic_params).no_err();
225 let resolver_data = Arc::new(resolver.data);
226 Ok(GenericParamsData { diagnostics: diagnostics.build(), generic_params, resolver_data })
227}
228
229pub fn impl_alias_resolver_data(
231 db: &dyn SemanticGroup,
232 impl_alias_id: ImplAliasId,
233) -> Maybe<Arc<ResolverData>> {
234 Ok(db.priv_impl_alias_semantic_data(impl_alias_id, false)?.resolver_data)
235}
236
237pub fn impl_alias_resolver_data_cycle(
239 db: &dyn SemanticGroup,
240 _cycle: &salsa::Cycle,
241 impl_alias_id: &ImplAliasId,
242) -> Maybe<Arc<ResolverData>> {
243 impl_alias_resolver_data(db, *impl_alias_id)
245}
246
247pub fn impl_alias_attributes(
249 db: &dyn SemanticGroup,
250 impl_alias_id: ImplAliasId,
251) -> Maybe<Vec<Attribute>> {
252 Ok(db.priv_impl_alias_semantic_data(impl_alias_id, false)?.attributes)
253}
254
255pub fn impl_alias_impl_def(db: &dyn SemanticGroup, impl_alias_id: ImplAliasId) -> Maybe<ImplDefId> {
257 let module_file_id = impl_alias_id.module_file_id(db.upcast());
258 let mut diagnostics = SemanticDiagnostics::default();
259 let impl_alias_ast = db.module_impl_alias_by_id(impl_alias_id)?.to_maybe()?;
260 let inference_id = InferenceId::ImplAliasImplDef(impl_alias_id);
261
262 let mut resolver = Resolver::new(db, module_file_id, inference_id);
263 resolver.set_feature_config(&impl_alias_id, &impl_alias_ast, &mut diagnostics);
264
265 let impl_path_syntax = impl_alias_ast.impl_path(db.upcast());
266
267 match resolver.resolve_generic_path_with_args(
268 &mut diagnostics,
269 &impl_path_syntax,
270 NotFoundItemType::Impl,
271 None,
272 ) {
273 Ok(ResolvedGenericItem::Impl(imp)) => Ok(imp),
274 Ok(ResolvedGenericItem::GenericImplAlias(impl_alias)) => db.impl_alias_impl_def(impl_alias),
275 _ => Err(skip_diagnostic()),
278 }
279}
280
281pub fn impl_alias_impl_def_cycle(
283 _db: &dyn SemanticGroup,
284 _cycle: &salsa::Cycle,
285 _impl_alias_id: &ImplAliasId,
286) -> Maybe<ImplDefId> {
287 Err(skip_diagnostic())
290}