1use std::sync::Arc;
2
3use cairo_lang_defs::ids::{
4 EnumId, ExternFunctionId, GenericTypeId, ImplDefId, ModuleId, ModuleItemId,
5 NamedLanguageElementId, TraitFunctionId, TraitId,
6};
7use cairo_lang_diagnostics::{Maybe, ToOption};
8use cairo_lang_filesystem::ids::{CrateId, SmolStrId};
9use cairo_lang_syntax::node::ast::{self, BinaryOperator, UnaryOperator};
10use cairo_lang_syntax::node::ids::SyntaxStablePtrId;
11use cairo_lang_utils::{Intern, OptionFrom, extract_matches, require, try_extract_matches};
12use itertools::Itertools;
13use num_bigint::BigInt;
14use num_traits::{Num, Signed, ToPrimitive, Zero};
15use salsa::Database;
16
17use crate::diagnostic::SemanticDiagnosticKind;
18use crate::expr::compute::ComputationContext;
19use crate::expr::inference::Inference;
20use crate::helper::ModuleHelper;
21use crate::items::constant::{ConstValue, ConstValueId};
22use crate::items::enm::{EnumSemantic, SemanticEnumEx};
23use crate::items::functions::{GenericFunctionId, ImplGenericFunctionId};
24use crate::items::imp::{ImplLongId, ImplSemantic};
25use crate::items::module::ModuleSemantic;
26use crate::items::module_type_alias::ModuleTypeAliasSemantic;
27use crate::items::trt::{
28 ConcreteTraitGenericFunctionId, ConcreteTraitGenericFunctionLongId, ConcreteTraitId,
29 TraitSemantic,
30};
31use crate::items::us::SemanticUseEx;
32use crate::resolve::ResolvedGenericItem;
33use crate::types::{ConcreteEnumLongId, ConcreteExternTypeLongId};
34use crate::{
35 ConcreteEnumId, ConcreteFunction, ConcreteImplLongId, ConcreteTypeId, ConcreteVariant, Expr,
36 ExprId, ExprTuple, FunctionId, FunctionLongId, GenericArgumentId, TypeId, TypeLongId, semantic,
37};
38
39pub fn core_module(db: &dyn Database) -> ModuleId<'_> {
41 let core_crate = db.core_crate();
42 ModuleId::CrateRoot(core_crate)
43}
44
45#[salsa::tracked]
47pub fn core_module_tracked(db: &dyn Database) -> ModuleId<'_> {
48 core_module(db)
49}
50
51pub fn get_submodule<'db>(
53 db: &'db dyn Database,
54 base_module: ModuleId<'db>,
55 submodule_name: SmolStrId<'db>,
56) -> Option<ModuleId<'db>> {
57 let module_item_id = db.module_item_by_name(base_module, submodule_name).ok()??;
58 if let ModuleItemId::Submodule(id) = module_item_id {
59 Some(ModuleId::Submodule(id))
60 } else {
61 None
62 }
63}
64
65pub fn core_submodule<'db>(db: &'db dyn Database, submodule_name: SmolStrId<'db>) -> ModuleId<'db> {
68 get_submodule(db, core_module(db), submodule_name)
69 .unwrap_or_else(|| panic!("`{}` is not a core submodule.", submodule_name.long(db)))
70}
71
72pub fn core_crate(db: &dyn Database) -> CrateId<'_> {
74 CrateId::core(db)
75}
76
77#[salsa::tracked]
79pub fn core_crate_tracked(db: &dyn Database) -> CrateId<'_> {
80 core_crate(db)
81}
82
83pub fn bounded_int_ty<'db>(db: &'db dyn Database, min: BigInt, max: BigInt) -> TypeId<'db> {
85 let internal = core_submodule(db, SmolStrId::from(db, "internal"));
86 let bounded_int = get_submodule(db, internal, SmolStrId::from(db, "bounded_int"))
87 .expect("Could not find bounded_int submodule in corelib.");
88 let felt252_ty = db.core_info().felt252;
89 let lower_id = ConstValue::Int(min, felt252_ty).intern(db);
90 let upper_id = ConstValue::Int(max, felt252_ty).intern(db);
91 try_get_ty_by_name(
92 db,
93 bounded_int,
94 SmolStrId::from(db, "BoundedInt"),
95 vec![GenericArgumentId::Constant(lower_id), GenericArgumentId::Constant(upper_id)],
96 )
97 .expect("could not find")
98}
99
100pub fn core_nonzero_ty<'db>(db: &'db dyn Database, inner_type: TypeId<'db>) -> TypeId<'db> {
101 get_ty_by_name(
102 db,
103 core_submodule(db, SmolStrId::from(db, "zeroable")),
104 SmolStrId::from(db, "NonZero"),
105 vec![GenericArgumentId::Type(inner_type)],
106 )
107}
108
109pub fn core_result_ty<'db>(
110 db: &'db dyn Database,
111 ok_type: TypeId<'db>,
112 err_type: TypeId<'db>,
113) -> TypeId<'db> {
114 TypeLongId::Concrete(ConcreteTypeId::Enum(
115 ConcreteEnumLongId {
116 enum_id: db.core_info().result,
117 generic_args: vec![GenericArgumentId::Type(ok_type), GenericArgumentId::Type(err_type)],
118 }
119 .intern(db),
120 ))
121 .intern(db)
122}
123
124pub fn core_option_ty<'db>(db: &'db dyn Database, some_type: TypeId<'db>) -> TypeId<'db> {
125 TypeLongId::Concrete(ConcreteTypeId::Enum(
126 ConcreteEnumLongId {
127 enum_id: db.core_info().option,
128 generic_args: vec![GenericArgumentId::Type(some_type)],
129 }
130 .intern(db),
131 ))
132 .intern(db)
133}
134
135pub fn core_box_ty<'db>(db: &'db dyn Database, inner_type: TypeId<'db>) -> TypeId<'db> {
136 get_ty_by_name(
137 db,
138 core_submodule(db, SmolStrId::from(db, "box")),
139 SmolStrId::from(db, "Box"),
140 vec![GenericArgumentId::Type(inner_type)],
141 )
142}
143
144pub fn core_array_felt252_ty<'db>(db: &'db dyn Database) -> TypeId<'db> {
145 get_core_ty_by_name(
146 db,
147 SmolStrId::from(db, "Array"),
148 vec![GenericArgumentId::Type(db.core_info().felt252)],
149 )
150}
151
152pub fn try_get_core_ty_by_name<'db>(
153 db: &'db dyn Database,
154 name: SmolStrId<'db>,
155 generic_args: Vec<GenericArgumentId<'db>>,
156) -> Result<TypeId<'db>, SemanticDiagnosticKind<'db>> {
157 try_get_ty_by_name(db, db.core_module(), name, generic_args)
158}
159
160pub fn try_get_ty_by_name<'db>(
161 db: &'db dyn Database,
162 module: ModuleId<'db>,
163 name: SmolStrId<'db>,
164 generic_args: Vec<GenericArgumentId<'db>>,
165) -> Result<TypeId<'db>, SemanticDiagnosticKind<'db>> {
166 let module_item_id = db
168 .module_item_by_name(module, name)
169 .map_err(|_| SemanticDiagnosticKind::UnknownType)?
170 .ok_or(SemanticDiagnosticKind::UnknownType)?;
171 let generic_type = match module_item_id {
172 ModuleItemId::Use(use_id) => {
173 db.use_resolved_item(use_id).to_option().and_then(|resolved_generic_item| {
174 try_extract_matches!(resolved_generic_item, ResolvedGenericItem::GenericType)
175 })
176 }
177 ModuleItemId::TypeAlias(module_type_alias_id) => {
178 let ty = db
179 .module_type_alias_resolved_type(module_type_alias_id)
180 .expect("Could not find type alias.");
181 assert!(
182 db.module_type_alias_generic_params(module_type_alias_id).unwrap().is_empty(),
183 "Cannot get type aliases with params from corelib."
184 );
185 return Ok(ty);
186 }
187 _ => GenericTypeId::option_from(module_item_id),
188 }
189 .ok_or(SemanticDiagnosticKind::NotAType)?;
190
191 Ok(semantic::TypeLongId::Concrete(semantic::ConcreteTypeId::new(
192 db,
193 generic_type,
194 generic_args,
195 ))
196 .intern(db))
197}
198
199pub fn get_core_ty_by_name<'db>(
200 db: &'db dyn Database,
201 name: SmolStrId<'db>,
202 generic_args: Vec<GenericArgumentId<'db>>,
203) -> TypeId<'db> {
204 try_get_core_ty_by_name(db, name, generic_args).unwrap()
205}
206
207pub fn get_ty_by_name<'db>(
208 db: &'db dyn Database,
209 module: ModuleId<'db>,
210 name: SmolStrId<'db>,
211 generic_args: Vec<GenericArgumentId<'db>>,
212) -> TypeId<'db> {
213 try_get_ty_by_name(db, module, name, generic_args).unwrap()
214}
215
216pub fn core_bool_ty<'db>(db: &'db dyn Database) -> TypeId<'db> {
217 let core_module = db.core_module();
218 let generic_type = db
220 .module_item_by_name(core_module, SmolStrId::from(db, "bool"))
221 .expect("Failed to load core lib.")
222 .and_then(GenericTypeId::option_from)
223 .expect("Type bool was not found in core lib.");
224 semantic::TypeLongId::Concrete(semantic::ConcreteTypeId::new(db, generic_type, vec![]))
225 .intern(db)
226}
227
228pub fn core_bool_enum<'db>(db: &'db dyn Database) -> ConcreteEnumId<'db> {
231 let core_module = db.core_module();
232 let enum_id = db
234 .module_item_by_name(core_module, SmolStrId::from(db, "bool"))
235 .expect("Failed to load core lib.")
236 .and_then(EnumId::option_from)
237 .expect("Type bool was not found in core lib.");
238 ConcreteEnumLongId { enum_id, generic_args: vec![] }.intern(db)
239}
240
241pub fn false_variant(db: &dyn Database) -> ConcreteVariant<'_> {
243 get_core_enum_concrete_variant(
244 db,
245 SmolStrId::from(db, "bool"),
246 vec![],
247 SmolStrId::from(db, "False"),
248 )
249}
250
251pub fn true_variant(db: &dyn Database) -> ConcreteVariant<'_> {
253 get_core_enum_concrete_variant(
254 db,
255 SmolStrId::from(db, "bool"),
256 vec![],
257 SmolStrId::from(db, "True"),
258 )
259}
260
261pub fn jump_nz_zero_variant<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteVariant<'db> {
263 get_enum_concrete_variant(
264 db,
265 core_submodule(db, SmolStrId::from(db, "zeroable")),
266 SmolStrId::from(db, "IsZeroResult"),
267 vec![GenericArgumentId::Type(ty)],
268 SmolStrId::from(db, "Zero"),
269 )
270}
271
272pub fn jump_nz_nonzero_variant<'db>(
274 db: &'db dyn Database,
275 ty: TypeId<'db>,
276) -> ConcreteVariant<'db> {
277 get_enum_concrete_variant(
278 db,
279 core_submodule(db, SmolStrId::from(db, "zeroable")),
280 SmolStrId::from(db, "IsZeroResult"),
281 vec![GenericArgumentId::Type(ty)],
282 SmolStrId::from(db, "NonZero"),
283 )
284}
285
286pub fn option_some_variant<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteVariant<'db> {
288 get_enum_concrete_variant(
289 db,
290 core_submodule(db, SmolStrId::from(db, "option")),
291 SmolStrId::from(db, "Option"),
292 vec![GenericArgumentId::Type(ty)],
293 SmolStrId::from(db, "Some"),
294 )
295}
296
297pub fn option_none_variant<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteVariant<'db> {
299 get_enum_concrete_variant(
300 db,
301 core_submodule(db, SmolStrId::from(db, "option")),
302 SmolStrId::from(db, "Option"),
303 vec![GenericArgumentId::Type(ty)],
304 SmolStrId::from(db, "None"),
305 )
306}
307
308pub fn result_ok_variant<'db>(
310 db: &'db dyn Database,
311 ok_ty: TypeId<'db>,
312 err_ty: TypeId<'db>,
313) -> ConcreteVariant<'db> {
314 get_enum_concrete_variant(
315 db,
316 core_submodule(db, SmolStrId::from(db, "result")),
317 SmolStrId::from(db, "Result"),
318 vec![GenericArgumentId::Type(ok_ty), GenericArgumentId::Type(err_ty)],
319 SmolStrId::from(db, "Ok"),
320 )
321}
322
323pub fn result_err_variant<'db>(
325 db: &'db dyn Database,
326 ok_ty: TypeId<'db>,
327 err_ty: TypeId<'db>,
328) -> ConcreteVariant<'db> {
329 get_enum_concrete_variant(
330 db,
331 core_submodule(db, SmolStrId::from(db, "result")),
332 SmolStrId::from(db, "Result"),
333 vec![GenericArgumentId::Type(ok_ty), GenericArgumentId::Type(err_ty)],
334 SmolStrId::from(db, "Err"),
335 )
336}
337
338pub fn signed_int_result_in_range_variant<'db>(
340 db: &'db dyn Database,
341 ty: TypeId<'db>,
342) -> ConcreteVariant<'db> {
343 get_enum_concrete_variant(
344 db,
345 core_submodule(db, SmolStrId::from(db, "integer")),
346 SmolStrId::from(db, "SignedIntegerResult"),
347 vec![GenericArgumentId::Type(ty)],
348 SmolStrId::from(db, "InRange"),
349 )
350}
351pub fn signed_int_result_underflow_variant<'db>(
353 db: &'db dyn Database,
354 ty: TypeId<'db>,
355) -> ConcreteVariant<'db> {
356 get_enum_concrete_variant(
357 db,
358 core_submodule(db, SmolStrId::from(db, "integer")),
359 SmolStrId::from(db, "SignedIntegerResult"),
360 vec![GenericArgumentId::Type(ty)],
361 SmolStrId::from(db, "Underflow"),
362 )
363}
364pub fn signed_int_result_overflow_variant<'db>(
366 db: &'db dyn Database,
367 ty: TypeId<'db>,
368) -> ConcreteVariant<'db> {
369 get_enum_concrete_variant(
370 db,
371 core_submodule(db, SmolStrId::from(db, "integer")),
372 SmolStrId::from(db, "SignedIntegerResult"),
373 vec![GenericArgumentId::Type(ty)],
374 SmolStrId::from(db, "Overflow"),
375 )
376}
377
378pub fn false_literal_expr<'db>(
381 ctx: &mut ComputationContext<'db, '_>,
382 stable_ptr: ast::ExprPtr<'db>,
383) -> semantic::Expr<'db> {
384 get_bool_variant_expr(
385 ctx,
386 SmolStrId::from(ctx.db, "bool"),
387 SmolStrId::from(ctx.db, "False"),
388 stable_ptr,
389 )
390}
391
392pub fn true_literal_expr<'db>(
395 ctx: &mut ComputationContext<'db, '_>,
396 stable_ptr: ast::ExprPtr<'db>,
397) -> semantic::Expr<'db> {
398 get_bool_variant_expr(
399 ctx,
400 SmolStrId::from(ctx.db, "bool"),
401 SmolStrId::from(ctx.db, "True"),
402 stable_ptr,
403 )
404}
405
406fn get_bool_variant_expr<'db>(
409 ctx: &mut ComputationContext<'db, '_>,
410 enum_name: SmolStrId<'db>,
411 variant_name: SmolStrId<'db>,
412 stable_ptr: ast::ExprPtr<'db>,
413) -> semantic::Expr<'db> {
414 let concrete_variant = get_core_enum_concrete_variant(ctx.db, enum_name, vec![], variant_name);
415 semantic::Expr::EnumVariantCtor(semantic::ExprEnumVariantCtor {
416 variant: concrete_variant,
417 value_expr: unit_expr(ctx, stable_ptr),
418 ty: core_bool_ty(ctx.db),
419 stable_ptr,
420 })
421}
422
423pub fn get_enum_concrete_variant<'db>(
426 db: &'db dyn Database,
427 module_id: ModuleId<'db>,
428 enum_name: SmolStrId<'db>,
429 generic_args: Vec<GenericArgumentId<'db>>,
430 variant_name: SmolStrId<'db>,
431) -> ConcreteVariant<'db> {
432 let ty = get_ty_by_name(db, module_id, enum_name, generic_args);
433 let concrete_ty = extract_matches!(ty.long(db), TypeLongId::Concrete);
434 let concrete_enum_id = extract_matches!(concrete_ty, ConcreteTypeId::Enum);
435 let enum_id = concrete_enum_id.enum_id(db);
436 let variant_id = db.enum_variants(enum_id).unwrap()[&variant_name];
437 let variant = db.variant_semantic(enum_id, variant_id).unwrap();
438 db.concrete_enum_variant(*concrete_enum_id, &variant).unwrap()
439}
440
441pub fn get_core_enum_concrete_variant<'db>(
444 db: &'db dyn Database,
445 enum_name: SmolStrId<'db>,
446 generic_args: Vec<GenericArgumentId<'db>>,
447 variant_name: SmolStrId<'db>,
448) -> ConcreteVariant<'db> {
449 get_enum_concrete_variant(db, core_module(db), enum_name, generic_args, variant_name)
450}
451
452pub fn unit_ty<'db>(db: &'db dyn Database) -> TypeId<'db> {
454 semantic::TypeLongId::Tuple(vec![]).intern(db)
455}
456
457pub fn never_ty<'db>(db: &'db dyn Database) -> TypeId<'db> {
459 let core_module = db.core_module();
460 let generic_type = db
462 .module_item_by_name(core_module, SmolStrId::from(db, "never"))
463 .expect("Failed to load core lib.")
464 .and_then(GenericTypeId::option_from)
465 .expect("Type never was not found in core lib.");
466 semantic::TypeLongId::Concrete(semantic::ConcreteTypeId::new(db, generic_type, vec![]))
467 .intern(db)
468}
469
470pub enum ErrorPropagationType<'db> {
471 Option { some_variant: ConcreteVariant<'db>, none_variant: ConcreteVariant<'db> },
472 Result { ok_variant: ConcreteVariant<'db>, err_variant: ConcreteVariant<'db> },
473}
474impl<'db> ErrorPropagationType<'db> {
475 pub fn ok_variant(&self) -> &ConcreteVariant<'db> {
476 match self {
477 ErrorPropagationType::Option { some_variant, .. } => some_variant,
478 ErrorPropagationType::Result { ok_variant, .. } => ok_variant,
479 }
480 }
481 pub fn err_variant(&self) -> &ConcreteVariant<'db> {
482 match self {
483 ErrorPropagationType::Option { none_variant, .. } => none_variant,
484 ErrorPropagationType::Result { err_variant, .. } => err_variant,
485 }
486 }
487}
488
489pub fn unwrap_error_propagation_type<'db>(
492 db: &'db dyn Database,
493 ty: TypeId<'db>,
494) -> Option<ErrorPropagationType<'db>> {
495 match ty.long(db) {
496 TypeLongId::Concrete(semantic::ConcreteTypeId::Enum(enm)) => {
498 let [v0, v1] = db.concrete_enum_variants(*enm).ok()?.into_iter().collect_array()?;
499 let info = db.core_info();
500 let enum_id = enm.enum_id(db);
501 if enum_id == info.result {
502 Some(ErrorPropagationType::Result { ok_variant: v0, err_variant: v1 })
503 } else if enum_id == info.option {
504 Some(ErrorPropagationType::Option { some_variant: v0, none_variant: v1 })
505 } else {
506 None
507 }
508 }
509 TypeLongId::GenericParameter(_)
510 | TypeLongId::Concrete(
511 semantic::ConcreteTypeId::Struct(_) | semantic::ConcreteTypeId::Extern(_),
512 )
513 | TypeLongId::Tuple(_)
514 | TypeLongId::Snapshot(_)
515 | TypeLongId::Var(_)
516 | TypeLongId::NumericLiteral(_)
517 | TypeLongId::Coupon(_)
518 | TypeLongId::ImplType(_)
519 | TypeLongId::Missing(_)
520 | TypeLongId::FixedSizeArray { .. }
521 | TypeLongId::Closure(_) => None,
522 }
523}
524
525pub fn unit_expr<'db>(
528 ctx: &mut ComputationContext<'db, '_>,
529 stable_ptr: ast::ExprPtr<'db>,
530) -> ExprId {
531 ctx.arenas.exprs.alloc(Expr::Tuple(ExprTuple {
532 items: Vec::new(),
533 ty: TypeLongId::Tuple(Vec::new()).intern(ctx.db),
534 stable_ptr,
535 }))
536}
537
538pub fn core_unary_operator<'db>(
539 db: &'db dyn Database,
540 inference: &mut Inference<'db, '_>,
541 unary_op: &UnaryOperator<'db>,
542 stable_ptr: SyntaxStablePtrId<'db>,
543) -> Maybe<Result<ConcreteTraitGenericFunctionId<'db>, SemanticDiagnosticKind<'db>>> {
544 let info = db.core_info();
545 let (trait_id, trait_fn) = match unary_op {
546 UnaryOperator::Minus(_) => (info.neg_trt, info.neg_fn),
547 UnaryOperator::Not(_) => (info.not_trt, info.not_fn),
548 UnaryOperator::BitNot(_) => (info.bitnot_trt, info.bitnot_fn),
549 UnaryOperator::At(_) => unreachable!("@ is not an unary operator."),
550 UnaryOperator::Desnap(_) => unreachable!("* is not an unary operator."),
551 UnaryOperator::Reference(_) => unreachable!("& is handled before reaching here."),
552 };
553 Ok(Ok(get_core_trait_function_infer(db, inference, trait_id, trait_fn, stable_ptr)))
554}
555
556pub fn core_binary_operator<'db>(
557 db: &'db dyn Database,
558 inference: &mut Inference<'db, '_>,
559 binary_op: &BinaryOperator<'db>,
560 stable_ptr: SyntaxStablePtrId<'db>,
561) -> Maybe<Result<(ConcreteTraitGenericFunctionId<'db>, bool), SemanticDiagnosticKind<'db>>> {
562 let info = db.core_info();
563 let (trait_id, trait_fn, snapshot) = match binary_op {
564 BinaryOperator::Plus(_) => (info.add_trt, info.add_fn, false),
565 BinaryOperator::PlusEq(_) => (info.add_assign_trt, info.add_assign_fn, false),
566 BinaryOperator::Minus(_) => (info.sub_trt, info.sub_fn, false),
567 BinaryOperator::MinusEq(_) => (info.sub_assign_trt, info.sub_assign_fn, false),
568 BinaryOperator::Mul(_) => (info.mul_trt, info.mul_fn, false),
569 BinaryOperator::MulEq(_) => (info.mul_assign_trt, info.mul_assign_fn, false),
570 BinaryOperator::Div(_) => (info.div_trt, info.div_fn, false),
571 BinaryOperator::DivEq(_) => (info.div_assign_trt, info.div_assign_fn, false),
572 BinaryOperator::Mod(_) => (info.rem_trt, info.rem_fn, false),
573 BinaryOperator::ModEq(_) => (info.rem_assign_trt, info.rem_assign_fn, false),
574 BinaryOperator::EqEq(_) => (info.partialeq_trt, info.eq_fn, true),
575 BinaryOperator::Neq(_) => (info.partialeq_trt, info.ne_fn, true),
576 BinaryOperator::LE(_) => (info.partialord_trt, info.le_fn, false),
577 BinaryOperator::GE(_) => (info.partialord_trt, info.ge_fn, false),
578 BinaryOperator::LT(_) => (info.partialord_trt, info.lt_fn, false),
579 BinaryOperator::GT(_) => (info.partialord_trt, info.gt_fn, false),
580 BinaryOperator::And(_) => (info.bitand_trt, info.bitand_fn, false),
581 BinaryOperator::Or(_) => (info.bitor_trt, info.bitor_fn, false),
582 BinaryOperator::Xor(_) => (info.bitxor_trt, info.bitxor_fn, false),
583 BinaryOperator::DotDot(_) => (info.range_op_trt, info.range_fn, false),
584 BinaryOperator::DotDotEq(_) => {
585 (info.range_inclusive_op_trt, info.range_inclusive_fn, false)
586 }
587 _ => return Ok(Err(SemanticDiagnosticKind::UnknownBinaryOperator)),
588 };
589 Ok(Ok((get_core_trait_function_infer(db, inference, trait_id, trait_fn, stable_ptr), snapshot)))
590}
591
592pub fn felt252_sub<'db>(db: &'db dyn Database) -> FunctionId<'db> {
593 get_core_function_impl_method(db, SmolStrId::from(db, "Felt252Sub"), SmolStrId::from(db, "sub"))
594}
595
596fn get_core_function_impl_method<'db>(
598 db: &'db dyn Database,
599 impl_name: SmolStrId<'db>,
600 method_name: SmolStrId<'db>,
601) -> FunctionId<'db> {
602 let core_module = db.core_module();
603 let module_item_id = db
604 .module_item_by_name(core_module, impl_name)
605 .expect("Failed to load core lib.")
606 .unwrap_or_else(|| panic!("Impl '{}' was not found in core lib.", impl_name.long(db)));
607 let impl_def_id = match module_item_id {
608 ModuleItemId::Use(use_id) => {
609 db.use_resolved_item(use_id).to_option().and_then(|resolved_generic_item| {
610 try_extract_matches!(resolved_generic_item, ResolvedGenericItem::Impl)
611 })
612 }
613 _ => ImplDefId::option_from(module_item_id),
614 }
615 .unwrap_or_else(|| panic!("{} is not an impl.", impl_name.long(db)));
616 let impl_id =
617 ImplLongId::Concrete(ConcreteImplLongId { impl_def_id, generic_args: vec![] }.intern(db))
618 .intern(db);
619 let concrete_trait_id = db.impl_concrete_trait(impl_id).unwrap();
620 let function = db
621 .trait_functions(concrete_trait_id.trait_id(db))
622 .ok()
623 .and_then(|functions| functions.get(&method_name).cloned())
624 .unwrap_or_else(|| {
625 panic!(
626 "no {} in {}.",
627 method_name.long(db),
628 concrete_trait_id.trait_id(db).name(db).long(db)
629 )
630 });
631 FunctionLongId {
632 function: ConcreteFunction {
633 generic_function: GenericFunctionId::Impl(ImplGenericFunctionId { impl_id, function }),
634 generic_args: vec![],
635 },
636 }
637 .intern(db)
638}
639
640pub fn core_felt252_is_zero<'db>(db: &'db dyn Database) -> FunctionId<'db> {
641 get_core_function_id(db, SmolStrId::from(db, "felt252_is_zero"), vec![])
642}
643
644pub fn core_withdraw_gas_fns<'db>(db: &'db dyn Database) -> [FunctionId<'db>; 2] {
646 let gas = core_submodule(db, SmolStrId::from(db, "gas"));
647 [
648 get_function_id(db, gas, SmolStrId::from(db, "withdraw_gas"), vec![]),
649 get_function_id(db, gas, SmolStrId::from(db, "withdraw_gas_all"), vec![]),
650 ]
651}
652
653pub fn internal_require_implicit(db: &dyn Database) -> GenericFunctionId<'_> {
654 get_generic_function_id(
655 db,
656 core_submodule(db, SmolStrId::from(db, "internal")),
657 SmolStrId::from(db, "require_implicit"),
658 )
659}
660pub fn get_core_function_id<'db>(
662 db: &'db dyn Database,
663 name: SmolStrId<'db>,
664 generic_args: Vec<GenericArgumentId<'db>>,
665) -> FunctionId<'db> {
666 get_function_id(db, db.core_module(), name, generic_args)
667}
668
669pub fn get_function_id<'db>(
671 db: &'db dyn Database,
672 module: ModuleId<'db>,
673 name: SmolStrId<'db>,
674 generic_args: Vec<GenericArgumentId<'db>>,
675) -> FunctionId<'db> {
676 get_generic_function_id(db, module, name).concretize(db, generic_args)
677}
678
679pub fn get_core_generic_function_id<'db>(
681 db: &'db dyn Database,
682 name: SmolStrId<'db>,
683) -> GenericFunctionId<'db> {
684 get_generic_function_id(db, db.core_module(), name)
685}
686
687pub fn get_generic_function_id<'db>(
689 db: &'db dyn Database,
690 module: ModuleId<'db>,
691 name: SmolStrId<'db>,
692) -> GenericFunctionId<'db> {
693 let module_item_id = db
694 .module_item_by_name(module, name)
695 .expect("Failed to load core lib.")
696 .unwrap_or_else(|| panic!("Function '{}' was not found in core lib.", name.long(db)));
697 match module_item_id {
698 ModuleItemId::Use(use_id) => {
699 db.use_resolved_item(use_id).to_option().and_then(|resolved_generic_item| {
700 try_extract_matches!(resolved_generic_item, ResolvedGenericItem::GenericFunction)
701 })
702 }
703 _ => GenericFunctionId::option_from(module_item_id),
704 }
705 .unwrap_or_else(|| panic!("{} is not a function.", name.long(db)))
706}
707
708pub fn concrete_copy_trait<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteTraitId<'db> {
709 concrete_trait(db, db.core_info().copy_trt, vec![GenericArgumentId::Type(ty)])
710}
711
712pub fn concrete_drop_trait<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteTraitId<'db> {
713 concrete_trait(db, db.core_info().drop_trt, vec![GenericArgumentId::Type(ty)])
714}
715
716pub fn concrete_destruct_trait<'db>(
717 db: &'db dyn Database,
718 ty: TypeId<'db>,
719) -> ConcreteTraitId<'db> {
720 concrete_trait(db, db.core_info().destruct_trt, vec![GenericArgumentId::Type(ty)])
721}
722
723pub fn concrete_panic_destruct_trait<'db>(
724 db: &'db dyn Database,
725 ty: TypeId<'db>,
726) -> ConcreteTraitId<'db> {
727 concrete_trait(db, db.core_info().panic_destruct_trt, vec![GenericArgumentId::Type(ty)])
728}
729
730pub fn concrete_iterator_trait<'db>(
731 db: &'db dyn Database,
732 ty: TypeId<'db>,
733) -> ConcreteTraitId<'db> {
734 concrete_trait(db, db.core_info().iterator_trt, vec![GenericArgumentId::Type(ty)])
735}
736
737pub fn fn_traits<'db>(db: &'db dyn Database) -> [TraitId<'db>; 2] {
738 let info = db.core_info();
739 [info.fn_trt, info.fn_once_trt]
740}
741
742fn concrete_trait<'db>(
744 db: &'db dyn Database,
745 trait_id: TraitId<'db>,
746 generic_args: Vec<GenericArgumentId<'db>>,
747) -> ConcreteTraitId<'db> {
748 semantic::ConcreteTraitLongId { trait_id, generic_args }.intern(db)
749}
750
751fn get_core_trait_function_infer<'db>(
754 db: &'db dyn Database,
755 inference: &mut Inference<'db, '_>,
756 trait_id: TraitId<'db>,
757 trait_function: TraitFunctionId<'db>,
758 stable_ptr: SyntaxStablePtrId<'db>,
759) -> ConcreteTraitGenericFunctionId<'db> {
760 let generic_params = db.trait_generic_params(trait_id).unwrap();
761 let generic_args = generic_params
762 .iter()
763 .map(|_| GenericArgumentId::Type(inference.new_type_var(Some(stable_ptr))))
764 .collect();
765 let concrete_trait_id = semantic::ConcreteTraitLongId { trait_id, generic_args }.intern(db);
766 ConcreteTraitGenericFunctionLongId::new(db, concrete_trait_id, trait_function).intern(db)
767}
768
769pub fn get_panic_ty<'db>(db: &'db dyn Database, inner_ty: TypeId<'db>) -> TypeId<'db> {
770 get_core_ty_by_name(
771 db,
772 SmolStrId::from(db, "PanicResult"),
773 vec![GenericArgumentId::Type(inner_ty)],
774 )
775}
776
777pub fn get_usize_ty<'db>(db: &'db dyn Database) -> TypeId<'db> {
778 get_core_ty_by_name(db, SmolStrId::from(db, "usize"), vec![])
779}
780
781pub fn numeric_upcastable_to_felt252(db: &dyn Database, ty: TypeId<'_>) -> bool {
783 match NumericLiteralType::new(db, ty) {
784 Some(
785 NumericLiteralType::Felt252
786 | NumericLiteralType::U8
787 | NumericLiteralType::U16
788 | NumericLiteralType::U32
789 | NumericLiteralType::U64
790 | NumericLiteralType::U128
791 | NumericLiteralType::I8
792 | NumericLiteralType::I16
793 | NumericLiteralType::I32
794 | NumericLiteralType::I64
795 | NumericLiteralType::I128
796 | NumericLiteralType::BoundedInt { .. },
797 ) => true,
798 None
799 | Some(
800 NumericLiteralType::U256
801 | NumericLiteralType::ClassHash
802 | NumericLiteralType::ContractAddress
803 | NumericLiteralType::NonZero(_),
804 ) => false,
805 }
806}
807
808#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
809pub enum LiteralError<'db> {
810 InvalidTypeForLiteral(TypeId<'db>),
811 OutOfRange(TypeId<'db>),
812}
813impl<'db> LiteralError<'db> {
814 pub fn format(&self, db: &dyn Database) -> String {
815 match self {
816 Self::OutOfRange(ty) => {
817 format!("The value does not fit within the range of type {}.", ty.format(db))
818 }
819 Self::InvalidTypeForLiteral(ty) => {
820 format!("A numeric literal of type {} cannot be created.", ty.format(db))
821 }
822 }
823 }
824}
825
826pub fn is_valid_literal_type<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> bool {
829 NumericLiteralType::new(db, ty).is_some_and(|ty| match ty {
830 NumericLiteralType::U8
831 | NumericLiteralType::U16
832 | NumericLiteralType::U32
833 | NumericLiteralType::U64
834 | NumericLiteralType::U128
835 | NumericLiteralType::U256
836 | NumericLiteralType::I8
837 | NumericLiteralType::I16
838 | NumericLiteralType::I32
839 | NumericLiteralType::I64
840 | NumericLiteralType::I128
841 | NumericLiteralType::Felt252
842 | NumericLiteralType::ClassHash
843 | NumericLiteralType::ContractAddress
844 | NumericLiteralType::BoundedInt { .. } => true,
845 NumericLiteralType::NonZero(inner) => is_valid_literal_type(db, inner),
846 })
847}
848
849pub fn validate_literal<'db>(
852 db: &'db dyn Database,
853 ty: TypeId<'db>,
854 value: &BigInt,
855) -> Result<(), LiteralError<'db>> {
856 let validate_out_of_range = |is_out_of_range: bool| {
857 if is_out_of_range { Err(LiteralError::OutOfRange(ty)) } else { Ok(()) }
858 };
859 match NumericLiteralType::new(db, ty).ok_or(LiteralError::InvalidTypeForLiteral(ty))? {
860 NumericLiteralType::U8 => validate_out_of_range(value.to_u8().is_none()),
861 NumericLiteralType::U16 => validate_out_of_range(value.to_u16().is_none()),
862 NumericLiteralType::U32 => validate_out_of_range(value.to_u32().is_none()),
863 NumericLiteralType::U64 => validate_out_of_range(value.to_u64().is_none()),
864 NumericLiteralType::U128 => validate_out_of_range(value.to_u128().is_none()),
865 NumericLiteralType::U256 => {
866 validate_out_of_range(value.is_negative() || value.bits() > 256)
867 }
868 NumericLiteralType::I8 => validate_out_of_range(value.to_i8().is_none()),
869 NumericLiteralType::I16 => validate_out_of_range(value.to_i16().is_none()),
870 NumericLiteralType::I32 => validate_out_of_range(value.to_i32().is_none()),
871 NumericLiteralType::I64 => validate_out_of_range(value.to_i64().is_none()),
872 NumericLiteralType::I128 => validate_out_of_range(value.to_i128().is_none()),
873 NumericLiteralType::Felt252 => validate_out_of_range(
874 value.abs()
875 > BigInt::from_str_radix(
876 "800000000000011000000000000000000000000000000000000000000000000",
877 16,
878 )
879 .unwrap(),
880 ),
881 NumericLiteralType::ClassHash | NumericLiteralType::ContractAddress => {
882 validate_out_of_range(value.is_negative() || value.bits() > 251)
883 }
884 NumericLiteralType::BoundedInt { min, max } => {
885 let (Some(min), Some(max)) = (min.to_int(db), max.to_int(db)) else {
886 return Err(LiteralError::InvalidTypeForLiteral(ty));
887 };
888 validate_out_of_range(value < min || value > max)
889 }
890 NumericLiteralType::NonZero(_) if value.is_zero() => Err(LiteralError::OutOfRange(ty)),
891 NumericLiteralType::NonZero(nz_wrapped_ty) => validate_literal(db, nz_wrapped_ty, value),
892 }
893}
894
895enum NumericLiteralType<'db> {
900 U8,
901 U16,
902 U32,
903 U64,
904 U128,
905 U256,
906 I8,
907 I16,
908 I32,
909 I64,
910 I128,
911 Felt252,
912 ClassHash,
913 ContractAddress,
914 BoundedInt {
916 min: ConstValueId<'db>,
917 max: ConstValueId<'db>,
918 },
919 NonZero(TypeId<'db>),
921}
922impl<'db> NumericLiteralType<'db> {
923 fn new(db: &'db dyn Database, ty: TypeId<'db>) -> Option<Self> {
926 let info = db.core_info();
927 if ty == info.u8 {
928 Some(Self::U8)
929 } else if ty == info.u16 {
930 Some(Self::U16)
931 } else if ty == info.u32 {
932 Some(Self::U32)
933 } else if ty == info.u64 {
934 Some(Self::U64)
935 } else if ty == info.u128 {
936 Some(Self::U128)
937 } else if ty == info.u256 {
938 Some(Self::U256)
939 } else if ty == info.i8 {
940 Some(Self::I8)
941 } else if ty == info.i16 {
942 Some(Self::I16)
943 } else if ty == info.i32 {
944 Some(Self::I32)
945 } else if ty == info.i64 {
946 Some(Self::I64)
947 } else if ty == info.i128 {
948 Some(Self::I128)
949 } else if ty == info.felt252 {
950 Some(Self::Felt252)
951 } else if ty == info.class_hash {
952 Some(Self::ClassHash)
953 } else if ty == info.contract_address {
954 Some(Self::ContractAddress)
955 } else if let Some(inner) = try_extract_nz_wrapped_type(db, ty) {
956 Some(Self::NonZero(inner))
957 } else if let Some((min, max)) = try_extract_bounded_int_type(db, ty) {
958 Some(Self::BoundedInt { min, max })
959 } else {
960 None
961 }
962 }
963}
964
965pub fn try_extract_nz_wrapped_type<'db>(
967 db: &'db dyn Database,
968 ty: TypeId<'db>,
969) -> Option<TypeId<'db>> {
970 let concrete_ty = try_extract_matches!(ty.long(db), TypeLongId::Concrete)?;
971 let extern_ty = try_extract_matches!(concrete_ty, ConcreteTypeId::Extern)?;
972 let ConcreteExternTypeLongId { extern_type_id, generic_args } = extern_ty.long(db);
973 let [GenericArgumentId::Type(inner)] = generic_args[..] else { return None };
974 (extern_type_id.name(db).long(db) == "NonZero").then_some(inner)
975}
976
977pub fn try_extract_box_inner_type<'db>(
979 db: &'db dyn Database,
980 ty: &TypeLongId<'db>,
981) -> Option<TypeId<'db>> {
982 let concrete_ty = try_extract_matches!(ty, TypeLongId::Concrete)?;
983 let extern_ty = try_extract_matches!(concrete_ty, ConcreteTypeId::Extern)?;
984 let ConcreteExternTypeLongId { extern_type_id, generic_args } = extern_ty.long(db);
985 let [GenericArgumentId::Type(inner)] = generic_args[..] else { return None };
986 (extern_type_id.name(db).long(db) == "Box").then_some(inner)
987}
988
989pub fn try_extract_bounded_int_type<'db>(
991 db: &'db dyn Database,
992 ty: TypeId<'db>,
993) -> Option<(ConstValueId<'db>, ConstValueId<'db>)> {
994 let concrete_ty = try_extract_matches!(ty.long(db), TypeLongId::Concrete)?;
995 let extern_ty = try_extract_matches!(concrete_ty, ConcreteTypeId::Extern)?;
996 let ConcreteExternTypeLongId { extern_type_id, generic_args } = extern_ty.long(db);
997 require(extern_type_id.name(db).long(db) == "BoundedInt")?;
998 if let [GenericArgumentId::Constant(min), GenericArgumentId::Constant(max)] = generic_args[..] {
999 Some((min, max))
1000 } else {
1001 None
1002 }
1003}
1004
1005#[derive(Debug, Eq, PartialEq, Hash, salsa::Update)]
1007pub struct CoreInfo<'db> {
1008 pub felt252: TypeId<'db>,
1010 pub u8: TypeId<'db>,
1011 pub u16: TypeId<'db>,
1012 pub u32: TypeId<'db>,
1013 pub u64: TypeId<'db>,
1014 pub u128: TypeId<'db>,
1015 pub u256: TypeId<'db>,
1016 pub i8: TypeId<'db>,
1017 pub i16: TypeId<'db>,
1018 pub i32: TypeId<'db>,
1019 pub i64: TypeId<'db>,
1020 pub i128: TypeId<'db>,
1021 pub class_hash: TypeId<'db>,
1022 pub contract_address: TypeId<'db>,
1023 pub result: EnumId<'db>,
1025 pub option: EnumId<'db>,
1026 pub numeric_literal_trt: TraitId<'db>,
1028 pub string_literal_trt: TraitId<'db>,
1029 pub deref_trt: TraitId<'db>,
1030 pub deref_mut_trt: TraitId<'db>,
1031 pub index_trt: TraitId<'db>,
1032 pub index_view_trt: TraitId<'db>,
1033 pub copy_trt: TraitId<'db>,
1034 pub drop_trt: TraitId<'db>,
1035 pub destruct_trt: TraitId<'db>,
1036 pub panic_destruct_trt: TraitId<'db>,
1037 pub add_trt: TraitId<'db>,
1038 pub sub_trt: TraitId<'db>,
1039 pub mul_trt: TraitId<'db>,
1040 pub div_trt: TraitId<'db>,
1041 pub rem_trt: TraitId<'db>,
1042 pub div_rem_trt: TraitId<'db>,
1043 pub neg_trt: TraitId<'db>,
1044 pub add_assign_trt: TraitId<'db>,
1045 pub sub_assign_trt: TraitId<'db>,
1046 pub mul_assign_trt: TraitId<'db>,
1047 pub div_assign_trt: TraitId<'db>,
1048 pub rem_assign_trt: TraitId<'db>,
1049 pub bitnot_trt: TraitId<'db>,
1050 pub bitand_trt: TraitId<'db>,
1051 pub bitor_trt: TraitId<'db>,
1052 pub bitxor_trt: TraitId<'db>,
1053 pub not_trt: TraitId<'db>,
1054 pub partialeq_trt: TraitId<'db>,
1055 pub partialord_trt: TraitId<'db>,
1056 pub range_op_trt: TraitId<'db>,
1057 pub range_inclusive_op_trt: TraitId<'db>,
1058 pub into_iterator_trt: TraitId<'db>,
1059 pub iterator_trt: TraitId<'db>,
1060 pub fn_trt: TraitId<'db>,
1061 pub fn_once_trt: TraitId<'db>,
1062 pub try_into_trt: TraitId<'db>,
1063 pub type_eq_trt: TraitId<'db>,
1064 pub felt252_dict_value_trt: TraitId<'db>,
1065 pub box_trt: TraitId<'db>,
1066 pub deref_fn: TraitFunctionId<'db>,
1068 pub deref_mut_fn: TraitFunctionId<'db>,
1069 pub destruct_fn: TraitFunctionId<'db>,
1070 pub panic_destruct_fn: TraitFunctionId<'db>,
1071 pub add_fn: TraitFunctionId<'db>,
1072 pub sub_fn: TraitFunctionId<'db>,
1073 pub mul_fn: TraitFunctionId<'db>,
1074 pub div_fn: TraitFunctionId<'db>,
1075 pub rem_fn: TraitFunctionId<'db>,
1076 pub div_rem_fn: TraitFunctionId<'db>,
1077 pub neg_fn: TraitFunctionId<'db>,
1078 pub add_assign_fn: TraitFunctionId<'db>,
1079 pub sub_assign_fn: TraitFunctionId<'db>,
1080 pub mul_assign_fn: TraitFunctionId<'db>,
1081 pub div_assign_fn: TraitFunctionId<'db>,
1082 pub rem_assign_fn: TraitFunctionId<'db>,
1083 pub bitnot_fn: TraitFunctionId<'db>,
1084 pub bitand_fn: TraitFunctionId<'db>,
1085 pub bitor_fn: TraitFunctionId<'db>,
1086 pub bitxor_fn: TraitFunctionId<'db>,
1087 pub not_fn: TraitFunctionId<'db>,
1088 pub eq_fn: TraitFunctionId<'db>,
1089 pub ne_fn: TraitFunctionId<'db>,
1090 pub lt_fn: TraitFunctionId<'db>,
1091 pub gt_fn: TraitFunctionId<'db>,
1092 pub le_fn: TraitFunctionId<'db>,
1093 pub ge_fn: TraitFunctionId<'db>,
1094 pub range_fn: TraitFunctionId<'db>,
1095 pub range_inclusive_fn: TraitFunctionId<'db>,
1096 pub into_iter_fn: TraitFunctionId<'db>,
1097 pub next_fn: TraitFunctionId<'db>,
1098 pub call_fn: TraitFunctionId<'db>,
1099 pub call_once_fn: TraitFunctionId<'db>,
1100 pub try_into_fn: TraitFunctionId<'db>,
1101 pub box_new_fn: TraitFunctionId<'db>,
1102 pub upcast_fn: GenericFunctionId<'db>,
1103 pub downcast_fn: GenericFunctionId<'db>,
1104 pub into_box: ExternFunctionId<'db>,
1105 pub unbox: ExternFunctionId<'db>,
1106 pub box_forward_snapshot: ExternFunctionId<'db>,
1107 pub tuple_submodule: ModuleId<'db>,
1108 pub fixed_size_array_submodule: ModuleId<'db>,
1109 pub keyword_docs_submodule: ModuleId<'db>,
1110}
1111impl<'db> CoreInfo<'db> {
1112 fn new(db: &'db dyn Database) -> Self {
1113 let core = ModuleHelper::core(db);
1114 let integer: ModuleHelper<'db> = core.submodule("integer");
1115 let traits = core.submodule("traits");
1116 let ops = core.submodule("ops");
1117 let deref_module = ops.submodule("deref");
1118 let deref_trt = deref_module.trait_id("Deref");
1119 let deref_mut_trt = deref_module.trait_id("DerefMut");
1120 let destruct_trt = traits.trait_id("Destruct");
1121 let panic_destruct_trt = traits.trait_id("PanicDestruct");
1122 let add_trt = traits.trait_id("Add");
1123 let sub_trt = traits.trait_id("Sub");
1124 let mul_trt = traits.trait_id("Mul");
1125 let div_trt = traits.trait_id("Div");
1126 let rem_trt = traits.trait_id("Rem");
1127 let div_rem_trt = traits.trait_id("DivRem");
1128 let neg_trt = traits.trait_id("Neg");
1129 let arith_module = ops.submodule("arith");
1130 let add_assign_trt = arith_module.trait_id("AddAssign");
1131 let sub_assign_trt = arith_module.trait_id("SubAssign");
1132 let mul_assign_trt = arith_module.trait_id("MulAssign");
1133 let div_assign_trt = arith_module.trait_id("DivAssign");
1134 let rem_assign_trt = arith_module.trait_id("RemAssign");
1135 let bitnot_trt = traits.trait_id("BitNot");
1136 let bitand_trt = traits.trait_id("BitAnd");
1137 let bitor_trt = traits.trait_id("BitOr");
1138 let bitxor_trt = traits.trait_id("BitXor");
1139 let not_trt = traits.trait_id("Not");
1140 let partialeq_trt = traits.trait_id("PartialEq");
1141 let partialord_trt = traits.trait_id("PartialOrd");
1142 let range_module = ops.submodule("range");
1143 let range_op_trt = range_module.trait_id("RangeOp");
1144 let range_inclusive_op_trt = range_module.trait_id("RangeInclusiveOp");
1145 let iter_traits = core.submodule("iter").submodule("traits");
1146 let into_iterator_trt: TraitId<'db> =
1147 iter_traits.submodule("collect").trait_id("IntoIterator");
1148 let iterator_trt = iter_traits.submodule("iterator").trait_id("Iterator");
1149 let fn_module = ops.submodule("function");
1150 let fn_trt = fn_module.trait_id("Fn");
1151 let fn_once_trt = fn_module.trait_id("FnOnce");
1152 let box_module = core.submodule("box");
1153 let box_trt = box_module.trait_id("BoxTrait");
1154 let index_module = ops.submodule("index");
1155 let starknet = core.submodule("starknet");
1156 let bounded_int = core.submodule("internal").submodule("bounded_int");
1157 let trait_fn = |trait_id: TraitId<'db>, name: &'static str| {
1158 db.trait_function_by_name(trait_id, SmolStrId::from(db, name)).unwrap().unwrap()
1160 };
1161 let tuple_submodule = core.submodule("tuple").id;
1162 let fixed_size_array_submodule = core.submodule("fixed_size_array").id;
1163 Self {
1164 felt252: core.ty("felt252", vec![]),
1165 u8: integer.ty("u8", vec![]),
1166 u16: integer.ty("u16", vec![]),
1167 u32: integer.ty("u32", vec![]),
1168 u64: integer.ty("u64", vec![]),
1169 u128: integer.ty("u128", vec![]),
1170 u256: integer.ty("u256", vec![]),
1171 i8: integer.ty("i8", vec![]),
1172 i16: integer.ty("i16", vec![]),
1173 i32: integer.ty("i32", vec![]),
1174 i64: integer.ty("i64", vec![]),
1175 i128: integer.ty("i128", vec![]),
1176 class_hash: starknet.submodule("class_hash").ty("ClassHash", vec![]),
1177 contract_address: starknet.submodule("contract_address").ty("ContractAddress", vec![]),
1178 result: core.submodule("result").enum_id("Result"),
1179 option: core.submodule("option").enum_id("Option"),
1180 numeric_literal_trt: integer.trait_id("NumericLiteral"),
1181 string_literal_trt: core.submodule("string").trait_id("StringLiteral"),
1182 index_trt: index_module.trait_id("Index"),
1183 index_view_trt: index_module.trait_id("IndexView"),
1184 deref_trt,
1185 deref_mut_trt,
1186 copy_trt: traits.trait_id("Copy"),
1187 drop_trt: traits.trait_id("Drop"),
1188 destruct_trt,
1189 panic_destruct_trt,
1190 add_trt,
1191 sub_trt,
1192 mul_trt,
1193 div_trt,
1194 rem_trt,
1195 div_rem_trt,
1196 neg_trt,
1197 add_assign_trt,
1198 sub_assign_trt,
1199 mul_assign_trt,
1200 div_assign_trt,
1201 rem_assign_trt,
1202 bitnot_trt,
1203 bitand_trt,
1204 bitor_trt,
1205 bitxor_trt,
1206 not_trt,
1207 partialeq_trt,
1208 partialord_trt,
1209 range_op_trt,
1210 range_inclusive_op_trt,
1211 into_iterator_trt,
1212 iterator_trt,
1213 fn_trt,
1214 fn_once_trt,
1215 try_into_trt: traits.trait_id("TryInto"),
1216 type_eq_trt: core.submodule("metaprogramming").trait_id("TypeEqual"),
1217 felt252_dict_value_trt: traits.trait_id("Felt252DictValue"),
1218 box_trt,
1219 try_into_fn: trait_fn(traits.trait_id("TryInto"), "try_into"),
1220 deref_fn: trait_fn(deref_trt, "deref"),
1221 deref_mut_fn: trait_fn(deref_mut_trt, "deref_mut"),
1222 destruct_fn: trait_fn(destruct_trt, "destruct"),
1223 panic_destruct_fn: trait_fn(panic_destruct_trt, "panic_destruct"),
1224 add_fn: trait_fn(add_trt, "add"),
1225 sub_fn: trait_fn(sub_trt, "sub"),
1226 mul_fn: trait_fn(mul_trt, "mul"),
1227 div_fn: trait_fn(div_trt, "div"),
1228 rem_fn: trait_fn(rem_trt, "rem"),
1229 div_rem_fn: trait_fn(div_rem_trt, "div_rem"),
1230 neg_fn: trait_fn(neg_trt, "neg"),
1231 add_assign_fn: trait_fn(add_assign_trt, "add_assign"),
1232 sub_assign_fn: trait_fn(sub_assign_trt, "sub_assign"),
1233 mul_assign_fn: trait_fn(mul_assign_trt, "mul_assign"),
1234 div_assign_fn: trait_fn(div_assign_trt, "div_assign"),
1235 rem_assign_fn: trait_fn(rem_assign_trt, "rem_assign"),
1236 bitnot_fn: trait_fn(bitnot_trt, "bitnot"),
1237 bitand_fn: trait_fn(bitand_trt, "bitand"),
1238 bitor_fn: trait_fn(bitor_trt, "bitor"),
1239 bitxor_fn: trait_fn(bitxor_trt, "bitxor"),
1240 not_fn: trait_fn(not_trt, "not"),
1241 eq_fn: trait_fn(partialeq_trt, "eq"),
1242 ne_fn: trait_fn(partialeq_trt, "ne"),
1243 lt_fn: trait_fn(partialord_trt, "lt"),
1244 gt_fn: trait_fn(partialord_trt, "gt"),
1245 le_fn: trait_fn(partialord_trt, "le"),
1246 ge_fn: trait_fn(partialord_trt, "ge"),
1247 range_fn: trait_fn(range_op_trt, "range"),
1248 range_inclusive_fn: trait_fn(range_inclusive_op_trt, "range_inclusive"),
1249 into_iter_fn: trait_fn(into_iterator_trt, "into_iter"),
1250 next_fn: trait_fn(iterator_trt, "next"),
1251 call_fn: trait_fn(fn_trt, "call"),
1252 call_once_fn: trait_fn(fn_once_trt, "call"),
1253 box_new_fn: trait_fn(box_trt, "new"),
1254 upcast_fn: bounded_int.generic_function_id("upcast"),
1255 downcast_fn: bounded_int.generic_function_id("downcast"),
1256 into_box: box_module.extern_function_id("into_box"),
1257 unbox: box_module.extern_function_id("unbox"),
1258 box_forward_snapshot: box_module.extern_function_id("box_forward_snapshot"),
1259 tuple_submodule,
1260 fixed_size_array_submodule,
1261 keyword_docs_submodule: core.submodule("keyword_docs").id,
1262 }
1263 }
1264}
1265
1266pub fn core_info(db: &dyn Database) -> Arc<CoreInfo<'_>> {
1268 CoreInfo::new(db).into()
1269}
1270
1271#[salsa::tracked]
1273pub fn core_info_tracked(db: &dyn Database) -> Arc<CoreInfo<'_>> {
1274 core_info(db)
1275}
1276
1277pub trait CorelibSemantic<'db>: Database {
1279 fn core_crate(&'db self) -> CrateId<'db> {
1280 core_crate_tracked(self.as_dyn_database())
1281 }
1282 fn core_module(&'db self) -> ModuleId<'db> {
1283 core_module_tracked(self.as_dyn_database())
1284 }
1285 fn core_info(&'db self) -> Arc<CoreInfo<'db>> {
1286 core_info_tracked(self.as_dyn_database())
1287 }
1288}
1289impl<'db, T: Database + ?Sized> CorelibSemantic<'db> for T {}