Skip to content

Commit 24cd780

Browse files
committed
Merge branch 'main' into domain-keys-in-map
2 parents d593537 + 972f9e4 commit 24cd780

File tree

6 files changed

+43
-21
lines changed

6 files changed

+43
-21
lines changed

.github/workflows/release.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ jobs:
218218

219219
- name: Attest Distribution Assets with SBoM
220220
id: attest-sbom
221-
uses: actions/attest-sbom@115c3be05ff3974bcbd596578934b3f9ce39bf68 # v2.2.0
221+
uses: actions/attest-sbom@bd218ad0dbcb3e146bd073d1d9c6d78e08aa8a0b # v2.4.0
222222
with:
223223
subject-path: |
224224
/tmp/build-artifacts/{elixir-otp-*.*,Docs.zip}

lib/elixir/lib/map.ex

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,11 @@ defmodule Map do
317317
iex> Map.fetch!(%{a: 1}, :a)
318318
1
319319
320+
When the key is missing, an exception is raised:
321+
322+
Map.fetch!(%{a: 1}, :b)
323+
** (KeyError) key :b not found in: %{a: 1}
324+
320325
"""
321326
@spec fetch!(map, key) :: value
322327
def fetch!(map, key) do

lib/elixir/lib/module/types/descr.ex

Lines changed: 16 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -283,7 +283,7 @@ defmodule Module.Types.Descr do
283283
case descr do
284284
%{dynamic: %{optional: 1}} -> %{dynamic: %{optional: 1}}
285285
%{optional: 1} -> %{optional: 1}
286-
_ -> %{}
286+
_ -> @none
287287
end
288288
end
289289

@@ -490,13 +490,21 @@ defmodule Module.Types.Descr do
490490

491491
defp iterator_difference_static(:none, map), do: map
492492

493-
defp empty_difference_static?(left, :term), do: not Map.has_key?(left, :optional)
493+
# This function is designed to compute the difference during subtyping efficiently.
494+
# Do not use it for anything else.
495+
defp empty_difference_subtype?(%{dynamic: dyn_left} = left, %{dynamic: dyn_right} = right) do
496+
# Dynamic will either exist on both sides or on none
497+
empty_difference_subtype?(dyn_left, dyn_right) and
498+
empty_difference_subtype?(Map.delete(left, :dynamic), Map.delete(right, :dynamic))
499+
end
500+
501+
defp empty_difference_subtype?(left, :term), do: keep_optional(left) == @none
494502

495-
defp empty_difference_static?(left, right) do
496-
iterator_empty_difference_static?(:maps.next(:maps.iterator(unfold(left))), unfold(right))
503+
defp empty_difference_subtype?(left, right) do
504+
iterator_empty_difference_subtype?(:maps.next(:maps.iterator(unfold(left))), unfold(right))
497505
end
498506

499-
defp iterator_empty_difference_static?({key, v1, iterator}, map) do
507+
defp iterator_empty_difference_subtype?({key, v1, iterator}, map) do
500508
case map do
501509
%{^key => v2} ->
502510
value = difference(key, v1, v2)
@@ -505,15 +513,14 @@ defmodule Module.Types.Descr do
505513
%{} ->
506514
empty_key?(key, v1)
507515
end and
508-
iterator_empty_difference_static?(:maps.next(iterator), map)
516+
iterator_empty_difference_subtype?(:maps.next(iterator), map)
509517
end
510518

511-
defp iterator_empty_difference_static?(:none, _map), do: true
519+
defp iterator_empty_difference_subtype?(:none, _map), do: true
512520

513521
# Returning 0 from the callback is taken as none() for that subtype.
514522
defp difference(:atom, v1, v2), do: atom_difference(v1, v2)
515523
defp difference(:bitmap, v1, v2), do: v1 - (v1 &&& v2)
516-
defp difference(:dynamic, v1, v2), do: dynamic_difference(v1, v2)
517524
defp difference(:list, v1, v2), do: list_difference(v1, v2)
518525
defp difference(:map, v1, v2), do: map_difference(v1, v2)
519526
defp difference(:optional, 1, 1), do: 0
@@ -563,7 +570,6 @@ defmodule Module.Types.Descr do
563570
defp empty_key?(:map, value), do: map_empty?(value)
564571
defp empty_key?(:list, value), do: list_empty?(value)
565572
defp empty_key?(:tuple, value), do: tuple_empty?(value)
566-
defp empty_key?(:dynamic, value), do: empty?(value)
567573
defp empty_key?(_, _value), do: false
568574

569575
@doc """
@@ -690,7 +696,7 @@ defmodule Module.Types.Descr do
690696
end
691697

692698
defp subtype_static?(same, same), do: true
693-
defp subtype_static?(left, right), do: empty_difference_static?(left, right)
699+
defp subtype_static?(left, right), do: empty_difference_subtype?(left, right)
694700

695701
@doc """
696702
Check if a type is equal to another.
@@ -2145,13 +2151,6 @@ defmodule Module.Types.Descr do
21452151
defp dynamic_intersection(left, right),
21462152
do: symmetrical_intersection(unfold(left), unfold(right), &intersection/3)
21472153

2148-
defp dynamic_difference(left, right) do
2149-
case difference_static(left, right) do
2150-
value when value == @none -> 0
2151-
value -> value
2152-
end
2153-
end
2154-
21552154
defp dynamic_to_quoted(descr, opts) do
21562155
cond do
21572156
descr == %{} ->

lib/elixir/src/elixir_erl_pass.erl

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,8 @@ translate_remote(Left, Right, Meta, Args, S) ->
628628
[TOne, TTwo] -> {{op, Ann, Right, TOne, TTwo}, SA}
629629
end;
630630
{inline_pure, Result} ->
631-
translate(Result, Ann, S);
631+
Generated = erl_anno:set_generated(true, Ann),
632+
translate(Result, Generated, S);
632633
{inline_args, NewArgs} ->
633634
{TLeft, SL} = translate(Left, Ann, S),
634635
{TArgs, SA} = translate_args(NewArgs, Ann, SL),
@@ -690,7 +691,7 @@ inline_pure_function('Elixir.URI', parse) -> true;
690691
inline_pure_function('Elixir.URI', encode_query) -> true;
691692
inline_pure_function('Elixir.URI', encode_www_form) -> true;
692693
inline_pure_function('Elixir.URI', decode) -> true;
693-
inline_pure_function('Elixir.URI', decode_www_for) -> true;
694+
inline_pure_function('Elixir.URI', decode_www_form) -> true;
694695
inline_pure_function('Elixir.Version', parse) -> true;
695696
inline_pure_function('Elixir.Version', 'parse!') -> true;
696697
inline_pure_function('Elixir.Version', parse_requirement) -> true;
@@ -717,7 +718,7 @@ generate_struct_name_guard([Field | Rest], Acc, S) ->
717718
%% TODO: Make this a runtime error on Elixir v2.0
718719
no_parens_remote(nil, _Key) -> {error, {badmap, nil}};
719720
no_parens_remote(false, _Key) -> {error, {badmap, false}};
720-
no_parens_remote(true, _Key) -> {error, {badmap, false}};
721+
no_parens_remote(true, _Key) -> {error, {badmap, true}};
721722
no_parens_remote(Atom, Fun) when is_atom(Atom) ->
722723
Message = fun() ->
723724
io_lib:format(
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
defmodule Dialyzer.OpaqueInline do
2+
@spec bar(MapSet.t()) :: term()
3+
def bar(set) do
4+
set
5+
end
6+
7+
def foo() do
8+
bar(MapSet.new([1, 2, 3]))
9+
end
10+
end

lib/elixir/test/elixir/kernel/dialyzer_test.exs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ defmodule Kernel.DialyzerTest do
3232
:elixir_env,
3333
:elixir_erl_pass,
3434
:maps,
35+
:sets,
3536
ArgumentError,
3637
Atom,
3738
Code,
@@ -45,6 +46,7 @@ defmodule Kernel.DialyzerTest do
4546
List,
4647
Macro,
4748
Macro.Env,
49+
MapSet,
4850
Module,
4951
Protocol,
5052
String,
@@ -176,6 +178,11 @@ defmodule Kernel.DialyzerTest do
176178
assert_dialyze_no_warnings!(context)
177179
end
178180

181+
test "no warning on inlined calls returning opaque", context do
182+
copy_beam!(context, Dialyzer.OpaqueInline)
183+
assert_dialyze_no_warnings!(context)
184+
end
185+
179186
defp copy_beam!(context, module) do
180187
name = "#{module}.beam"
181188
File.cp!(Path.join(context.base_dir, name), Path.join(context.outdir, name))

0 commit comments

Comments
 (0)