@@ -23,6 +23,7 @@ use super::traits::CustomType;
2323
2424use crate :: ast:: builder:: BuilderEnum ;
2525use crate :: ast:: builder:: IRBuilder ;
26+ use crate :: format_label;
2627use crate :: lsp:: semantic_tokens:: type_index;
2728
2829use crate :: mismatch_err;
@@ -214,14 +215,46 @@ impl<'a, 'ctx> Ctx<'a> {
214215 }
215216 pub fn up_cast < ' b > (
216217 & mut self ,
217- trait_pltype : Arc < RefCell < PLType > > ,
218- st_pltype : Arc < RefCell < PLType > > ,
219- trait_range : Range ,
220- st_range : Range ,
221- st_value : usize ,
218+ target_pltype : Arc < RefCell < PLType > > ,
219+ ori_pltype : Arc < RefCell < PLType > > ,
220+ target_range : Range ,
221+ ori_range : Range ,
222+ ori_value : usize ,
222223 builder : & ' b BuilderEnum < ' a , ' ctx > ,
223224 ) -> Result < usize , PLDiag > {
224- if let PLType :: Union ( u) = & * trait_pltype. borrow ( ) {
225+ if let ( PLType :: Closure ( c) , PLType :: Fn ( f) ) =
226+ ( & * target_pltype. borrow ( ) , & * ori_pltype. borrow ( ) )
227+ {
228+ if f. to_closure_ty ( self , builder) != * c {
229+ return Err ( ori_range
230+ . new_err ( ErrorCode :: FUNCTION_TYPE_NOT_MATCH )
231+ . add_label (
232+ target_range,
233+ self . get_file ( ) ,
234+ format_label ! ( "expected type `{}`" , c. get_name( ) ) ,
235+ )
236+ . add_label (
237+ ori_range,
238+ self . get_file ( ) ,
239+ format_label ! ( "found type `{}`" , f. to_closure_ty( self , builder) . get_name( ) ) ,
240+ )
241+ . add_to_ctx ( self ) ) ;
242+ }
243+ if ori_value == usize:: MAX {
244+ return Err ( ori_range
245+ . new_err ( ErrorCode :: CANNOT_ASSIGN_INCOMPLETE_GENERICS )
246+ . add_help ( "try add generic type explicitly to fix this error." )
247+ . add_to_ctx ( self ) ) ;
248+ }
249+ let closure_v = builder. alloc ( "tmp" , & target_pltype. borrow ( ) , self , None ) ;
250+ let closure_f = builder. build_struct_gep ( closure_v, 0 , "closure_f" ) . unwrap ( ) ;
251+ let ori_value = builder. try_load2var ( ori_range, ori_value, self ) ?;
252+ // TODO now, we only handle the case that the closure is a pure function.
253+ // TODO the real closure case is leave to the future.
254+ builder. build_store ( closure_f, ori_value) ;
255+ return Ok ( closure_v) ;
256+ }
257+ if let PLType :: Union ( u) = & * target_pltype. borrow ( ) {
225258 let union_members = self . run_in_type_mod ( u, |ctx, u| {
226259 let mut union_members = vec ! [ ] ;
227260 for tp in & u. sum_types {
@@ -231,9 +264,9 @@ impl<'a, 'ctx> Ctx<'a> {
231264 Ok ( union_members)
232265 } ) ?;
233266 for ( i, tp) in union_members. iter ( ) . enumerate ( ) {
234- if * tp. borrow ( ) == * st_pltype . borrow ( ) {
267+ if * tp. borrow ( ) == * ori_pltype . borrow ( ) {
235268 let union_handle =
236- builder. alloc ( "tmp_unionv" , & trait_pltype . borrow ( ) , self , None ) ;
269+ builder. alloc ( "tmp_unionv" , & target_pltype . borrow ( ) , self , None ) ;
237270 let union_value = builder
238271 . build_struct_gep ( union_handle, 1 , "union_value" )
239272 . unwrap ( ) ;
@@ -242,11 +275,11 @@ impl<'a, 'ctx> Ctx<'a> {
242275 . unwrap ( ) ;
243276 let union_type = builder. int_value ( & PriType :: U64 , i as u64 , false ) ;
244277 builder. build_store ( union_type_field, union_type) ;
245- let mut ptr = st_value ;
246- if !builder. is_ptr ( st_value ) {
278+ let mut ptr = ori_value ;
279+ if !builder. is_ptr ( ori_value ) {
247280 // mv to heap
248- ptr = builder. alloc ( "tmp" , & st_pltype . borrow ( ) , self , None ) ;
249- builder. build_store ( ptr, st_value ) ;
281+ ptr = builder. alloc ( "tmp" , & ori_pltype . borrow ( ) , self , None ) ;
282+ builder. build_store ( ptr, ori_value ) ;
250283 }
251284 let st_value = builder. bitcast (
252285 self ,
@@ -260,20 +293,20 @@ impl<'a, 'ctx> Ctx<'a> {
260293 }
261294 }
262295 }
263- let ( st_pltype, st_value) = self . auto_deref ( st_pltype , st_value , builder) ;
296+ let ( st_pltype, st_value) = self . auto_deref ( ori_pltype , ori_value , builder) ;
264297 if let ( PLType :: Trait ( t) , PLType :: Struct ( st) ) =
265- ( & * trait_pltype . borrow ( ) , & * st_pltype. borrow ( ) )
298+ ( & * target_pltype . borrow ( ) , & * st_pltype. borrow ( ) )
266299 {
267300 if !st. implements_trait ( t, & self . plmod ) {
268301 return Err ( mismatch_err ! (
269302 self ,
270- st_range ,
271- trait_range ,
272- trait_pltype . borrow( ) ,
303+ ori_range ,
304+ target_range ,
305+ target_pltype . borrow( ) ,
273306 st_pltype. borrow( )
274307 ) ) ;
275308 }
276- let trait_handle = builder. alloc ( "tmp_traitv" , & trait_pltype . borrow ( ) , self , None ) ;
309+ let trait_handle = builder. alloc ( "tmp_traitv" , & target_pltype . borrow ( ) , self , None ) ;
277310 for f in t. list_trait_fields ( ) . iter ( ) {
278311 let mthd = st. find_method ( self , & f. name ) . unwrap ( ) ;
279312 let fnhandle = builder. get_or_insert_fn_handle ( & mthd, self ) ;
@@ -303,9 +336,9 @@ impl<'a, 'ctx> Ctx<'a> {
303336 #[ allow( clippy:: needless_return) ]
304337 return Err ( mismatch_err ! (
305338 self ,
306- st_range ,
307- trait_range ,
308- trait_pltype . borrow( ) ,
339+ ori_range ,
340+ target_range ,
341+ target_pltype . borrow( ) ,
309342 st_pltype. borrow( )
310343 ) ) ;
311344 }
@@ -807,6 +840,7 @@ impl<'a, 'ctx> Ctx<'a> {
807840 PLType :: Pointer ( _) => unreachable ! ( ) ,
808841 PLType :: PlaceHolder ( _) => CompletionItemKind :: STRUCT ,
809842 PLType :: Union ( _) => CompletionItemKind :: ENUM ,
843+ PLType :: Closure ( _) => unreachable ! ( ) ,
810844 } ;
811845 if k. starts_with ( '|' ) {
812846 // skip method
0 commit comments