Skip to content

Commit b87a9fa

Browse files
authored
Do not consider variables from pattern in bitstring modifier (#14738)
1 parent 827e65a commit b87a9fa

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

lib/elixir/src/elixir_bitstring.erl

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ expand(Meta, Args, S, E, RequireSize) ->
3030
expand(_BitstrMeta, _Fun, [], Acc, S, E, Alignment, _RequireSize) ->
3131
{lists:reverse(Acc), Alignment, S, E};
3232
expand(BitstrMeta, Fun, [{'::', Meta, [Left, Right]} | T], Acc, S, E, Alignment, RequireSize) ->
33-
{ELeft, {SL, OriginalS}, EL} = expand_expr(Left, Fun, S, E),
33+
% We don't want to consider variables added in the Left pattern inside the Right specs
34+
{#elixir_ex{vars=BeforeVars}, _} = S,
35+
36+
{ELeft, {#elixir_ex{vars=AfterVars} = SL, OriginalS}, EL} = expand_expr(Left, Fun, S, E),
3437
validate_expr(ELeft, Meta, E),
3538

3639
MatchOrRequireSize = RequireSize or is_match_size(T, EL),
@@ -40,10 +43,11 @@ expand(BitstrMeta, Fun, [{'::', Meta, [Left, Right]} | T], Acc, S, E, Alignment,
4043
{'^', _, [{_, _, _}]} -> {infer, ELeft};
4144
_ -> required
4245
end,
43-
{ERight, EAlignment, SS, ES} = expand_specs(EType, Meta, Right, SL, OriginalS, EL, ExpectSize),
46+
47+
{ERight, EAlignment, SS, ES} = expand_specs(EType, Meta, Right, SL#elixir_ex{vars=BeforeVars}, OriginalS, EL, ExpectSize),
4448

4549
EAcc = concat_or_prepend_bitstring(Meta, ELeft, ERight, Acc, ES, MatchOrRequireSize),
46-
expand(BitstrMeta, Fun, T, EAcc, {SS, OriginalS}, ES, alignment(Alignment, EAlignment), RequireSize);
50+
expand(BitstrMeta, Fun, T, EAcc, {SS#elixir_ex{vars=AfterVars}, OriginalS}, ES, alignment(Alignment, EAlignment), RequireSize);
4751
expand(BitstrMeta, Fun, [H | T], Acc, S, E, Alignment, RequireSize) ->
4852
Meta = extract_meta(H, BitstrMeta),
4953
{ELeft, {SS, OriginalS}, ES} = expand_expr(H, Fun, S, E),

lib/elixir/test/elixir/kernel/expansion_test.exs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2890,6 +2890,17 @@ defmodule Kernel.ExpansionTest do
28902890
end)
28912891
end
28922892

2893+
test "raises for variable used both in pattern and size" do
2894+
assert_compile_error(~r/undefined variable "foo"/, fn ->
2895+
code =
2896+
quote do
2897+
fn <<foo::size(foo)>> -> :ok end
2898+
end
2899+
2900+
expand(code, [])
2901+
end)
2902+
end
2903+
28932904
test "raises for invalid unit" do
28942905
message = ~r"unit in bitstring expects an integer as argument, got: :oops"
28952906

lib/elixir/test/elixir/kernel/warning_test.exs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2237,6 +2237,20 @@ defmodule Kernel.WarningTest do
22372237
purge(Sample)
22382238
end
22392239

2240+
test "deprecate non-quoted variables in bitstring size modifiers" do
2241+
assert_warn_eval(
2242+
[
2243+
"the variable \"a\" is accessed inside size(...) of a bitstring but it was defined outside of the match",
2244+
"You must precede it with the pin operator"
2245+
],
2246+
"""
2247+
a = "foo"
2248+
<<a::binary-size(byte_size(a) - 1)>> <> _ = a
2249+
"fo" = a
2250+
"""
2251+
)
2252+
end
2253+
22402254
defp assert_compile_error(messages, string) do
22412255
captured =
22422256
capture_err(fn ->

0 commit comments

Comments
 (0)