1
0
forked from M-Labs/nac3

nac3core: self is not not allowed to explicitly appear in method type annotations

This commit is contained in:
ychenfo 2021-09-08 21:53:54 +08:00
parent 1300b5ebdd
commit 5a1a8ecee3
2 changed files with 190 additions and 175 deletions

View File

@ -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,126 +844,90 @@ 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 .annotation
.annotation .as_ref()
.as_ref() .ok_or_else(|| "type annotation needed".to_string())?
.ok_or_else(|| "type annotation needed".to_string())? .as_ref();
.as_ref(); parse_ast_to_type_annotation_kinds(
parse_ast_to_type_annotation_kinds( class_resolver.as_ref(),
class_resolver.as_ref(), temp_def_list,
temp_def_list, unifier,
unifier, primitives,
primitives, annotation_expr,
annotation_expr, )?
)? };
}; // find type vars within this method parameter type annotation
let type_vars_within =
// find type vars within this method parameter type annotation get_type_var_contained_in_type_annotation(&type_ann);
let type_vars_within = // handle the class type var and the method type var
get_type_var_contained_in_type_annotation(&type_ann); for type_var_within in type_vars_within {
// handle the class type var and the method type var if let TypeAnnotation::TypeVarKind(ty) = type_var_within {
for type_var_within in type_vars_within { let id = Self::get_var_id(ty, unifier)?;
if let TypeAnnotation::TypeVarKind(ty) = type_var_within { if let Some(prev_ty) = method_var_map.insert(id, ty) {
let id = Self::get_var_id(ty, unifier)?; // if already in the list, make sure they are the same?
if let Some(prev_ty) = method_var_map.insert(id, ty) { assert_eq!(prev_ty, ty);
// if already in the list, make sure they are the same?
assert_eq!(prev_ty, ty);
}
} else {
unreachable!("must be type var annotation");
} }
} else {
unreachable!("must be type var annotation");
} }
// finish handling type vars
let dummy_func_arg = FuncArg {
name,
ty: unifier.get_fresh_var().0,
// TODO: symbol default value?
default_value: None,
};
// push the dummy type and the type annotation
// into the list for later unification
type_var_to_concrete_def.insert(dummy_func_arg.ty, type_ann.clone());
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);
} }
// finish handling type vars
let dummy_func_arg = FuncArg {
name,
ty: unifier.get_fresh_var().0,
// TODO: symbol default value?
default_value: None,
};
// push the dummy type and the type annotation
// into the list for later unification
type_var_to_concrete_def.insert(dummy_func_arg.ty, type_ann.clone());
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( class_resolver.as_ref(),
class_resolver.as_ref(), temp_def_list,
temp_def_list, unifier,
unifier, primitives,
primitives, result,
result, )?;
)?; // find type vars within this return type annotation
let type_vars_within =
// find type vars within this return type annotation get_type_var_contained_in_type_annotation(&annotation);
let type_vars_within = // handle the class type var and the method type var
get_type_var_contained_in_type_annotation(&annotation); for type_var_within in type_vars_within {
// handle the class type var and the method type var if let TypeAnnotation::TypeVarKind(ty) = type_var_within {
for type_var_within in type_vars_within { let id = Self::get_var_id(ty, unifier)?;
if let TypeAnnotation::TypeVarKind(ty) = type_var_within { if let Some(prev_ty) = method_var_map.insert(id, ty) {
let id = Self::get_var_id(ty, unifier)?; // if already in the list, make sure they are the same?
if let Some(prev_ty) = method_var_map.insert(id, ty) { assert_eq!(prev_ty, ty);
// if already in the list, make sure they are the same?
assert_eq!(prev_ty, ty);
}
} else {
unreachable!("must be type var annotation");
} }
} else {
unreachable!("must be type var annotation");
} }
let dummy_return_type = unifier.get_fresh_var().0;
type_var_to_concrete_def.insert(dummy_return_type, annotation.clone());
dummy_return_type
} else {
// if do not have return annotation, return none
// for uniform handling, still use type annoatation
let dummy_return_type = unifier.get_fresh_var().0;
type_var_to_concrete_def.insert(
dummy_return_type,
TypeAnnotation::PrimitiveKind(primitives.none),
);
dummy_return_type
} }
let dummy_return_type = unifier.get_fresh_var().0;
type_var_to_concrete_def.insert(dummy_return_type, annotation.clone());
dummy_return_type
} else { } else {
// if is the "__init__" function, the return type is self // if do not have return annotation, return none
// for uniform handling, still use type annoatation
let dummy_return_type = unifier.get_fresh_var().0; let dummy_return_type = unifier.get_fresh_var().0;
type_var_to_concrete_def.insert( type_var_to_concrete_def.insert(
dummy_return_type, dummy_return_type,
make_self_type_annotation(class_type_vars_def.as_slice(), class_id), TypeAnnotation::PrimitiveKind(primitives.none),
); );
dummy_return_type dummy_return_type
} }
@ -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 {

View File

@ -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]
// ) )
} }
} }