@@ -338,10 +338,10 @@ defmodule Module.Types.Expr do
338338 end
339339
340340 # TODO: for pat <- expr do expr end
341- def of_expr ( { :for , _meta , [ _ | _ ] = args } , stack , context ) do
341+ def of_expr ( { :for , meta , [ _ | _ ] = args } , stack , context ) do
342342 { clauses , [ [ { :do , block } | opts ] ] } = Enum . split ( args , - 1 )
343343 context = Enum . reduce ( clauses , context , & for_clause ( & 1 , stack , & 2 ) )
344- context = Enum . reduce ( opts , context , & for_option ( & 1 , stack , & 2 ) )
344+ context = Enum . reduce ( opts , context , & for_option ( & 1 , meta , stack , & 2 ) )
345345
346346 if Keyword . has_key? ( opts , :reduce ) do
347347 { _ , context } = of_clauses ( block , [ dynamic ( ) ] , :for_reduce , stack , { none ( ) , context } )
@@ -471,13 +471,17 @@ defmodule Module.Types.Expr do
471471
472472 ## Comprehensions
473473
474- defp for_clause ( { :<- , _ , [ left , right ] } = expr , stack , context ) do
474+ defp for_clause ( { :<- , meta , [ left , right ] } , stack , context ) do
475+ expr = { :<- , [ type_check: :generator ] ++ meta , [ left , right ] }
475476 { pattern , guards } = extract_head ( [ left ] )
476- { _ , context } = of_expr ( right , stack , context )
477+ { type , context } = of_expr ( right , stack , context )
477478
478479 { _type , context } =
479480 Pattern . of_match ( pattern , guards , dynamic ( ) , expr , :for , stack , context )
480481
482+ { _type , context } =
483+ Apply . remote ( Enumerable , :count , [ right ] , [ type ] , expr , stack , context )
484+
481485 context
482486 end
483487
@@ -500,17 +504,34 @@ defmodule Module.Types.Expr do
500504 context
501505 end
502506
503- defp for_option ( { :into , expr } , stack , context ) do
504- { _type , context } = of_expr ( expr , stack , context )
507+ defp for_option ( { :into , expr } , _meta , _stack , context ) when is_list ( expr ) or is_binary ( expr ) do
508+ context
509+ end
510+
511+ defp for_option ( { :into , expr } , meta , stack , context ) do
512+ { type , context } = of_expr ( expr , stack , context )
513+
514+ meta =
515+ case expr do
516+ { _ , meta , _ } -> meta
517+ _ -> meta
518+ end
519+
520+ wrapped_expr = { :__block__ , [ type_check: :into ] ++ meta , [ expr ] }
521+
522+ { _type , context } =
523+ Apply . remote ( Collectable , :into , [ expr ] , [ type ] , wrapped_expr , stack , context )
524+
505525 context
506526 end
507527
508- defp for_option ( { :reduce , expr } , stack , context ) do
528+ defp for_option ( { :reduce , expr } , _meta , stack , context ) do
509529 { _type , context } = of_expr ( expr , stack , context )
510530 context
511531 end
512532
513- defp for_option ( { :uniq , _ } , _stack , context ) do
533+ defp for_option ( { :uniq , _ } , _meta , _stack , context ) do
534+ # This option is verified to be a boolean at compile-time
514535 context
515536 end
516537
0 commit comments