fix: ownership checker bug

This commit is contained in:
Shunsuke Shibayama 2024-12-25 16:26:53 +09:00
parent 94df64d696
commit c34e013658
5 changed files with 65 additions and 52 deletions

View file

@ -389,7 +389,7 @@ impl Context {
) )
.quantify(); .quantify();
let t_staticmethod = nd_func(vec![kw(KW_FUNC, F.clone())], None, F.clone()).quantify(); let t_staticmethod = nd_func(vec![kw(KW_FUNC, F.clone())], None, F.clone()).quantify();
let t_str = nd_func(vec![kw(KW_OBJECT, Obj)], None, Str) let t_str = nd_func(vec![kw(KW_OBJECT, ref_(Obj))], None, Str)
& no_var_func( & no_var_func(
vec![kw(KW_BYTES_OR_BUFFER, mono(BYTES)), kw(KW_ENCODING, Str)], vec![kw(KW_BYTES_OR_BUFFER, mono(BYTES)), kw(KW_ENCODING, Str)],
vec![kw(KW_ERRORS, Str)], vec![kw(KW_ERRORS, Str)],

View file

@ -580,7 +580,7 @@ impl Context {
for arg_t in branch_ts.iter().skip(1) { for arg_t in branch_ts.iter().skip(1) {
return_t = self.union(&return_t, arg_t.typ().return_t().unwrap_or(&Type::Never)); return_t = self.union(&return_t, arg_t.typ().return_t().unwrap_or(&Type::Never));
} }
let param_ty = ParamTy::Pos(match_target_expr_t.clone()); let param_ty = ParamTy::Pos(match_target_expr_t.clone().into_ref());
let param_ts = [vec![param_ty], branch_ts.to_vec()].concat(); let param_ts = [vec![param_ty], branch_ts.to_vec()].concat();
let t = if kind.is_func() { let t = if kind.is_func() {
func(param_ts, None, vec![], None, return_t) func(param_ts, None, vec![], None, return_t)

View file

@ -165,63 +165,63 @@ impl OwnershipChecker {
args_owns.non_defaults.len() args_owns.non_defaults.len()
}; };
let defaults_len = args_owns.defaults.len(); let defaults_len = args_owns.defaults.len();
if call.args.pos_args.len() > non_defaults_len { let (non_default_args, var_args) = call
let (non_default_args, var_args) = .args
call.args.pos_args.split_at(non_defaults_len); .pos_args
for (nd_arg, (_, ownership)) in .split_at(usize::min(non_defaults_len, call.args.pos_args.len()));
non_default_args.iter().zip(args_owns.non_defaults.iter()) for (nd_arg, (_, ownership)) in
{ non_default_args.iter().zip(args_owns.non_defaults.iter())
self.check_expr(&nd_arg.expr, *ownership, false); {
self.check_expr(&nd_arg.expr, *ownership, false);
}
if let Some((_, ownership)) = args_owns.var_params.as_ref() {
for var_arg in var_args.iter() {
self.check_expr(&var_arg.expr, *ownership, false);
} }
if let Some((_, ownership)) = args_owns.var_params.as_ref() { } else {
for var_arg in var_args.iter() { let kw_args = var_args;
self.check_expr(&var_arg.expr, *ownership, false); for (arg, (_, ownership)) in kw_args.iter().zip(args_owns.defaults.iter()) {
} self.check_expr(&arg.expr, *ownership, false);
} else {
let kw_args = var_args;
for (arg, (_, ownership)) in kw_args.iter().zip(args_owns.defaults.iter()) {
self.check_expr(&arg.expr, *ownership, false);
}
} }
} }
if call.args.kw_args.len() > defaults_len { let (default_args, kw_var_args) = call
let (default_args, kw_var_args) = call.args.kw_args.split_at(defaults_len); .args
for kw_arg in default_args.iter() { .kw_args
if let Some((_, ownership)) = args_owns .split_at(usize::min(defaults_len, call.args.kw_args.len()));
.defaults for kw_arg in default_args.iter() {
.iter() if let Some((_, ownership)) = args_owns
.find(|(k, _)| k == kw_arg.keyword.inspect()) .defaults
{ .iter()
self.check_expr(&kw_arg.expr, *ownership, false); .find(|(k, _)| k == kw_arg.keyword.inspect())
} else if let Some((_, ownership)) = args_owns {
.non_defaults self.check_expr(&kw_arg.expr, *ownership, false);
.iter() } else if let Some((_, ownership)) = args_owns
.find(|(k, _)| k.as_ref() == Some(kw_arg.keyword.inspect())) .non_defaults
{ .iter()
self.check_expr(&kw_arg.expr, *ownership, false); .find(|(k, _)| k.as_ref() == Some(kw_arg.keyword.inspect()))
} else { {
todo!() self.check_expr(&kw_arg.expr, *ownership, false);
}
}
if let Some((_, ownership)) = args_owns.kw_var_params.as_ref() {
for var_arg in kw_var_args.iter() {
self.check_expr(&var_arg.expr, *ownership, false);
}
} else { } else {
let kw_args = kw_var_args; todo!()
for (arg, (_, ownership)) in kw_args.iter().zip(args_owns.defaults.iter()) { }
self.check_expr(&arg.expr, *ownership, false); }
} if let Some((_, ownership)) = args_owns.kw_var_params.as_ref() {
for var_arg in kw_var_args.iter() {
self.check_expr(&var_arg.expr, *ownership, false);
}
} else {
let kw_args = kw_var_args;
for (arg, (_, ownership)) in kw_args.iter().zip(args_owns.defaults.iter()) {
self.check_expr(&arg.expr, *ownership, false);
} }
} }
} }
// TODO: referenced
Expr::BinOp(binop) => { Expr::BinOp(binop) => {
self.check_expr(&binop.lhs, ownership, false); self.check_expr(&binop.lhs, Ownership::Ref, false);
self.check_expr(&binop.rhs, ownership, false); self.check_expr(&binop.rhs, Ownership::Ref, false);
} }
Expr::UnaryOp(unary) => { Expr::UnaryOp(unary) => {
self.check_expr(&unary.expr, ownership, false); self.check_expr(&unary.expr, Ownership::Ref, false);
} }
Expr::List(list) => match list { Expr::List(list) => match list {
List::Normal(lis) => { List::Normal(lis) => {

View file

@ -882,7 +882,14 @@ impl SubrType {
let ownership = match nd_param.typ() { let ownership = match nd_param.typ() {
Type::Ref(_) => Ownership::Ref, Type::Ref(_) => Ownership::Ref,
Type::RefMut { .. } => Ownership::RefMut, Type::RefMut { .. } => Ownership::RefMut,
_ => Ownership::Owned, other => {
if other.is_mut_type() {
Ownership::Owned
} else {
// e.g. passed `Nat!`, but coerced to `Nat`
Ownership::Ref
}
}
}; };
nd_args.push((nd_param.name().cloned(), ownership)); nd_args.push((nd_param.name().cloned(), ownership));
} }
@ -895,7 +902,13 @@ impl SubrType {
let ownership = match d_param.typ() { let ownership = match d_param.typ() {
Type::Ref(_) => Ownership::Ref, Type::Ref(_) => Ownership::Ref,
Type::RefMut { .. } => Ownership::RefMut, Type::RefMut { .. } => Ownership::RefMut,
_ => Ownership::Owned, other => {
if other.is_mut_type() {
Ownership::Owned
} else {
Ownership::Ref
}
}
}; };
d_args.push((d_param.name().unwrap().clone(), ownership)); d_args.push((d_param.name().unwrap().clone(), ownership));
} }

View file

@ -25,7 +25,7 @@ get_badge! file_path =
do!: do!:
"File not found" "File not found"
get_doc_en_file_paths! relative_dir_path, relative_file_paths_result := [] = get_doc_en_file_paths! relative_dir_path, relative_file_paths_result: List(Str) := [] =
dir_path = mylib.path_join(cwd, relative_dir_path) dir_path = mylib.path_join(cwd, relative_dir_path)
dir_list = sorted os.listdir! dir_path dir_list = sorted os.listdir! dir_path
relative_file_paths = ![] relative_file_paths = ![]