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 never 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 UnaryOperator::Reference(_) => unreachable!("& is handled before reaching here."),
556 };
557 Ok(Ok(get_core_trait_function_infer(db, inference, trait_id, trait_fn, stable_ptr)))
558}
559
560pub fn core_binary_operator<'db>(
561 db: &'db dyn Database,
562 inference: &mut Inference<'db, '_>,
563 binary_op: &BinaryOperator<'db>,
564 stable_ptr: SyntaxStablePtrId<'db>,
565) -> Maybe<Result<(ConcreteTraitGenericFunctionId<'db>, bool), SemanticDiagnosticKind<'db>>> {
566 let info = db.core_info();
567 let (trait_id, trait_fn, snapshot) = match binary_op {
568 BinaryOperator::Plus(_) => (info.add_trt, info.add_fn, false),
569 BinaryOperator::PlusEq(_) => (info.add_assign_trt, info.add_assign_fn, false),
570 BinaryOperator::Minus(_) => (info.sub_trt, info.sub_fn, false),
571 BinaryOperator::MinusEq(_) => (info.sub_assign_trt, info.sub_assign_fn, false),
572 BinaryOperator::Mul(_) => (info.mul_trt, info.mul_fn, false),
573 BinaryOperator::MulEq(_) => (info.mul_assign_trt, info.mul_assign_fn, false),
574 BinaryOperator::Div(_) => (info.div_trt, info.div_fn, false),
575 BinaryOperator::DivEq(_) => (info.div_assign_trt, info.div_assign_fn, false),
576 BinaryOperator::Mod(_) => (info.rem_trt, info.rem_fn, false),
577 BinaryOperator::ModEq(_) => (info.rem_assign_trt, info.rem_assign_fn, false),
578 BinaryOperator::EqEq(_) => (info.partialeq_trt, info.eq_fn, true),
579 BinaryOperator::Neq(_) => (info.partialeq_trt, info.ne_fn, true),
580 BinaryOperator::LE(_) => (info.partialord_trt, info.le_fn, false),
581 BinaryOperator::GE(_) => (info.partialord_trt, info.ge_fn, false),
582 BinaryOperator::LT(_) => (info.partialord_trt, info.lt_fn, false),
583 BinaryOperator::GT(_) => (info.partialord_trt, info.gt_fn, false),
584 BinaryOperator::And(_) => (info.bitand_trt, info.bitand_fn, false),
585 BinaryOperator::Or(_) => (info.bitor_trt, info.bitor_fn, false),
586 BinaryOperator::Xor(_) => (info.bitxor_trt, info.bitxor_fn, false),
587 BinaryOperator::DotDot(_) => (info.range_op_trt, info.range_fn, false),
588 BinaryOperator::DotDotEq(_) => {
589 (info.range_inclusive_op_trt, info.range_inclusive_fn, false)
590 }
591 _ => return Ok(Err(SemanticDiagnosticKind::UnknownBinaryOperator)),
592 };
593 Ok(Ok((get_core_trait_function_infer(db, inference, trait_id, trait_fn, stable_ptr), snapshot)))
594}
595
596pub fn felt252_sub<'db>(db: &'db dyn Database) -> FunctionId<'db> {
597 get_core_function_impl_method(db, SmolStrId::from(db, "Felt252Sub"), SmolStrId::from(db, "sub"))
598}
599
600fn get_core_function_impl_method<'db>(
602 db: &'db dyn Database,
603 impl_name: SmolStrId<'db>,
604 method_name: SmolStrId<'db>,
605) -> FunctionId<'db> {
606 let core_module = db.core_module();
607 let module_item_id = db
608 .module_item_by_name(core_module, impl_name)
609 .expect("Failed to load core lib.")
610 .unwrap_or_else(|| panic!("Impl '{}' was not found in core lib.", impl_name.long(db)));
611 let impl_def_id = match module_item_id {
612 ModuleItemId::Use(use_id) => {
613 db.use_resolved_item(use_id).to_option().and_then(|resolved_generic_item| {
614 try_extract_matches!(resolved_generic_item, ResolvedGenericItem::Impl)
615 })
616 }
617 _ => ImplDefId::option_from(module_item_id),
618 }
619 .unwrap_or_else(|| panic!("{} is not an impl.", impl_name.long(db)));
620 let impl_id =
621 ImplLongId::Concrete(ConcreteImplLongId { impl_def_id, generic_args: vec![] }.intern(db))
622 .intern(db);
623 let concrete_trait_id = db.impl_concrete_trait(impl_id).unwrap();
624 let function = db
625 .trait_functions(concrete_trait_id.trait_id(db))
626 .ok()
627 .and_then(|functions| functions.get(&method_name).cloned())
628 .unwrap_or_else(|| {
629 panic!(
630 "no {} in {}.",
631 method_name.long(db),
632 concrete_trait_id.trait_id(db).name(db).long(db)
633 )
634 });
635 FunctionLongId {
636 function: ConcreteFunction {
637 generic_function: GenericFunctionId::Impl(ImplGenericFunctionId { impl_id, function }),
638 generic_args: vec![],
639 },
640 }
641 .intern(db)
642}
643
644pub fn core_felt252_is_zero<'db>(db: &'db dyn Database) -> FunctionId<'db> {
645 get_core_function_id(db, SmolStrId::from(db, "felt252_is_zero"), vec![])
646}
647
648pub fn core_withdraw_gas_fns<'db>(db: &'db dyn Database) -> [FunctionId<'db>; 2] {
650 let gas = core_submodule(db, SmolStrId::from(db, "gas"));
651 [
652 get_function_id(db, gas, SmolStrId::from(db, "withdraw_gas"), vec![]),
653 get_function_id(db, gas, SmolStrId::from(db, "withdraw_gas_all"), vec![]),
654 ]
655}
656
657pub fn internal_require_implicit(db: &dyn Database) -> GenericFunctionId<'_> {
658 get_generic_function_id(
659 db,
660 core_submodule(db, SmolStrId::from(db, "internal")),
661 SmolStrId::from(db, "require_implicit"),
662 )
663}
664pub fn get_core_function_id<'db>(
666 db: &'db dyn Database,
667 name: SmolStrId<'db>,
668 generic_args: Vec<GenericArgumentId<'db>>,
669) -> FunctionId<'db> {
670 get_function_id(db, db.core_module(), name, generic_args)
671}
672
673pub fn get_function_id<'db>(
675 db: &'db dyn Database,
676 module: ModuleId<'db>,
677 name: SmolStrId<'db>,
678 generic_args: Vec<GenericArgumentId<'db>>,
679) -> FunctionId<'db> {
680 get_generic_function_id(db, module, name).concretize(db, generic_args)
681}
682
683pub fn get_core_generic_function_id<'db>(
685 db: &'db dyn Database,
686 name: SmolStrId<'db>,
687) -> GenericFunctionId<'db> {
688 get_generic_function_id(db, db.core_module(), name)
689}
690
691pub fn get_generic_function_id<'db>(
693 db: &'db dyn Database,
694 module: ModuleId<'db>,
695 name: SmolStrId<'db>,
696) -> GenericFunctionId<'db> {
697 let module_item_id = db
698 .module_item_by_name(module, name)
699 .expect("Failed to load core lib.")
700 .unwrap_or_else(|| panic!("Function '{}' was not found in core lib.", name.long(db)));
701 match module_item_id {
702 ModuleItemId::Use(use_id) => {
703 db.use_resolved_item(use_id).to_option().and_then(|resolved_generic_item| {
704 try_extract_matches!(resolved_generic_item, ResolvedGenericItem::GenericFunction)
705 })
706 }
707 _ => GenericFunctionId::option_from(module_item_id),
708 }
709 .unwrap_or_else(|| panic!("{} is not a function.", name.long(db)))
710}
711
712pub fn concrete_copy_trait<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteTraitId<'db> {
713 concrete_trait(db, db.core_info().copy_trt, vec![GenericArgumentId::Type(ty)])
714}
715
716pub fn concrete_drop_trait<'db>(db: &'db dyn Database, ty: TypeId<'db>) -> ConcreteTraitId<'db> {
717 concrete_trait(db, db.core_info().drop_trt, vec![GenericArgumentId::Type(ty)])
718}
719
720pub fn concrete_destruct_trait<'db>(
721 db: &'db dyn Database,
722 ty: TypeId<'db>,
723) -> ConcreteTraitId<'db> {
724 concrete_trait(db, db.core_info().destruct_trt, vec![GenericArgumentId::Type(ty)])
725}
726
727pub fn concrete_panic_destruct_trait<'db>(
728 db: &'db dyn Database,
729 ty: TypeId<'db>,
730) -> ConcreteTraitId<'db> {
731 concrete_trait(db, db.core_info().panic_destruct_trt, vec![GenericArgumentId::Type(ty)])
732}
733
734pub fn concrete_iterator_trait<'db>(
735 db: &'db dyn Database,
736 ty: TypeId<'db>,
737) -> ConcreteTraitId<'db> {
738 concrete_trait(db, db.core_info().iterator_trt, vec![GenericArgumentId::Type(ty)])
739}
740
741pub fn fn_traits<'db>(db: &'db dyn Database) -> [TraitId<'db>; 2] {
742 let info = db.core_info();
743 [info.fn_trt, info.fn_once_trt]
744}
745
746fn concrete_trait<'db>(
748 db: &'db dyn Database,
749 trait_id: TraitId<'db>,
750 generic_args: Vec<GenericArgumentId<'db>>,
751) -> ConcreteTraitId<'db> {
752 semantic::ConcreteTraitLongId { trait_id, generic_args }.intern(db)
753}
754
755fn get_core_trait_function_infer<'db>(
758 db: &'db dyn Database,
759 inference: &mut Inference<'db, '_>,
760 trait_id: TraitId<'db>,
761 trait_function: TraitFunctionId<'db>,
762 stable_ptr: SyntaxStablePtrId<'db>,
763) -> ConcreteTraitGenericFunctionId<'db> {
764 let generic_params = db.trait_generic_params(trait_id).unwrap();
765 let generic_args = generic_params
766 .iter()
767 .map(|_| GenericArgumentId::Type(inference.new_type_var(Some(stable_ptr))))
768 .collect();
769 let concrete_trait_id = semantic::ConcreteTraitLongId { trait_id, generic_args }.intern(db);
770 ConcreteTraitGenericFunctionLongId::new(db, concrete_trait_id, trait_function).intern(db)
771}
772
773pub fn get_panic_ty<'db>(db: &'db dyn Database, inner_ty: TypeId<'db>) -> TypeId<'db> {
774 get_core_ty_by_name(
775 db,
776 SmolStrId::from(db, "PanicResult"),
777 vec![GenericArgumentId::Type(inner_ty)],
778 )
779}
780
781pub fn get_usize_ty<'db>(db: &'db dyn Database) -> TypeId<'db> {
782 get_core_ty_by_name(db, SmolStrId::from(db, "usize"), vec![])
783}
784
785pub fn numeric_upcastable_to_felt252(db: &dyn Database, ty: TypeId<'_>) -> bool {
787 let info = db.core_info();
788 ty == info.felt252
789 || ty == info.u8
790 || ty == info.u16
791 || ty == info.u32
792 || ty == info.u64
793 || ty == info.u128
794 || ty == info.i8
795 || ty == info.i16
796 || ty == info.i32
797 || ty == info.i64
798 || ty == info.i128
799 || try_extract_bounded_int_type_ranges(db, ty).is_some()
800}
801
802#[derive(Clone, Debug, Eq, Hash, PartialEq, salsa::Update)]
803pub enum LiteralError<'db> {
804 InvalidTypeForLiteral(TypeId<'db>),
805 OutOfRange(TypeId<'db>),
806}
807impl<'db> LiteralError<'db> {
808 pub fn format(&self, db: &dyn Database) -> String {
809 match self {
810 Self::OutOfRange(ty) => {
811 format!("The value does not fit within the range of type {}.", ty.format(db))
812 }
813 Self::InvalidTypeForLiteral(ty) => {
814 format!("A numeric literal of type {} cannot be created.", ty.format(db))
815 }
816 }
817 }
818}
819
820pub fn validate_literal<'db>(
823 db: &'db dyn Database,
824 ty: TypeId<'db>,
825 value: &BigInt,
826) -> Result<(), LiteralError<'db>> {
827 let info = db.core_info();
828 let validate_out_of_range = |is_out_of_range: bool| {
829 if is_out_of_range { Err(LiteralError::OutOfRange(ty)) } else { Ok(()) }
830 };
831 if ty == info.felt252 {
832 validate_out_of_range(
833 value.abs()
834 > BigInt::from_str_radix(
835 "800000000000011000000000000000000000000000000000000000000000000",
836 16,
837 )
838 .unwrap(),
839 )
840 } else if ty == info.u8 {
841 validate_out_of_range(value.to_u8().is_none())
842 } else if ty == info.u16 {
843 validate_out_of_range(value.to_u16().is_none())
844 } else if ty == info.u32 {
845 validate_out_of_range(value.to_u32().is_none())
846 } else if ty == info.u64 {
847 validate_out_of_range(value.to_u64().is_none())
848 } else if ty == info.u128 {
849 validate_out_of_range(value.to_u128().is_none())
850 } else if ty == info.i8 {
851 validate_out_of_range(value.to_i8().is_none())
852 } else if ty == info.i16 {
853 validate_out_of_range(value.to_i16().is_none())
854 } else if ty == info.i32 {
855 validate_out_of_range(value.to_i32().is_none())
856 } else if ty == info.i64 {
857 validate_out_of_range(value.to_i64().is_none())
858 } else if ty == info.i128 {
859 validate_out_of_range(value.to_i128().is_none())
860 } else if ty == info.u256 {
861 validate_out_of_range(value.is_negative() || value.bits() > 256)
862 } else if ty == info.class_hash || ty == info.contract_address {
863 validate_out_of_range(value.is_negative() || value.bits() > 251)
864 } else if let Some(nz_wrapped_ty) = try_extract_nz_wrapped_type(db, ty) {
865 if value.is_zero() {
866 Err(LiteralError::OutOfRange(ty))
867 } else {
868 validate_literal(db, nz_wrapped_ty, value)
869 }
870 } else if let Some((min, max)) = try_extract_bounded_int_type_ranges(db, ty) {
871 validate_out_of_range(*value < min || *value > max)
872 } else {
873 Err(LiteralError::InvalidTypeForLiteral(ty))
874 }
875}
876
877pub fn try_extract_nz_wrapped_type<'db>(
879 db: &'db dyn Database,
880 ty: TypeId<'db>,
881) -> Option<TypeId<'db>> {
882 let concrete_ty = try_extract_matches!(ty.long(db), TypeLongId::Concrete)?;
883 let extern_ty = try_extract_matches!(concrete_ty, ConcreteTypeId::Extern)?;
884 let ConcreteExternTypeLongId { extern_type_id, generic_args } = extern_ty.long(db);
885 let [GenericArgumentId::Type(inner)] = generic_args[..] else { return None };
886 (extern_type_id.name(db).long(db) == "NonZero").then_some(inner)
887}
888
889pub fn try_extract_bounded_int_type_ranges<'db>(
891 db: &'db dyn Database,
892 ty: TypeId<'db>,
893) -> Option<(BigInt, BigInt)> {
894 let concrete_ty = try_extract_matches!(ty.long(db), TypeLongId::Concrete)?;
895 let extern_ty = try_extract_matches!(concrete_ty, ConcreteTypeId::Extern)?;
896 let ConcreteExternTypeLongId { extern_type_id, generic_args } = extern_ty.long(db);
897 require(extern_type_id.name(db).long(db) == "BoundedInt")?;
898 let [GenericArgumentId::Constant(min), GenericArgumentId::Constant(max)] = generic_args[..]
899 else {
900 return None;
901 };
902 let to_int = |id: ConstValueId<'db>| id.long(db).to_int().cloned();
903
904 Some((to_int(min)?, to_int(max)?))
905}
906
907#[derive(Debug, Eq, PartialEq, Hash, salsa::Update)]
909pub struct CoreInfo<'db> {
910 pub felt252: TypeId<'db>,
912 pub u8: TypeId<'db>,
913 pub u16: TypeId<'db>,
914 pub u32: TypeId<'db>,
915 pub u64: TypeId<'db>,
916 pub u128: TypeId<'db>,
917 pub u256: TypeId<'db>,
918 pub i8: TypeId<'db>,
919 pub i16: TypeId<'db>,
920 pub i32: TypeId<'db>,
921 pub i64: TypeId<'db>,
922 pub i128: TypeId<'db>,
923 pub class_hash: TypeId<'db>,
924 pub contract_address: TypeId<'db>,
925 pub numeric_literal_trt: TraitId<'db>,
927 pub string_literal_trt: TraitId<'db>,
928 pub deref_trt: TraitId<'db>,
929 pub deref_mut_trt: TraitId<'db>,
930 pub index_trt: TraitId<'db>,
931 pub index_view_trt: TraitId<'db>,
932 pub copy_trt: TraitId<'db>,
933 pub drop_trt: TraitId<'db>,
934 pub destruct_trt: TraitId<'db>,
935 pub panic_destruct_trt: TraitId<'db>,
936 pub add_trt: TraitId<'db>,
937 pub sub_trt: TraitId<'db>,
938 pub mul_trt: TraitId<'db>,
939 pub div_trt: TraitId<'db>,
940 pub rem_trt: TraitId<'db>,
941 pub div_rem_trt: TraitId<'db>,
942 pub neg_trt: TraitId<'db>,
943 pub add_assign_trt: TraitId<'db>,
944 pub sub_assign_trt: TraitId<'db>,
945 pub mul_assign_trt: TraitId<'db>,
946 pub div_assign_trt: TraitId<'db>,
947 pub rem_assign_trt: TraitId<'db>,
948 pub bitnot_trt: TraitId<'db>,
949 pub bitand_trt: TraitId<'db>,
950 pub bitor_trt: TraitId<'db>,
951 pub bitxor_trt: TraitId<'db>,
952 pub not_trt: TraitId<'db>,
953 pub partialeq_trt: TraitId<'db>,
954 pub partialord_trt: TraitId<'db>,
955 pub range_op_trt: TraitId<'db>,
956 pub range_inclusive_op_trt: TraitId<'db>,
957 pub into_iterator_trt: TraitId<'db>,
958 pub iterator_trt: TraitId<'db>,
959 pub fn_trt: TraitId<'db>,
960 pub fn_once_trt: TraitId<'db>,
961 pub type_eq_trt: TraitId<'db>,
962 pub felt252_dict_value_trt: TraitId<'db>,
963 pub box_trt: TraitId<'db>,
964 pub deref_fn: TraitFunctionId<'db>,
966 pub deref_mut_fn: TraitFunctionId<'db>,
967 pub destruct_fn: TraitFunctionId<'db>,
968 pub panic_destruct_fn: TraitFunctionId<'db>,
969 pub add_fn: TraitFunctionId<'db>,
970 pub sub_fn: TraitFunctionId<'db>,
971 pub mul_fn: TraitFunctionId<'db>,
972 pub div_fn: TraitFunctionId<'db>,
973 pub rem_fn: TraitFunctionId<'db>,
974 pub div_rem_fn: TraitFunctionId<'db>,
975 pub neg_fn: TraitFunctionId<'db>,
976 pub add_assign_fn: TraitFunctionId<'db>,
977 pub sub_assign_fn: TraitFunctionId<'db>,
978 pub mul_assign_fn: TraitFunctionId<'db>,
979 pub div_assign_fn: TraitFunctionId<'db>,
980 pub rem_assign_fn: TraitFunctionId<'db>,
981 pub bitnot_fn: TraitFunctionId<'db>,
982 pub bitand_fn: TraitFunctionId<'db>,
983 pub bitor_fn: TraitFunctionId<'db>,
984 pub bitxor_fn: TraitFunctionId<'db>,
985 pub not_fn: TraitFunctionId<'db>,
986 pub eq_fn: TraitFunctionId<'db>,
987 pub ne_fn: TraitFunctionId<'db>,
988 pub lt_fn: TraitFunctionId<'db>,
989 pub gt_fn: TraitFunctionId<'db>,
990 pub le_fn: TraitFunctionId<'db>,
991 pub ge_fn: TraitFunctionId<'db>,
992 pub range_fn: TraitFunctionId<'db>,
993 pub range_inclusive_fn: TraitFunctionId<'db>,
994 pub into_iter_fn: TraitFunctionId<'db>,
995 pub next_fn: TraitFunctionId<'db>,
996 pub call_fn: TraitFunctionId<'db>,
997 pub call_once_fn: TraitFunctionId<'db>,
998 pub box_new_fn: TraitFunctionId<'db>,
999 pub upcast_fn: GenericFunctionId<'db>,
1000 pub downcast_fn: GenericFunctionId<'db>,
1001 pub tuple_submodule: ModuleId<'db>,
1002 pub fixed_size_array_submodule: ModuleId<'db>,
1003 pub keyword_docs_submodule: ModuleId<'db>,
1004}
1005impl<'db> CoreInfo<'db> {
1006 fn new(db: &'db dyn Database) -> Self {
1007 let core = ModuleHelper::core(db);
1008 let integer: ModuleHelper<'db> = core.submodule("integer");
1009 let traits = core.submodule("traits");
1010 let ops = core.submodule("ops");
1011 let deref_module = ops.submodule("deref");
1012 let deref_trt = deref_module.trait_id("Deref");
1013 let deref_mut_trt = deref_module.trait_id("DerefMut");
1014 let destruct_trt = traits.trait_id("Destruct");
1015 let panic_destruct_trt = traits.trait_id("PanicDestruct");
1016 let add_trt = traits.trait_id("Add");
1017 let sub_trt = traits.trait_id("Sub");
1018 let mul_trt = traits.trait_id("Mul");
1019 let div_trt = traits.trait_id("Div");
1020 let rem_trt = traits.trait_id("Rem");
1021 let div_rem_trt = traits.trait_id("DivRem");
1022 let neg_trt = traits.trait_id("Neg");
1023 let arith_module = ops.submodule("arith");
1024 let add_assign_trt = arith_module.trait_id("AddAssign");
1025 let sub_assign_trt = arith_module.trait_id("SubAssign");
1026 let mul_assign_trt = arith_module.trait_id("MulAssign");
1027 let div_assign_trt = arith_module.trait_id("DivAssign");
1028 let rem_assign_trt = arith_module.trait_id("RemAssign");
1029 let bitnot_trt = traits.trait_id("BitNot");
1030 let bitand_trt = traits.trait_id("BitAnd");
1031 let bitor_trt = traits.trait_id("BitOr");
1032 let bitxor_trt = traits.trait_id("BitXor");
1033 let not_trt = traits.trait_id("Not");
1034 let partialeq_trt = traits.trait_id("PartialEq");
1035 let partialord_trt = traits.trait_id("PartialOrd");
1036 let range_module = ops.submodule("range");
1037 let range_op_trt = range_module.trait_id("RangeOp");
1038 let range_inclusive_op_trt = range_module.trait_id("RangeInclusiveOp");
1039 let iter_traits = core.submodule("iter").submodule("traits");
1040 let into_iterator_trt: TraitId<'db> =
1041 iter_traits.submodule("collect").trait_id("IntoIterator");
1042 let iterator_trt = iter_traits.submodule("iterator").trait_id("Iterator");
1043 let fn_module = ops.submodule("function");
1044 let fn_trt = fn_module.trait_id("Fn");
1045 let fn_once_trt = fn_module.trait_id("FnOnce");
1046 let box_module = core.submodule("box");
1047 let box_trt = box_module.trait_id("BoxTrait");
1048 let index_module = ops.submodule("index");
1049 let starknet = core.submodule("starknet");
1050 let bounded_int = core.submodule("internal").submodule("bounded_int");
1051 let trait_fn = |trait_id: TraitId<'db>, name: &'static str| {
1052 db.trait_function_by_name(trait_id, SmolStrId::from(db, name)).unwrap().unwrap()
1054 };
1055 let tuple_submodule = core.submodule("tuple").id;
1056 let fixed_size_array_submodule = core.submodule("fixed_size_array").id;
1057 Self {
1058 felt252: core.ty("felt252", vec![]),
1059 u8: integer.ty("u8", vec![]),
1060 u16: integer.ty("u16", vec![]),
1061 u32: integer.ty("u32", vec![]),
1062 u64: integer.ty("u64", vec![]),
1063 u128: integer.ty("u128", vec![]),
1064 u256: integer.ty("u256", vec![]),
1065 i8: integer.ty("i8", vec![]),
1066 i16: integer.ty("i16", vec![]),
1067 i32: integer.ty("i32", vec![]),
1068 i64: integer.ty("i64", vec![]),
1069 i128: integer.ty("i128", vec![]),
1070 class_hash: starknet.submodule("class_hash").ty("ClassHash", vec![]),
1071 contract_address: starknet.submodule("contract_address").ty("ContractAddress", vec![]),
1072 numeric_literal_trt: integer.trait_id("NumericLiteral"),
1073 string_literal_trt: core.submodule("string").trait_id("StringLiteral"),
1074 index_trt: index_module.trait_id("Index"),
1075 index_view_trt: index_module.trait_id("IndexView"),
1076 deref_trt,
1077 deref_mut_trt,
1078 copy_trt: traits.trait_id("Copy"),
1079 drop_trt: traits.trait_id("Drop"),
1080 destruct_trt,
1081 panic_destruct_trt,
1082 add_trt,
1083 sub_trt,
1084 mul_trt,
1085 div_trt,
1086 rem_trt,
1087 div_rem_trt,
1088 neg_trt,
1089 add_assign_trt,
1090 sub_assign_trt,
1091 mul_assign_trt,
1092 div_assign_trt,
1093 rem_assign_trt,
1094 bitnot_trt,
1095 bitand_trt,
1096 bitor_trt,
1097 bitxor_trt,
1098 not_trt,
1099 partialeq_trt,
1100 partialord_trt,
1101 range_op_trt,
1102 range_inclusive_op_trt,
1103 into_iterator_trt,
1104 iterator_trt,
1105 fn_trt,
1106 fn_once_trt,
1107 type_eq_trt: core.submodule("metaprogramming").trait_id("TypeEqual"),
1108 felt252_dict_value_trt: traits.trait_id("Felt252DictValue"),
1109 box_trt,
1110 deref_fn: trait_fn(deref_trt, "deref"),
1111 deref_mut_fn: trait_fn(deref_mut_trt, "deref_mut"),
1112 destruct_fn: trait_fn(destruct_trt, "destruct"),
1113 panic_destruct_fn: trait_fn(panic_destruct_trt, "panic_destruct"),
1114 add_fn: trait_fn(add_trt, "add"),
1115 sub_fn: trait_fn(sub_trt, "sub"),
1116 mul_fn: trait_fn(mul_trt, "mul"),
1117 div_fn: trait_fn(div_trt, "div"),
1118 rem_fn: trait_fn(rem_trt, "rem"),
1119 div_rem_fn: trait_fn(div_rem_trt, "div_rem"),
1120 neg_fn: trait_fn(neg_trt, "neg"),
1121 add_assign_fn: trait_fn(add_assign_trt, "add_assign"),
1122 sub_assign_fn: trait_fn(sub_assign_trt, "sub_assign"),
1123 mul_assign_fn: trait_fn(mul_assign_trt, "mul_assign"),
1124 div_assign_fn: trait_fn(div_assign_trt, "div_assign"),
1125 rem_assign_fn: trait_fn(rem_assign_trt, "rem_assign"),
1126 bitnot_fn: trait_fn(bitnot_trt, "bitnot"),
1127 bitand_fn: trait_fn(bitand_trt, "bitand"),
1128 bitor_fn: trait_fn(bitor_trt, "bitor"),
1129 bitxor_fn: trait_fn(bitxor_trt, "bitxor"),
1130 not_fn: trait_fn(not_trt, "not"),
1131 eq_fn: trait_fn(partialeq_trt, "eq"),
1132 ne_fn: trait_fn(partialeq_trt, "ne"),
1133 lt_fn: trait_fn(partialord_trt, "lt"),
1134 gt_fn: trait_fn(partialord_trt, "gt"),
1135 le_fn: trait_fn(partialord_trt, "le"),
1136 ge_fn: trait_fn(partialord_trt, "ge"),
1137 range_fn: trait_fn(range_op_trt, "range"),
1138 range_inclusive_fn: trait_fn(range_inclusive_op_trt, "range_inclusive"),
1139 into_iter_fn: trait_fn(into_iterator_trt, "into_iter"),
1140 next_fn: trait_fn(iterator_trt, "next"),
1141 call_fn: trait_fn(fn_trt, "call"),
1142 call_once_fn: trait_fn(fn_once_trt, "call"),
1143 box_new_fn: trait_fn(box_trt, "new"),
1144 upcast_fn: bounded_int.generic_function_id("upcast"),
1145 downcast_fn: bounded_int.generic_function_id("downcast"),
1146 tuple_submodule,
1147 fixed_size_array_submodule,
1148 keyword_docs_submodule: core.submodule("keyword_docs").id,
1149 }
1150 }
1151}
1152
1153pub fn core_info(db: &dyn Database) -> Arc<CoreInfo<'_>> {
1155 CoreInfo::new(db).into()
1156}
1157
1158#[salsa::tracked]
1160pub fn core_info_tracked(db: &dyn Database) -> Arc<CoreInfo<'_>> {
1161 core_info(db)
1162}
1163
1164pub trait CorelibSemantic<'db>: Database {
1166 fn core_crate(&'db self) -> CrateId<'db> {
1167 core_crate_tracked(self.as_dyn_database())
1168 }
1169 fn core_module(&'db self) -> ModuleId<'db> {
1170 core_module_tracked(self.as_dyn_database())
1171 }
1172 fn core_info(&'db self) -> Arc<CoreInfo<'db>> {
1173 core_info_tracked(self.as_dyn_database())
1174 }
1175}
1176impl<'db, T: Database + ?Sized> CorelibSemantic<'db> for T {}