@@ -139,7 +139,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
139139 Entry :: Occupied ( e) => e. into_mut ( ) ,
140140 Entry :: Vacant ( e) => {
141141 // Find it if it was not cached.
142- let mut instance_and_crate: Option < ( ty:: Instance < ' _ > , CrateNum , bool ) > = None ;
142+
143+ struct SymbolTarget < ' tcx > {
144+ instance : ty:: Instance < ' tcx > ,
145+ cnum : CrateNum ,
146+ is_weak : bool ,
147+ }
148+ let mut symbol_target: Option < SymbolTarget < ' tcx > > = None ;
143149 helpers:: iter_exported_symbols ( tcx, |cnum, def_id| {
144150 let attrs = tcx. codegen_fn_attrs ( def_id) ;
145151 // Skip over imports of items.
@@ -158,23 +164,31 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
158164 let symbol_name = tcx. symbol_name ( instance) . name ;
159165 let is_weak = attrs. linkage == Some ( Linkage :: WeakAny ) ;
160166 if symbol_name == link_name. as_str ( ) {
161- if let Some ( ( original_instance, original_cnum, original_is_weak) ) =
162- instance_and_crate
167+ if let Some ( SymbolTarget {
168+ instance : original_instance,
169+ cnum : original_cnum,
170+ is_weak : original_is_weak,
171+ } ) = symbol_target
163172 {
173+ // There is more than one definition with this name. What we do now
174+ // depends on whether one or both definitions are weak.
164175 match ( is_weak, original_is_weak) {
165176 ( false , true ) => {
166177 // Original definition is a weak definition. Override it.
167178
168- instance_and_crate =
169- Some ( ( ty:: Instance :: mono ( tcx, def_id) , cnum, is_weak) ) ;
179+ symbol_target = Some ( SymbolTarget {
180+ instance : ty:: Instance :: mono ( tcx, def_id) ,
181+ cnum,
182+ is_weak,
183+ } ) ;
170184 }
171185 ( true , false ) => {
172186 // Current definition is a weak definition. Keep the original one.
173187 }
174188 ( true , true ) | ( false , false ) => {
175189 // Either both definitions are non-weak or both are weak. In
176190 // either case return an error. For weak definitions we error
177- // because it is undefined which definition would have been
191+ // because it is unspecified which definition would have been
178192 // picked by the linker.
179193
180194 // Make sure we are consistent wrt what is 'first' and 'second'.
@@ -205,22 +219,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
205219 }
206220 }
207221 } else {
208- instance_and_crate =
209- Some ( ( ty:: Instance :: mono ( tcx, def_id) , cnum, is_weak) ) ;
222+ symbol_target = Some ( SymbolTarget {
223+ instance : ty:: Instance :: mono ( tcx, def_id) ,
224+ cnum,
225+ is_weak,
226+ } ) ;
210227 }
211228 }
212229 interp_ok ( ( ) )
213230 } ) ?;
214231
215- if let Some ( ( instance, _ , _ ) ) = instance_and_crate {
232+ if let Some ( SymbolTarget { instance, .. } ) = symbol_target {
216233 if !matches ! ( tcx. def_kind( instance. def_id( ) ) , DefKind :: Fn | DefKind :: AssocFn ) {
217234 throw_ub_format ! (
218235 "attempt to call an exported symbol that is not defined as a function"
219236 ) ;
220237 }
221238 }
222239
223- e. insert ( instance_and_crate . map ( |ic| ic . 0 ) )
240+ e. insert ( symbol_target . map ( |SymbolTarget { instance , .. } | instance ) )
224241 }
225242 } ;
226243 match instance {
0 commit comments