|
3 | 3 | %% SPDX-FileCopyrightText: 2012 Plataformatec |
4 | 4 |
|
5 | 5 | -module(elixir_map). |
6 | | --export([expand_map/4, expand_struct/5, format_error/1, maybe_load_struct_info/3]). |
| 6 | +-export([expand_map/4, expand_struct/5, format_error/1, maybe_load_struct_info/4]). |
7 | 7 | -import(elixir_errors, [function_error/4, file_error/4, file_warn/4]). |
8 | 8 | -include("elixir.hrl"). |
9 | 9 |
|
@@ -139,22 +139,19 @@ assert_struct_info_if_not_function(Meta, Name, Assocs, #{function := nil} = E) - |
139 | 139 | assert_struct_info_if_not_function(_Meta, _Name, _Assocs, _E) -> |
140 | 140 | ok. |
141 | 141 |
|
142 | | -maybe_load_struct_info(Meta, Name, E) -> |
143 | | - maybe_load_struct_info(Meta, Name, soft, E). |
144 | | - |
145 | 142 | maybe_load_struct_info(Meta, Name, Mode, E) -> |
146 | 143 | try |
147 | | - InContext = in_context(Name, E), |
| 144 | + Lookup = in_context(Name, E) orelse is_compiling_struct(Meta, Name, Mode, E), |
148 | 145 |
|
149 | | - case (InContext orelse is_compiling_struct(Meta, Name, Mode, E)) |
150 | | - andalso lookup_struct_info_from_data_tables(Name) of |
| 146 | + case lookup_struct_info_from_data_tables(Name) of |
151 | 147 | %% If I am accessing myself and there is no attribute, |
152 | 148 | %% don't invoke the fallback to avoid calling loaded code. |
153 | 149 | false when ?key(E, module) =:= Name -> nil; |
154 | 150 | false -> |
155 | | - %% We already attempted to wait for the struct (unless InContext), |
156 | | - %% so we only invoke '__info__' if already loaded or InContext |
157 | | - case InContext orelse erlang:module_loaded(Name) of |
| 151 | + %% If we attempted to lookup a definition, we always invoke it, to deal |
| 152 | + %% with potential race conditions about the table being deleted at the |
| 153 | + %% time we were looking up. |
| 154 | + case Lookup orelse erlang:module_loaded(Name) of |
158 | 155 | true -> Name:'__info__'(struct); |
159 | 156 | false -> nil |
160 | 157 | end; |
|
0 commit comments