luaur_analysis/methods/
constraint_solver_push_constraint.rs1use alloc::boxed::Box;
5use core::ptr::NonNull;
6
7use crate::enums::subtyping_variance::SubtypingVariance;
8use crate::records::code_too_complex::CodeTooComplex;
9use crate::records::constraint::Constraint;
10use crate::records::constraint_solver::ConstraintSolver;
11use crate::records::equality_constraint::EqualityConstraint;
12use crate::records::hash_subtype_constraint_record::HashSubtypeConstraintRecord;
13use crate::records::scope::Scope;
14use crate::records::subtype_constraint::SubtypeConstraint;
15use crate::records::subtype_constraint_record::SubtypeConstraintRecord;
16use crate::type_aliases::constraint_v::{ConstraintV, ConstraintVMember};
17use luaur_ast::records::location::Location;
18use luaur_common::records::dense_hash_table::DenseHasher;
19
20impl DenseHasher<SubtypeConstraintRecord> for HashSubtypeConstraintRecord {
24 fn hash(&self, key: &SubtypeConstraintRecord) -> usize {
25 self.operator_call(key)
26 }
27}
28
29impl ConstraintSolver {
30 pub fn push_constraint(
31 &mut self,
32 scope: NonNull<Scope>,
33 location: Location,
34 cv: ConstraintV,
35 ) -> NonNull<Constraint> {
36 let mut scr: Option<SubtypeConstraintRecord> = None;
37 if let Some(sc) = SubtypeConstraint::get_if(&cv) {
38 scr = Some(SubtypeConstraintRecord {
39 subTy: sc.sub_type,
40 superTy: sc.super_type,
41 variance: SubtypingVariance::Covariant,
42 });
43 } else if let Some(ec) = EqualityConstraint::get_if(&cv) {
44 scr = Some(SubtypeConstraintRecord {
45 subTy: ec.assignment_type,
46 superTy: ec.result_type,
47 variance: SubtypingVariance::Invariant,
48 });
49 }
50
51 if let Some(record) = scr {
52 if let Some(f) = self.seen_constraints.find(&record) {
53 return NonNull::new(*f).unwrap();
54 }
55 }
56
57 let c: Box<Constraint> = Box::new(
58 Constraint::constraint_not_null_scope_location_constraint_v(scope, &location, cv),
59 );
60 let borrow: *mut Constraint = c.as_ref() as *const Constraint as *mut Constraint;
61
62 if let Some(record) = scr {
63 *self.seen_constraints.get_or_insert(record) = borrow;
64 }
65
66 self.solver_constraints.push(c);
67 self.unsolved_constraints.push(borrow as *const Constraint);
68
69 if self.solver_constraint_limit > 0 {
70 self.solver_constraint_limit -= 1;
71
72 if self.solver_constraint_limit == 0 {
73 self.report_error_type_error_data_location(
74 CodeTooComplex::default().into(),
75 &location,
76 );
77 }
78 }
79
80 NonNull::new(borrow).unwrap()
81 }
82}