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();
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(
vec![kw(KW_BYTES_OR_BUFFER, mono(BYTES)), kw(KW_ENCODING, Str)],
vec![kw(KW_ERRORS, Str)],

View file

@ -580,7 +580,7 @@ impl Context {
for arg_t in branch_ts.iter().skip(1) {
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 t = if kind.is_func() {
func(param_ts, None, vec![], None, return_t)

View file

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

View file

@ -882,7 +882,14 @@ impl SubrType {
let ownership = match nd_param.typ() {
Type::Ref(_) => Ownership::Ref,
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));
}
@ -895,7 +902,13 @@ impl SubrType {
let ownership = match d_param.typ() {
Type::Ref(_) => Ownership::Ref,
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));
}

View file

@ -25,7 +25,7 @@ get_badge! file_path =
do!:
"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_list = sorted os.listdir! dir_path
relative_file_paths = ![]