@@ -115,9 +115,20 @@ defmodule Module.Types.Expr do
115115
116116 # %{map | ...}
117117 # TODO: Once we support typed structs, we need to type check them here.
118- def of_expr ( { :%{} , _ , [ { :| , _ , [ map , args ] } ] } , stack , context ) do
118+ def of_expr ( { :%{} , meta , [ { :| , _ , [ map , args ] } ] } = expr , stack , context ) do
119119 { map_type , context } = of_expr ( map , stack , context )
120- Of . update_map ( map_type , args , stack , context , & of_expr / 3 )
120+
121+ Of . permutate_map ( args , stack , context , & of_expr / 3 , fn _closed? , pairs ->
122+ # TODO: If closed? is false, we need to open up the map
123+ Enum . reduce ( pairs , map_type , fn { key , type } , acc ->
124+ case map_put ( acc , key , type ) do
125+ descr when is_descr ( descr ) -> descr
126+ :badmap -> throw ( { :badmap , map_type , expr , context } )
127+ end
128+ end )
129+ end )
130+ catch
131+ error -> { error_type ( ) , error ( __MODULE__ , error , meta , stack , context ) }
121132 end
122133
123134 # %Struct{map | ...}
@@ -134,7 +145,7 @@ defmodule Module.Types.Expr do
134145 { map_type , context } = of_expr ( map , stack , context )
135146
136147 if disjoint? ( struct_type , map_type ) do
137- warning = { :badupdate , :struct , expr , struct_type , map_type , context }
148+ warning = { :badstruct , expr , struct_type , map_type , context }
138149 { error_type ( ) , error ( __MODULE__ , warning , update_meta , stack , context ) }
139150 else
140151 map_type = map_put! ( map_type , :__struct__ , atom ( [ module ] ) )
@@ -522,15 +533,15 @@ defmodule Module.Types.Expr do
522533
523534 ## Warning formatting
524535
525- def format_diagnostic ( { :badupdate , type , expr , expected_type , actual_type , context } ) do
536+ def format_diagnostic ( { :badstruct , expr , expected_type , actual_type , context } ) do
526537 traces = collect_traces ( expr , context )
527538
528539 % {
529540 details: % { typing_traces: traces } ,
530541 message:
531542 IO . iodata_to_binary ( [
532543 """
533- incompatible types in #{ type } update:
544+ incompatible types in struct update:
534545
535546 #{ expr_to_string ( expr ) |> indent ( 4 ) }
536547
@@ -547,6 +558,27 @@ defmodule Module.Types.Expr do
547558 }
548559 end
549560
561+ def format_diagnostic ( { :badmap , type , expr , context } ) do
562+ traces = collect_traces ( expr , context )
563+
564+ % {
565+ details: % { typing_traces: traces } ,
566+ message:
567+ IO . iodata_to_binary ( [
568+ """
569+ expected a map within map update syntax:
570+
571+ #{ expr_to_string ( expr ) |> indent ( 4 ) }
572+
573+ but got type:
574+
575+ #{ to_quoted_string ( type ) |> indent ( 4 ) }
576+ """ ,
577+ format_traces ( traces )
578+ ] )
579+ }
580+ end
581+
550582 def format_diagnostic ( { :badbinary , type , expr , context } ) do
551583 traces = collect_traces ( expr , context )
552584
0 commit comments