fix: crack crash

This commit is contained in:
Shunsuke Shibayama 2023-10-02 21:50:59 +09:00
parent f1d71e0dab
commit cce95e7210
5 changed files with 55 additions and 20 deletions

View file

@ -1277,7 +1277,8 @@ impl Context {
Ok(TyParam::Array([l, r].concat()))
}
(TyParam::FreeVar(fv), r) if fv.is_linked() => {
self.eval_bin_tp(op, fv.crack().clone(), r)
let t = fv.crack().clone();
self.eval_bin_tp(op, t, r)
}
(TyParam::FreeVar(_), _) if op.is_comparison() => Ok(TyParam::value(true)),
// _: Nat <= 10 => true
@ -1289,7 +1290,8 @@ impl Context {
Ok(TyParam::value(true))
}
(l, TyParam::FreeVar(fv)) if fv.is_linked() => {
self.eval_bin_tp(op, l, fv.crack().clone())
let t = fv.crack().clone();
self.eval_bin_tp(op, l, t)
}
(_, TyParam::FreeVar(_)) if op.is_comparison() => Ok(TyParam::value(true)),
// 10 <= _: Nat => true
@ -1340,7 +1342,10 @@ impl Context {
pub(crate) fn eval_unary_tp(&self, op: OpKind, val: TyParam) -> EvalResult<TyParam> {
match val {
TyParam::Value(c) => self.eval_unary_val(op, c).map(TyParam::Value),
TyParam::FreeVar(fv) if fv.is_linked() => self.eval_unary_tp(op, fv.crack().clone()),
TyParam::FreeVar(fv) if fv.is_linked() => {
let t = fv.crack().clone();
self.eval_unary_tp(op, t)
}
e @ TyParam::Erased(_) => Ok(e),
TyParam::FreeVar(fv) if fv.is_unbound() => {
feature_error!(self, Location::Unknown, &format!("{op} {fv}"))
@ -1409,7 +1414,10 @@ impl Context {
/// 量化変数などはそのまま返す
pub(crate) fn eval_tp(&self, p: TyParam) -> EvalResult<TyParam> {
match p {
TyParam::FreeVar(fv) if fv.is_linked() => self.eval_tp(fv.crack().clone()),
TyParam::FreeVar(fv) if fv.is_linked() => {
let tp = fv.crack().clone();
self.eval_tp(tp)
}
TyParam::FreeVar(_) => Ok(p),
TyParam::Mono(name) => self
.rec_get_const_obj(&name)
@ -1490,7 +1498,8 @@ impl Context {
) -> Result<Type, (Type, EvalErrors)> {
match substituted {
Type::FreeVar(fv) if fv.is_linked() => {
self.eval_t_params(fv.crack().clone(), level, t_loc)
let t = fv.crack().clone();
self.eval_t_params(t, level, t_loc)
}
Type::FreeVar(fv) if fv.constraint_is_sandwiched() => {
let (sub, sup) = fv.get_subsup().unwrap();
@ -1664,9 +1673,10 @@ impl Context {
// All type variables will be dereferenced or fail.
let (sub, opt_sup) = match lhs.clone() {
Type::FreeVar(fv) if fv.is_linked() => {
let t = fv.crack().clone();
return self
.eval_t_params(proj(fv.crack().clone(), rhs), level, t_loc)
.map_err(|(_, errs)| errs)
.eval_t_params(proj(t, rhs), level, t_loc)
.map_err(|(_, errs)| errs);
}
Type::FreeVar(fv) if fv.is_unbound() => {
let (sub, sup) = fv.get_subsup().unwrap();
@ -1823,7 +1833,10 @@ impl Context {
}
Ok(Type::from(kvs))
}
TyParam::FreeVar(fv) if fv.is_linked() => self.convert_tp_into_type(fv.crack().clone()),
TyParam::FreeVar(fv) if fv.is_linked() => {
let t = fv.crack().clone();
self.convert_tp_into_type(t)
}
// TyParam(Ts: Array(Type)) -> Type(Ts: Array(Type))
TyParam::FreeVar(fv) if fv.get_type().is_some() => Ok(named_free_var(
fv.unbound_name().unwrap(),
@ -1849,7 +1862,8 @@ impl Context {
pub(crate) fn convert_tp_into_value(&self, tp: TyParam) -> Result<ValueObj, TyParam> {
match tp {
TyParam::FreeVar(fv) if fv.is_linked() => {
self.convert_tp_into_value(fv.crack().clone())
let tp = fv.crack().clone();
self.convert_tp_into_value(tp)
}
TyParam::Value(v) => Ok(v),
TyParam::Array(arr) => {
@ -1891,7 +1905,8 @@ impl Context {
pub(crate) fn convert_singular_type_into_value(&self, typ: Type) -> Result<ValueObj, Type> {
match typ {
Type::FreeVar(fv) if fv.is_linked() => {
self.convert_singular_type_into_value(fv.crack().clone())
let t = fv.crack().clone();
self.convert_singular_type_into_value(t)
}
Type::Refinement(ref refine) => {
if let Predicate::Equal { rhs, .. } = refine.pred.as_ref() {
@ -2032,7 +2047,8 @@ impl Context {
pub(crate) fn convert_type_to_dict_type(&self, ty: Type) -> Result<Dict<Type, Type>, ()> {
match ty {
Type::FreeVar(fv) if fv.is_linked() => {
self.convert_type_to_dict_type(fv.crack().clone())
let t = fv.crack().clone();
self.convert_type_to_dict_type(t)
}
Type::Refinement(refine) => self.convert_type_to_dict_type(*refine.t),
Type::Poly { name, params } if &name[..] == "Dict" => {
@ -2052,7 +2068,8 @@ impl Context {
pub(crate) fn convert_type_to_tuple_type(&self, ty: Type) -> Result<Vec<Type>, ()> {
match ty {
Type::FreeVar(fv) if fv.is_linked() => {
self.convert_type_to_tuple_type(fv.crack().clone())
let t = fv.crack().clone();
self.convert_type_to_tuple_type(t)
}
Type::Refinement(refine) => self.convert_type_to_tuple_type(*refine.t),
Type::Poly { name, params } if &name[..] == "Tuple" => {
@ -2070,7 +2087,10 @@ impl Context {
pub(crate) fn convert_type_to_array(&self, ty: Type) -> Result<Vec<ValueObj>, Type> {
match ty {
Type::FreeVar(fv) if fv.is_linked() => self.convert_type_to_array(fv.crack().clone()),
Type::FreeVar(fv) if fv.is_linked() => {
let t = fv.crack().clone();
self.convert_type_to_array(t)
}
Type::Refinement(refine) => self.convert_type_to_array(*refine.t),
Type::Poly { name, params } if &name[..] == "Array" || &name[..] == "Array!" => {
let Ok(t) = self.convert_tp_into_type(params[0].clone()) else {
@ -2203,7 +2223,10 @@ impl Context {
fn detach_tp(&self, tp: TyParam, tv_cache: &mut TyVarCache) -> TyParam {
match tp {
TyParam::FreeVar(fv) if fv.is_linked() => self.detach_tp(fv.crack().clone(), tv_cache),
TyParam::FreeVar(fv) if fv.is_linked() => {
let tp = fv.crack().clone();
self.detach_tp(tp, tv_cache)
}
TyParam::FreeVar(fv) => {
let new_fv = fv.detach();
let name = new_fv.unbound_name().unwrap();

View file

@ -48,7 +48,8 @@ impl Generalizer {
}
TyParam::FreeVar(fv) if fv.is_generalized() => TyParam::FreeVar(fv),
TyParam::FreeVar(fv) if fv.is_linked() => {
self.generalize_tp(fv.crack().clone(), uninit)
let tp = fv.crack().clone();
self.generalize_tp(tp, uninit)
}
// TODO: Polymorphic generalization
TyParam::FreeVar(fv) if fv.level() > Some(self.level) => {

View file

@ -333,7 +333,8 @@ impl Context {
) -> TyCheckResult<TyParam> {
match quantified {
TyParam::FreeVar(fv) if fv.is_linked() => {
self.instantiate_tp(fv.crack().clone(), tmp_tv_cache, loc)
let tp = fv.crack().clone();
self.instantiate_tp(tp, tmp_tv_cache, loc)
}
TyParam::FreeVar(fv) if fv.is_generalized() => {
let (name, constr) = (fv.unbound_name().unwrap(), fv.constraint().unwrap());
@ -655,7 +656,8 @@ impl Context {
) -> TyCheckResult<Type> {
match unbound {
FreeVar(fv) if fv.is_linked() => {
self.instantiate_t_inner(fv.crack().clone(), tmp_tv_cache, loc)
let t = fv.crack().clone();
self.instantiate_t_inner(t, tmp_tv_cache, loc)
}
FreeVar(fv) if fv.is_generalized() => {
let (name, constr) = (fv.unbound_name().unwrap(), fv.constraint().unwrap());
@ -829,7 +831,10 @@ impl Context {
pub(crate) fn instantiate(&self, quantified: Type, callee: &hir::Expr) -> TyCheckResult<Type> {
match quantified {
FreeVar(fv) if fv.is_linked() => self.instantiate(fv.crack().clone(), callee),
FreeVar(fv) if fv.is_linked() => {
let t = fv.crack().clone();
self.instantiate(t, callee)
}
And(lhs, rhs) => {
let lhs = self.instantiate(*lhs, callee)?;
let rhs = self.instantiate(*rhs, callee)?;
@ -889,7 +894,10 @@ impl Context {
pub(crate) fn instantiate_dummy(&self, quantified: Type) -> TyCheckResult<Type> {
match quantified {
FreeVar(fv) if fv.is_linked() => self.instantiate_dummy(fv.crack().clone()),
FreeVar(fv) if fv.is_linked() => {
let t = fv.crack().clone();
self.instantiate_dummy(t)
}
And(lhs, rhs) => {
let lhs = self.instantiate_dummy(*lhs)?;
let rhs = self.instantiate_dummy(*rhs)?;

View file

@ -1219,7 +1219,8 @@ impl Context {
fn instantiate_tp_as_type(&self, tp: TyParam, loc: &impl Locational) -> TyCheckResult<Type> {
match tp {
TyParam::FreeVar(fv) if fv.is_linked() => {
self.instantiate_tp_as_type(fv.crack().clone(), loc)
let tp = fv.crack().clone();
self.instantiate_tp_as_type(tp, loc)
}
TyParam::Mono(name) => Ok(mono(name)),
TyParam::Proj { obj, attr } => {

View file

@ -787,6 +787,8 @@ impl<T: Send + Clone> Free<T> {
/// returns linked type (panic if self is unbounded)
/// NOTE: check by `.is_linked` before call
/// NOTE: Sometimes a `BorrowMut` error occurs when trying to pass the result of `crack().clone()` as an argument.
/// Bind it to a variable beforehand.
#[track_caller]
pub fn crack(&self) -> Ref<'_, T> {
Ref::map(self.borrow(), |f| match f {