forked from M-Labs/nac3
nac3core: self is not not allowed to explicitly appear in method type annotations
This commit is contained in:
parent
1300b5ebdd
commit
5a1a8ecee3
|
@ -135,6 +135,7 @@ impl TopLevelComposer {
|
||||||
"bool".into(),
|
"bool".into(),
|
||||||
"none".into(),
|
"none".into(),
|
||||||
"None".into(),
|
"None".into(),
|
||||||
|
"self".into(),
|
||||||
]),
|
]),
|
||||||
defined_class_method_name: Default::default(),
|
defined_class_method_name: Default::default(),
|
||||||
defined_class_name: Default::default(),
|
defined_class_name: Default::default(),
|
||||||
|
@ -586,11 +587,9 @@ impl TopLevelComposer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// println!("type_var_to_concrete_def2: {:?}", type_var_to_concrete_def);
|
println!("type_var_to_concrete_def3: {:?}\n", type_var_to_concrete_def);
|
||||||
|
|
||||||
// unification of previously assigned typevar
|
// unification of previously assigned typevar
|
||||||
println!("type_var_to_concrete_def3: {:?}\n", type_var_to_concrete_def);
|
|
||||||
let mut ddddd: Vec<(Type, Type)> = Vec::new();
|
|
||||||
for (ty, def) in type_var_to_concrete_def {
|
for (ty, def) in type_var_to_concrete_def {
|
||||||
println!(
|
println!(
|
||||||
"{:?}_{} -> {:?}\n",
|
"{:?}_{} -> {:?}\n",
|
||||||
|
@ -604,23 +603,6 @@ impl TopLevelComposer {
|
||||||
let target_ty =
|
let target_ty =
|
||||||
get_type_from_type_annotation_kinds(&temp_def_list, unifier, primitives, &def)?;
|
get_type_from_type_annotation_kinds(&temp_def_list, unifier, primitives, &def)?;
|
||||||
unifier.unify(ty, target_ty)?;
|
unifier.unify(ty, target_ty)?;
|
||||||
ddddd.push((ty, target_ty));
|
|
||||||
}
|
|
||||||
|
|
||||||
for (ty, tar_ty) in ddddd {
|
|
||||||
println!(
|
|
||||||
"{:?}_{} -> {:?}_{}",
|
|
||||||
ty,
|
|
||||||
unifier.stringify(ty,
|
|
||||||
&mut |id| format!("class{}", id),
|
|
||||||
&mut |id| format!("tvar{}", id)
|
|
||||||
),
|
|
||||||
tar_ty,
|
|
||||||
unifier.stringify(tar_ty,
|
|
||||||
&mut |id| format!("class{}", id),
|
|
||||||
&mut |id| format!("tvar{}", id)
|
|
||||||
),
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -793,7 +775,7 @@ impl TopLevelComposer {
|
||||||
) -> Result<(), String> {
|
) -> Result<(), String> {
|
||||||
let mut class_def = class_def.write();
|
let mut class_def = class_def.write();
|
||||||
let (
|
let (
|
||||||
class_id,
|
_class_id,
|
||||||
_class_name,
|
_class_name,
|
||||||
_class_bases_ast,
|
_class_bases_ast,
|
||||||
class_body_ast,
|
class_body_ast,
|
||||||
|
@ -862,16 +844,10 @@ impl TopLevelComposer {
|
||||||
and names thould not be the same as the keywords"
|
and names thould not be the same as the keywords"
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
if name == "__init__" && !defined_paramter_name.contains("self") {
|
|
||||||
return Err(
|
|
||||||
"class __init__ function must contain the `self` parameter".into()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut result = Vec::new();
|
let mut result = Vec::new();
|
||||||
for x in &args.args {
|
for x in &args.args {
|
||||||
let name = x.node.arg.clone();
|
let name = x.node.arg.clone();
|
||||||
if name != "self" {
|
|
||||||
let type_ann = {
|
let type_ann = {
|
||||||
let annotation_expr = x
|
let annotation_expr = x
|
||||||
.node
|
.node
|
||||||
|
@ -887,7 +863,6 @@ impl TopLevelComposer {
|
||||||
annotation_expr,
|
annotation_expr,
|
||||||
)?
|
)?
|
||||||
};
|
};
|
||||||
|
|
||||||
// find type vars within this method parameter type annotation
|
// find type vars within this method parameter type annotation
|
||||||
let type_vars_within =
|
let type_vars_within =
|
||||||
get_type_var_contained_in_type_annotation(&type_ann);
|
get_type_var_contained_in_type_annotation(&type_ann);
|
||||||
|
@ -903,7 +878,6 @@ impl TopLevelComposer {
|
||||||
unreachable!("must be type var annotation");
|
unreachable!("must be type var annotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// finish handling type vars
|
// finish handling type vars
|
||||||
let dummy_func_arg = FuncArg {
|
let dummy_func_arg = FuncArg {
|
||||||
name,
|
name,
|
||||||
|
@ -915,28 +889,11 @@ impl TopLevelComposer {
|
||||||
// into the list for later unification
|
// into the list for later unification
|
||||||
type_var_to_concrete_def.insert(dummy_func_arg.ty, type_ann.clone());
|
type_var_to_concrete_def.insert(dummy_func_arg.ty, type_ann.clone());
|
||||||
result.push(dummy_func_arg)
|
result.push(dummy_func_arg)
|
||||||
} else {
|
|
||||||
// if the parameter name is self
|
|
||||||
// python does not seem to enforce the name
|
|
||||||
// representing the self class object to be
|
|
||||||
// `self`??, but we do it here
|
|
||||||
let dummy_func_arg = FuncArg {
|
|
||||||
name: "self".into(),
|
|
||||||
ty: unifier.get_fresh_var().0,
|
|
||||||
default_value: None,
|
|
||||||
};
|
|
||||||
type_var_to_concrete_def.insert(
|
|
||||||
dummy_func_arg.ty,
|
|
||||||
make_self_type_annotation(class_type_vars_def.as_slice(), class_id),
|
|
||||||
);
|
|
||||||
result.push(dummy_func_arg);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
result
|
result
|
||||||
};
|
};
|
||||||
|
|
||||||
let ret_type = {
|
let ret_type = {
|
||||||
if name != "__init__" {
|
|
||||||
if let Some(result) = returns {
|
if let Some(result) = returns {
|
||||||
let result = result.as_ref();
|
let result = result.as_ref();
|
||||||
let annotation = parse_ast_to_type_annotation_kinds(
|
let annotation = parse_ast_to_type_annotation_kinds(
|
||||||
|
@ -946,7 +903,6 @@ impl TopLevelComposer {
|
||||||
primitives,
|
primitives,
|
||||||
result,
|
result,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// find type vars within this return type annotation
|
// find type vars within this return type annotation
|
||||||
let type_vars_within =
|
let type_vars_within =
|
||||||
get_type_var_contained_in_type_annotation(&annotation);
|
get_type_var_contained_in_type_annotation(&annotation);
|
||||||
|
@ -962,7 +918,6 @@ impl TopLevelComposer {
|
||||||
unreachable!("must be type var annotation");
|
unreachable!("must be type var annotation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let dummy_return_type = unifier.get_fresh_var().0;
|
let dummy_return_type = unifier.get_fresh_var().0;
|
||||||
type_var_to_concrete_def.insert(dummy_return_type, annotation.clone());
|
type_var_to_concrete_def.insert(dummy_return_type, annotation.clone());
|
||||||
dummy_return_type
|
dummy_return_type
|
||||||
|
@ -976,15 +931,6 @@ impl TopLevelComposer {
|
||||||
);
|
);
|
||||||
dummy_return_type
|
dummy_return_type
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// if is the "__init__" function, the return type is self
|
|
||||||
let dummy_return_type = unifier.get_fresh_var().0;
|
|
||||||
type_var_to_concrete_def.insert(
|
|
||||||
dummy_return_type,
|
|
||||||
make_self_type_annotation(class_type_vars_def.as_slice(), class_id),
|
|
||||||
);
|
|
||||||
dummy_return_type
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if let TopLevelDef::Function { var_id, .. } =
|
if let TopLevelDef::Function { var_id, .. } =
|
||||||
|
@ -1042,6 +988,7 @@ impl TopLevelComposer {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: allow class have field which type refers to Self type?
|
||||||
type_var_to_concrete_def
|
type_var_to_concrete_def
|
||||||
.insert(dummy_field_type, annotation);
|
.insert(dummy_field_type, annotation);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -156,23 +156,23 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
vec![
|
vec![
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class A():
|
class A():
|
||||||
def __init__(self):
|
def __init__():
|
||||||
self.a: int32 = 3
|
self.a: int32 = 3
|
||||||
def fun(self, b: B):
|
def fun(b: B):
|
||||||
pass
|
pass
|
||||||
def foo(self, a: T, b: V):
|
def foo(a: T, b: V):
|
||||||
pass
|
pass
|
||||||
"},
|
"},
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class B(C):
|
class B(C):
|
||||||
def __init__(self):
|
def __init__():
|
||||||
pass
|
pass
|
||||||
"},
|
"},
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class C(A):
|
class C(A):
|
||||||
def __init__(self):
|
def __init__():
|
||||||
pass
|
pass
|
||||||
def fun(self, b: B):
|
def fun(b: B):
|
||||||
a = 1
|
a = 1
|
||||||
pass
|
pass
|
||||||
"},
|
"},
|
||||||
|
@ -190,82 +190,149 @@ fn test_simple_function_analyze(source: Vec<&str>, tys: Vec<&str>, names: Vec<&s
|
||||||
name: \"A\",
|
name: \"A\",
|
||||||
def_id: DefinitionId(5),
|
def_id: DefinitionId(5),
|
||||||
ancestors: [CustomClassKind { id: DefinitionId(5), params: [] }],
|
ancestors: [CustomClassKind { id: DefinitionId(5), params: [] }],
|
||||||
fields: [(\"a\", \"0\")],
|
fields: [(\"a\", \"class0\")],
|
||||||
methods: [(\"__init__\", \"fn[[self=5], 5]\", DefinitionId(6)), (\"fun\", \"fn[[self=5, b=9], 4]\", DefinitionId(7))],
|
methods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(6)), (\"fun\", \"fn[[b=class10], class4]\", DefinitionId(7)), (\"foo\", \"fn[[a=tvar2, b=tvar3], class4]\", DefinitionId(8))],
|
||||||
type_vars: []
|
type_vars: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"6: Function {
|
indoc! {"6: Function {
|
||||||
name: \"A__init__\",
|
name: \"A__init__\",
|
||||||
sig: \"fn[[self=5], 5]\",
|
sig: \"fn[[], class4]\",
|
||||||
var_id: []
|
var_id: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"7: Function {
|
indoc! {"7: Function {
|
||||||
name: \"Afun\",
|
name: \"Afun\",
|
||||||
sig: \"fn[[self=5, b=9], 4]\",
|
sig: \"fn[[b=class10], class4]\",
|
||||||
var_id: []
|
var_id: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"8: Initializer { DefinitionId(5) }"},
|
indoc! {"8: Function {
|
||||||
|
name: \"Afoo\",
|
||||||
|
sig: \"fn[[a=tvar2, b=tvar3], class4]\",
|
||||||
|
var_id: [2, 3]
|
||||||
|
}"},
|
||||||
|
|
||||||
indoc! {"9: Class {
|
indoc! {"9: Initializer { DefinitionId(5) }"},
|
||||||
|
|
||||||
|
indoc! {"10: Class {
|
||||||
name: \"B\",
|
name: \"B\",
|
||||||
def_id: DefinitionId(9),
|
def_id: DefinitionId(10),
|
||||||
ancestors: [CustomClassKind { id: DefinitionId(9), params: [] }, CustomClassKind { id: DefinitionId(12), params: [] }, CustomClassKind { id: DefinitionId(5), params: [] }],
|
ancestors: [CustomClassKind { id: DefinitionId(10), params: [] }, CustomClassKind { id: DefinitionId(13), params: [] }, CustomClassKind { id: DefinitionId(5), params: [] }],
|
||||||
fields: [(\"a\", \"0\")],
|
fields: [(\"a\", \"class0\")],
|
||||||
methods: [(\"__init__\", \"fn[[self=9], 9]\", DefinitionId(10)), (\"fun\", \"fn[[self=12, b=9], 4]\", DefinitionId(14))],
|
methods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(11)), (\"fun\", \"fn[[b=class10], class4]\", DefinitionId(15)), (\"foo\", \"fn[[a=tvar2, b=tvar3], class4]\", DefinitionId(8))],
|
||||||
type_vars: []
|
type_vars: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"10: Function {
|
indoc! {"11: Function {
|
||||||
name: \"B__init__\",
|
name: \"B__init__\",
|
||||||
sig: \"fn[[self=9], 9]\",
|
sig: \"fn[[], class4]\",
|
||||||
var_id: []
|
var_id: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"11: Initializer { DefinitionId(9) }"},
|
indoc! {"12: Initializer { DefinitionId(10) }"},
|
||||||
|
|
||||||
indoc! {"12: Class {
|
indoc! {"13: Class {
|
||||||
name: \"C\",
|
name: \"C\",
|
||||||
def_id: DefinitionId(12),
|
def_id: DefinitionId(13),
|
||||||
ancestors: [CustomClassKind { id: DefinitionId(12), params: [] }, CustomClassKind { id: DefinitionId(5), params: [] }],
|
ancestors: [CustomClassKind { id: DefinitionId(13), params: [] }, CustomClassKind { id: DefinitionId(5), params: [] }],
|
||||||
fields: [(\"a\", \"0\")],
|
fields: [(\"a\", \"class0\")],
|
||||||
methods: [(\"__init__\", \"fn[[self=12], 12]\", DefinitionId(13)), (\"fun\", \"fn[[self=12, b=9], 4]\", DefinitionId(14))],
|
methods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(14)), (\"fun\", \"fn[[b=class10], class4]\", DefinitionId(15)), (\"foo\", \"fn[[a=tvar2, b=tvar3], class4]\", DefinitionId(8))],
|
||||||
type_vars: []
|
type_vars: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"13: Function {
|
|
||||||
name: \"C__init__\",
|
|
||||||
sig: \"fn[[self=12], 12]\",
|
|
||||||
var_id: []
|
|
||||||
}"},
|
|
||||||
|
|
||||||
indoc! {"14: Function {
|
indoc! {"14: Function {
|
||||||
name: \"Cfun\",
|
name: \"C__init__\",
|
||||||
sig: \"fn[[self=12, b=9], 4]\",
|
sig: \"fn[[], class4]\",
|
||||||
var_id: []
|
var_id: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
indoc! {"15: Initializer { DefinitionId(12) }"},
|
indoc! {"15: Function {
|
||||||
|
name: \"Cfun\",
|
||||||
indoc! {"16: Function {
|
sig: \"fn[[b=class10], class4]\",
|
||||||
name: \"foo\",
|
|
||||||
sig: \"fn[[a=5], 4]\",
|
|
||||||
var_id: []
|
var_id: []
|
||||||
}"},
|
}"},
|
||||||
|
|
||||||
|
indoc! {"16: Initializer { DefinitionId(13) }"},
|
||||||
|
|
||||||
|
indoc! {"17: Function {
|
||||||
|
name: \"foo\",
|
||||||
|
sig: \"fn[[a=class5], class4]\",
|
||||||
|
var_id: []
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"18: Function {
|
||||||
|
name: \"ff\",
|
||||||
|
sig: \"fn[[a=tvar2], tvar3]\",
|
||||||
|
var_id: [2, 3]
|
||||||
|
}"},
|
||||||
];
|
];
|
||||||
"simple class compose"
|
"simple class compose"
|
||||||
)]
|
)]
|
||||||
#[test_case(
|
#[test_case(
|
||||||
vec![
|
vec![
|
||||||
indoc! {"
|
indoc! {"
|
||||||
class Generic_A(Generic[T, V]):
|
class Generic_A(Generic[V], B):
|
||||||
def __init__():
|
def __init__():
|
||||||
|
self.a: int64 = 123123123123
|
||||||
|
def fun(a: int32) -> V:
|
||||||
|
pass
|
||||||
|
"},
|
||||||
|
indoc! {"
|
||||||
|
class B:
|
||||||
|
def __init__():
|
||||||
|
self.aa: bool = False
|
||||||
|
def foo(b: T):
|
||||||
pass
|
pass
|
||||||
"}
|
"}
|
||||||
],
|
],
|
||||||
vec![];
|
vec![
|
||||||
|
indoc! {"5: Class {
|
||||||
|
name: \"Generic_A\",
|
||||||
|
def_id: DefinitionId(5),
|
||||||
|
ancestors: [CustomClassKind { id: DefinitionId(5), params: [TypeVarKind(UnificationKey(101))] }, CustomClassKind { id: DefinitionId(9), params: [] }],
|
||||||
|
fields: [(\"aa\", \"class3\"), (\"a\", \"class1\")],
|
||||||
|
methods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(6)), (\"foo\", \"fn[[b=tvar2], class4]\", DefinitionId(11)), (\"fun\", \"fn[[a=class0], tvar3]\", DefinitionId(7))],
|
||||||
|
type_vars: [UnificationKey(101)]
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"6: Function {
|
||||||
|
name: \"Generic_A__init__\",
|
||||||
|
sig: \"fn[[], class4]\",
|
||||||
|
var_id: [3]
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"7: Function {
|
||||||
|
name: \"Generic_Afun\",
|
||||||
|
sig: \"fn[[a=class0], tvar3]\",
|
||||||
|
var_id: [3]
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"8: Initializer { DefinitionId(5) }"},
|
||||||
|
|
||||||
|
indoc! {"9: Class {
|
||||||
|
name: \"B\",
|
||||||
|
def_id: DefinitionId(9),
|
||||||
|
ancestors: [CustomClassKind { id: DefinitionId(9), params: [] }],
|
||||||
|
fields: [(\"aa\", \"class3\")],
|
||||||
|
methods: [(\"__init__\", \"fn[[], class4]\", DefinitionId(10)), (\"foo\", \"fn[[b=tvar2], class4]\", DefinitionId(11))],
|
||||||
|
type_vars: []
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"10: Function {
|
||||||
|
name: \"B__init__\",
|
||||||
|
sig: \"fn[[], class4]\",
|
||||||
|
var_id: []
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"11: Function {
|
||||||
|
name: \"Bfoo\",
|
||||||
|
sig: \"fn[[b=tvar2], class4]\",
|
||||||
|
var_id: [2]
|
||||||
|
}"},
|
||||||
|
|
||||||
|
indoc! {"12: Initializer { DefinitionId(9) }"},
|
||||||
|
];
|
||||||
"generic class"
|
"generic class"
|
||||||
)]
|
)]
|
||||||
fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
|
fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
|
||||||
|
@ -275,6 +342,7 @@ fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
|
||||||
let tvar_v = composer
|
let tvar_v = composer
|
||||||
.unifier
|
.unifier
|
||||||
.get_fresh_var_with_range(&[composer.primitives_ty.bool, composer.primitives_ty.int32]);
|
.get_fresh_var_with_range(&[composer.primitives_ty.bool, composer.primitives_ty.int32]);
|
||||||
|
|
||||||
println!("t: {}, {:?}", tvar_t.1, tvar_t.0);
|
println!("t: {}, {:?}", tvar_t.1, tvar_t.0);
|
||||||
println!("v: {}, {:?}\n", tvar_v.1, tvar_v.0);
|
println!("v: {}, {:?}\n", tvar_v.1, tvar_v.0);
|
||||||
|
|
||||||
|
@ -311,17 +379,17 @@ fn test_simple_class_analyze(source: Vec<&str>, res: Vec<&str>) {
|
||||||
// &mut |id| format!("tvar{}", id)
|
// &mut |id| format!("tvar{}", id)
|
||||||
// )
|
// )
|
||||||
// );
|
// );
|
||||||
// assert_eq!(
|
assert_eq!(
|
||||||
// format!(
|
format!(
|
||||||
// "{}: {}",
|
"{}: {}",
|
||||||
// i + 5,
|
i + 5,
|
||||||
// def.to_string(
|
def.to_string(
|
||||||
// composer.unifier.borrow_mut(),
|
composer.unifier.borrow_mut(),
|
||||||
// &mut |id| id.to_string(),
|
&mut |id| format!("class{}", id.to_string()),
|
||||||
// &mut |id| id.to_string()
|
&mut |id| format!("tvar{}", id.to_string()),
|
||||||
// )
|
)
|
||||||
// ),
|
),
|
||||||
// res[i]
|
res[i]
|
||||||
// )
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue