@@ -1394,6 +1394,52 @@ expect_tuple_union([], AccTy, AccCs, _NoAny, _N, _Env) ->
1394
1394
{AccTy , AccCs }.
1395
1395
1396
1396
1397
+ - spec expect_binary_type (type (), env ()) -> R when
1398
+ R :: any
1399
+ | {elem_ty , type (), constraints ()}
1400
+ | {elem_tys , [type ()], constraints ()}
1401
+ | {type_error , type ()}.
1402
+ expect_binary_type (? type (any ), _ ) ->
1403
+ any ;
1404
+ expect_binary_type (ElemTy = {type , _ , binary , _ }, _ ) ->
1405
+ {elem_ty , ElemTy , constraints :empty ()};
1406
+ expect_binary_type (Union = {type , _ , union , UnionTys }, Env ) ->
1407
+ {Tys , Cs } = expect_binary_union (UnionTys , [], constraints :empty (), Env ),
1408
+ case Tys of
1409
+ [] ->
1410
+ {type_error , Union };
1411
+ [Ty ] ->
1412
+ {elem_ty , Ty , Cs };
1413
+ _ ->
1414
+ {elem_tys , Tys , Cs }
1415
+ end ;
1416
+ expect_binary_type ({var , _ , Var }, _ ) ->
1417
+ TyVar = gradualizer_tyvar :new (Var , ? MODULE , ? LINE ),
1418
+ {elem_ty ,
1419
+ {var , erl_anno :new (0 ), TyVar },
1420
+ constraints :add_var (TyVar ,
1421
+ constraints :upper (Var , {type , erl_anno :new (0 ), binary ,
1422
+ [{integer , erl_anno :new (0 ), 0 },
1423
+ {integer , erl_anno :new (0 ), 1 }]}))};
1424
+ expect_binary_type (Ty , _ ) ->
1425
+ {type_error , Ty }.
1426
+
1427
+ - spec expect_binary_union ([type ()], [type ()], constraints (), env ()) -> {[type ()], constraints ()}.
1428
+ expect_binary_union ([Ty |Tys ], AccTy , AccCs , Env ) ->
1429
+ case expect_binary_type (normalize (Ty , Env ), Env ) of
1430
+ {type_error , _ } ->
1431
+ expect_binary_union (Tys , AccTy , AccCs , Env );
1432
+ any ->
1433
+ expect_binary_union (Tys , [type (any ) | AccTy ], AccCs , Env );
1434
+ {elem_ty , NTy , Cs } ->
1435
+ expect_binary_union (Tys , [NTy | AccTy ], constraints :combine (Cs , AccCs ), Env );
1436
+ {elem_tys , NTys , Cs } ->
1437
+ expect_binary_union (Tys , NTys ++ AccTy , constraints :combine (Cs , AccCs ), Env )
1438
+ end ;
1439
+ expect_binary_union ([], AccTy , AccCs , _Env ) ->
1440
+ {AccTy , AccCs }.
1441
+
1442
+
1397
1443
- spec allow_empty_list (type ()) -> type ().
1398
1444
allow_empty_list ({type , P , nonempty_list , []}) ->
1399
1445
{type , P , list , []};
@@ -3334,28 +3380,40 @@ type_check_comprehension_in(Env, ResTy, OrigExpr, lc, Expr, _P, []) ->
3334
3380
throw (type_error (OrigExpr , type (list ), ResTy ))
3335
3381
end ;
3336
3382
type_check_comprehension_in (Env , ResTy , OrigExpr , bc , Expr , _P , []) ->
3337
- ExprTy = case ResTy of
3338
- {type , _ , binary , [{integer , _ , 0 }, {integer , _ , _N }]} ->
3339
- % % The result is a multiple of N bits.
3340
- % % Expr must be a multiple of N bits too.
3341
- ResTy ;
3342
- {type , _ , binary , [{integer , _ , M }, {integer , _ , _N }]}
3343
- when M > 0 ->
3344
- % % The result is a binary with a minimum size of M. This
3345
- % % requires that the generators are non-empty. We don't
3346
- % % check that. At least, we can check that Gen is a
3347
- % % bitstring.
3348
- {type , erl_anno :new (0 ), binary ,
3349
- [{integer , erl_anno :new (0 ), 0 },
3350
- {integer , erl_anno :new (0 ), 1 }]};
3351
- _ ->
3352
- Ty = {type , erl_anno :new (0 ), binary ,
3353
- [{integer , erl_anno :new (0 ), 0 },
3354
- {integer , erl_anno :new (0 ), 1 }]},
3355
- throw (type_error (OrigExpr , Ty , ResTy ))
3356
- end ,
3357
- {_VB , Cs } = type_check_expr_in (Env , ExprTy , Expr ),
3358
- {Env , Cs };
3383
+ case expect_binary_type (ResTy , Env ) of
3384
+ any ->
3385
+ {_Ty , _VB , Cs } = type_check_expr (Env , Expr ),
3386
+ {Env , Cs };
3387
+ {elem_ty , ElemTy , Cs1 } ->
3388
+ ExprTy = case ElemTy of
3389
+ {type , _ , binary , [{integer , _ , 0 }, {integer , _ , _N }]} ->
3390
+ % % The result is a multiple of N bits.
3391
+ % % Expr must be a multiple of N bits too.
3392
+ ElemTy ;
3393
+ {type , _ , binary , [{integer , _ , M }, {integer , _ , _N }]}
3394
+ when M > 0 ->
3395
+ % % The result is a binary with a minimum size of M. This
3396
+ % % requires that the generators are non-empty. We don't
3397
+ % % check that. At least, we can check that Gen is a
3398
+ % % bitstring.
3399
+ % % TODO: Actually typecheck this case
3400
+ {type , erl_anno :new (0 ), binary ,
3401
+ [{integer , erl_anno :new (0 ), 0 },
3402
+ {integer , erl_anno :new (0 ), 1 }]};
3403
+ _ ->
3404
+ Ty = {type , erl_anno :new (0 ), binary ,
3405
+ [{integer , erl_anno :new (0 ), 0 },
3406
+ {integer , erl_anno :new (0 ), 1 }]},
3407
+ throw ({type_error , OrigExpr , Ty , ElemTy })
3408
+ end ,
3409
+ {_VB , Cs2 } = type_check_expr_in (Env , ExprTy , Expr ),
3410
+ {Env , constraints :combine (Cs1 , Cs2 )};
3411
+ {elem_tys , ElemTys , Cs1 } ->
3412
+ {VB , Cs2 } = type_check_union_in (Env , ElemTys , Expr ),
3413
+ {VB , constraints :combine (Cs1 , Cs2 )};
3414
+ {type_error , Ty } ->
3415
+ throw ({type_error , OrigExpr , Ty , ResTy })
3416
+ end ;
3359
3417
type_check_comprehension_in (Env , ResTy , OrigExpr , Compr , Expr , P ,
3360
3418
[{generate , _ , Pat , Gen } | Quals ]) ->
3361
3419
{Ty , _VB1 , Cs1 } = type_check_expr (Env , Gen ),
0 commit comments