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