1use crate::{
9 data_store::{PackageStore, cached_package_store::CachedPackageStore},
10 execution_mode::ExecutionMode,
11 execution_value::ExecutionState,
12 static_programmable_transactions::{
13 execution::context::subst_signature,
14 linkage::{analysis::LinkageAnalyzer, resolved_linkage::ExecutableLinkage},
15 loading::ast::{
16 self as L, Datatype, DeserializedPackage, LoadedFunction, LoadedFunctionInstantiation,
17 Type,
18 },
19 },
20};
21use move_binary_format::{
22 CompiledModule,
23 errors::{Location, VMError, VMResult},
24 file_format::{Ability, AbilitySet, TypeParameterIndex},
25};
26use move_core_types::{
27 annotated_value,
28 identifier::IdentStr,
29 language_storage::{ModuleId, StructTag},
30 resolver::IntraPackageName,
31 runtime_value::{self, MoveTypeLayout},
32 vm_status::StatusCode,
33};
34use move_vm_runtime::{
35 execution::{self as vm_runtime, vm::MoveVM},
36 runtime::MoveRuntime,
37};
38use std::{cell::OnceCell, marker::PhantomData, rc::Rc};
39use sui_protocol_config::ProtocolConfig;
40use sui_types::{
41 Identifier, SUI_FRAMEWORK_PACKAGE_ID, TypeTag,
42 balance::RESOLVED_BALANCE_STRUCT,
43 base_types::{ObjectID, TxContext},
44 coin::RESOLVED_COIN_STRUCT,
45 error::ExecutionErrorTrait,
46 execution_status::{ExecutionErrorKind, TypeArgumentError},
47 funds_accumulator::RESOLVED_WITHDRAWAL_STRUCT,
48 gas_coin::GasCoin,
49 move_package::{MovePackage, UpgradeCap, UpgradeReceipt, UpgradeTicket},
50 object::Object,
51 type_input::{StructInput, TypeInput},
52};
53
54pub struct Env<'pc, 'vm, 'state, 'linkage, 'extensions, Mode>
55where
56 Mode: ExecutionMode,
57{
58 pub protocol_config: &'pc ProtocolConfig,
59 pub vm: &'vm MoveRuntime,
60 pub state_view: &'state mut dyn ExecutionState,
61 pub linkable_store: &'linkage CachedPackageStore<'state, 'vm>,
62 pub linkage_analysis: &'linkage LinkageAnalyzer,
63 gas_coin_type: OnceCell<Type>,
64 upgrade_ticket_type: OnceCell<Type>,
65 upgrade_receipt_type: OnceCell<Type>,
66 upgrade_cap_type: OnceCell<Type>,
67 tx_context_type: OnceCell<Type>,
68 input_type_resolution_vm: &'linkage MoveVM<'extensions>,
72 _mode: PhantomData<fn() -> Mode>,
73}
74
75macro_rules! get_or_init_ty {
76 ($env:expr, $ident:ident, $tag:expr) => {{
77 let env = $env;
78 if env.$ident.get().is_none() {
79 let tag = $tag;
80 let ty = env.load_type_from_struct(&tag)?;
81 env.$ident.set(ty.clone()).unwrap();
82 }
83 Ok(env.$ident.get().unwrap().clone())
84 }};
85}
86
87impl<'pc, 'vm, 'state, 'linkage, 'extensions, Mode>
88 Env<'pc, 'vm, 'state, 'linkage, 'extensions, Mode>
89where
90 Mode: ExecutionMode,
91{
92 pub fn new(
93 protocol_config: &'pc ProtocolConfig,
94 vm: &'vm MoveRuntime,
95 state_view: &'state mut dyn ExecutionState,
96 linkable_store: &'linkage CachedPackageStore<'state, 'vm>,
97 linkage_analysis: &'linkage LinkageAnalyzer,
98 input_type_resolution_vm: &'linkage MoveVM<'extensions>,
99 ) -> Self {
100 Self {
101 protocol_config,
102 vm,
103 state_view,
104 linkable_store,
105 linkage_analysis,
106 gas_coin_type: OnceCell::new(),
107 upgrade_ticket_type: OnceCell::new(),
108 upgrade_receipt_type: OnceCell::new(),
109 upgrade_cap_type: OnceCell::new(),
110 tx_context_type: OnceCell::new(),
111 input_type_resolution_vm,
112 _mode: PhantomData,
113 }
114 }
115
116 pub fn convert_linked_vm_error(&self, e: VMError, linkage: &ExecutableLinkage) -> Mode::Error {
117 convert_vm_error(e, self.linkable_store, Some(linkage), self.protocol_config)
118 }
119
120 pub fn convert_vm_error(&self, e: VMError) -> Mode::Error {
121 convert_vm_error(e, self.linkable_store, None, self.protocol_config)
122 }
123
124 pub fn convert_type_argument_error(
125 &self,
126 idx: usize,
127 e: VMError,
128 linkage: &ExecutableLinkage,
129 ) -> Mode::Error {
130 use move_core_types::vm_status::StatusCode;
131 let argument_idx = match checked_as!(idx, TypeParameterIndex) {
132 Err(e) => return e.into(),
133 Ok(v) => v,
134 };
135 match e.major_status() {
136 StatusCode::NUMBER_OF_TYPE_ARGUMENTS_MISMATCH => {
137 Mode::Error::from_kind(ExecutionErrorKind::TypeArityMismatch)
138 }
139 StatusCode::EXTERNAL_RESOLUTION_REQUEST_ERROR => {
140 Mode::Error::from_kind(ExecutionErrorKind::TypeArgumentError {
141 argument_idx,
142 kind: TypeArgumentError::TypeNotFound,
143 })
144 }
145 StatusCode::CONSTRAINT_NOT_SATISFIED => {
146 Mode::Error::from_kind(ExecutionErrorKind::TypeArgumentError {
147 argument_idx,
148 kind: TypeArgumentError::ConstraintNotSatisfied,
149 })
150 }
151 _ => self.convert_linked_vm_error(e, linkage),
152 }
153 }
154
155 pub fn fully_annotated_layout(
156 &self,
157 ty: &Type,
158 ) -> Result<annotated_value::MoveTypeLayout, Mode::Error> {
159 let tag: TypeTag = ty.clone().try_into().map_err(|s| {
160 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, s)
161 })?;
162 let objects = tag.all_addresses();
163 let tag_linkage = ExecutableLinkage::type_linkage::<_, Mode::Error>(
164 self.linkage_analysis.config().clone(),
165 objects.into_iter().map(ObjectID::from),
166 self.linkable_store,
167 )?;
168 self.input_type_resolution_vm
169 .annotated_type_layout(&tag)
170 .map_err(|e| self.convert_linked_vm_error(e, &tag_linkage))
171 }
172
173 pub fn runtime_layout(&self, ty: &Type) -> Result<runtime_value::MoveTypeLayout, Mode::Error> {
174 let tag: TypeTag = ty.clone().try_into().map_err(|s| {
175 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, s)
176 })?;
177 let objects = tag.all_addresses();
178 let tag_linkage = ExecutableLinkage::type_linkage::<_, Mode::Error>(
179 self.linkage_analysis.config().clone(),
180 objects.into_iter().map(ObjectID::from),
181 self.linkable_store,
182 )?;
183 self.input_type_resolution_vm
184 .runtime_type_layout(&tag)
185 .map_err(|e| self.convert_linked_vm_error(e, &tag_linkage))
186 }
187
188 pub fn load_framework_function(
189 &self,
190 module: &IdentStr,
191 function: &IdentStr,
192 type_arguments: Vec<Type>,
193 ) -> Result<LoadedFunction, Mode::Error> {
194 self.load_function(
195 SUI_FRAMEWORK_PACKAGE_ID,
196 module.to_string(),
197 function.to_string(),
198 type_arguments,
199 )
200 }
201
202 pub fn load_function(
203 &self,
204 package: ObjectID,
205 module: String,
206 function: String,
207 type_arguments: Vec<Type>,
208 ) -> Result<LoadedFunction, Mode::Error> {
209 let module = to_identifier(module)?;
210 let name = to_identifier(function)?;
211
212 let linkage = self.linkage_analysis.compute_call_linkage::<Mode::Error>(
213 &package,
214 module.as_ident_str(),
215 name.as_ident_str(),
216 &type_arguments,
217 self.linkable_store,
218 )?;
219
220 let Some(original_id) = linkage.0.resolve_to_original_id(&package) else {
221 invariant_violation!(
222 "Package ID {:?} is not found in linkage generated for that package",
223 package
224 );
225 };
226 let version_mid = ModuleId::new(package.into(), module.clone());
227 let original_mid = ModuleId::new(original_id.into(), module);
228 let loaded_type_arguments = type_arguments
229 .iter()
230 .enumerate()
231 .map(|(idx, ty)| self.load_vm_type_argument_from_adapter_type(idx, ty))
232 .collect::<Result<Vec<_>, _>>()?;
233 let vm = self
237 .vm
238 .make_vm(
239 &self.linkable_store.package_store,
240 linkage.linkage_context::<Mode::Error>()?,
241 )
242 .map_err(|e| self.convert_linked_vm_error(e, &linkage))?;
243 let runtime_signature = vm
244 .function_information(&original_mid, name.as_ident_str(), &loaded_type_arguments)
245 .map_err(|e| {
246 if e.major_status() == StatusCode::EXTERNAL_RESOLUTION_REQUEST_ERROR {
247 Mode::Error::new_with_source(
248 ExecutionErrorKind::FunctionNotFound,
249 format!(
250 "Could not resolve function '{}' in module '{}'",
251 name, &version_mid,
252 ),
253 )
254 } else {
255 self.convert_linked_vm_error(e, &linkage)
256 }
257 })?;
258 let runtime_signature = subst_signature(runtime_signature, &loaded_type_arguments)
259 .map_err(|e| self.convert_linked_vm_error(e, &linkage))?;
260 let parameters = runtime_signature
261 .parameters
262 .into_iter()
263 .map(|ty| self.adapter_type_from_vm_type(&vm, &ty))
264 .collect::<Result<Vec<_>, _>>()?;
265 let return_ = runtime_signature
266 .return_
267 .into_iter()
268 .map(|ty| self.adapter_type_from_vm_type(&vm, &ty))
269 .collect::<Result<Vec<_>, _>>()?;
270 let signature = LoadedFunctionInstantiation {
271 parameters,
272 return_,
273 };
274 Ok(LoadedFunction {
275 version_mid,
276 original_mid,
277 name,
278 type_arguments,
279 signature,
280 linkage,
281 instruction_length: runtime_signature.instruction_count,
282 definition_index: runtime_signature.index,
283 visibility: runtime_signature.visibility,
284 is_entry: runtime_signature.is_entry,
285 is_native: runtime_signature.is_native,
286 })
287 }
288
289 pub fn load_type_input(&self, idx: usize, ty: TypeInput) -> Result<Type, Mode::Error> {
290 let vm_type = self.load_vm_type_from_type_input(idx, ty)?;
291 self.adapter_type_from_vm_type(self.input_type_resolution_vm, &vm_type)
292 }
293
294 pub fn load_type_tag(&self, idx: usize, ty: &TypeTag) -> Result<Type, Mode::Error> {
295 let vm_type = self.load_vm_type_from_type_tag(Some(idx), ty)?;
296 self.adapter_type_from_vm_type(self.input_type_resolution_vm, &vm_type)
297 }
298
299 pub fn load_type_from_struct(&self, tag: &StructTag) -> Result<Type, Mode::Error> {
301 let vm_type =
302 self.load_vm_type_from_type_tag(None, &TypeTag::Struct(Box::new(tag.clone())))?;
303 self.adapter_type_from_vm_type(self.input_type_resolution_vm, &vm_type)
304 }
305
306 pub fn type_layout_for_struct(&self, tag: &StructTag) -> Result<MoveTypeLayout, Mode::Error> {
307 let ty: Type = self.load_type_from_struct(tag)?;
308 self.runtime_layout(&ty)
309 }
310
311 pub fn gas_coin_type(&self) -> Result<Type, Mode::Error> {
312 get_or_init_ty!(self, gas_coin_type, GasCoin::type_())
313 }
314
315 pub fn upgrade_ticket_type(&self) -> Result<Type, Mode::Error> {
316 get_or_init_ty!(self, upgrade_ticket_type, UpgradeTicket::type_())
317 }
318
319 pub fn upgrade_receipt_type(&self) -> Result<Type, Mode::Error> {
320 get_or_init_ty!(self, upgrade_receipt_type, UpgradeReceipt::type_())
321 }
322
323 pub fn upgrade_cap_type(&self) -> Result<Type, Mode::Error> {
324 get_or_init_ty!(self, upgrade_cap_type, UpgradeCap::type_())
325 }
326
327 pub fn tx_context_type(&self) -> Result<Type, Mode::Error> {
328 get_or_init_ty!(self, tx_context_type, TxContext::type_())
329 }
330
331 pub fn coin_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
332 const COIN_ABILITIES: AbilitySet =
333 AbilitySet::singleton(Ability::Key).union(AbilitySet::singleton(Ability::Store));
334 let (a, m, n) = RESOLVED_COIN_STRUCT;
335 let module = ModuleId::new(*a, m.to_owned());
336 Ok(Type::Datatype(Rc::new(Datatype {
337 abilities: COIN_ABILITIES,
338 module,
339 name: n.to_owned(),
340 type_arguments: vec![inner_type],
341 })))
342 }
343
344 pub fn balance_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
345 const BALANCE_ABILITIES: AbilitySet = AbilitySet::singleton(Ability::Store);
346 let (a, m, n) = RESOLVED_BALANCE_STRUCT;
347 let module = ModuleId::new(*a, m.to_owned());
348 Ok(Type::Datatype(Rc::new(Datatype {
349 abilities: BALANCE_ABILITIES,
350 module,
351 name: n.to_owned(),
352 type_arguments: vec![inner_type],
353 })))
354 }
355
356 pub fn withdrawal_type(&self, inner_type: Type) -> Result<Type, Mode::Error> {
357 const WITHDRAWAL_ABILITIES: AbilitySet = AbilitySet::singleton(Ability::Drop);
358 let (a, m, n) = RESOLVED_WITHDRAWAL_STRUCT;
359 let module = ModuleId::new(*a, m.to_owned());
360 Ok(Type::Datatype(Rc::new(Datatype {
361 abilities: WITHDRAWAL_ABILITIES,
362 module,
363 name: n.to_owned(),
364 type_arguments: vec![inner_type],
365 })))
366 }
367
368 pub fn vector_type(&self, element_type: Type) -> Result<Type, Mode::Error> {
369 let abilities = AbilitySet::polymorphic_abilities(
370 AbilitySet::VECTOR,
371 [false],
372 [element_type.abilities()],
373 )
374 .map_err(|e| {
375 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, e.to_string())
376 })?;
377 Ok(Type::Vector(Rc::new(L::Vector {
378 abilities,
379 element_type,
380 })))
381 }
382
383 pub fn read_object(&self, id: &ObjectID) -> Result<&Object, Mode::Error> {
384 let Some(obj) = self.state_view.read_object(id) else {
385 invariant_violation!("Object {:?} does not exist", id);
387 };
388 Ok(obj)
389 }
390
391 pub fn load_vm_type_argument_from_adapter_type(
393 &self,
394 idx: usize,
395 ty: &Type,
396 ) -> Result<vm_runtime::Type, Mode::Error> {
397 self.load_vm_type_from_adapter_type(Some(idx), ty)
398 }
399
400 fn load_vm_type_from_adapter_type(
401 &self,
402 type_arg_idx: Option<usize>,
403 ty: &Type,
404 ) -> Result<vm_runtime::Type, Mode::Error> {
405 let tag: TypeTag = ty.clone().try_into().map_err(|s| {
406 Mode::Error::new_with_source(ExecutionErrorKind::VMInvariantViolation, s)
407 })?;
408 self.load_vm_type_from_type_tag(type_arg_idx, &tag)
409 }
410
411 fn load_vm_type_from_type_tag(
413 &self,
414 type_arg_idx: Option<usize>,
415 tag: &TypeTag,
416 ) -> Result<vm_runtime::Type, Mode::Error> {
417 fn execution_error<Mode: ExecutionMode>(
418 env: &Env<Mode>,
419 type_arg_idx: Option<usize>,
420 e: VMError,
421 linkage: &ExecutableLinkage,
422 ) -> Mode::Error {
423 if let Some(idx) = type_arg_idx {
424 env.convert_type_argument_error(idx, e, linkage)
425 } else {
426 env.convert_linked_vm_error(e, linkage)
427 }
428 }
429
430 let objects = tag.all_addresses();
431
432 let tag_linkage = ExecutableLinkage::type_linkage::<_, Mode::Error>(
433 self.linkage_analysis.config().clone(),
434 objects.iter().map(|a| ObjectID::from(*a)),
435 self.linkable_store,
436 )?;
437 let ty = self
438 .input_type_resolution_vm
439 .load_type(tag)
440 .map_err(|e| execution_error(self, type_arg_idx, e, &tag_linkage))?;
441 Ok(ty)
442 }
443
444 pub(crate) fn adapter_type_from_vm_type(
446 &self,
447 vm: &MoveVM,
448 vm_type: &vm_runtime::Type,
449 ) -> Result<Type, Mode::Error> {
450 use vm_runtime as VRT;
451
452 Ok(match vm_type {
453 VRT::Type::Bool => Type::Bool,
454 VRT::Type::U8 => Type::U8,
455 VRT::Type::U16 => Type::U16,
456 VRT::Type::U32 => Type::U32,
457 VRT::Type::U64 => Type::U64,
458 VRT::Type::U128 => Type::U128,
459 VRT::Type::U256 => Type::U256,
460 VRT::Type::Address => Type::Address,
461 VRT::Type::Signer => Type::Signer,
462
463 VRT::Type::Reference(ref_ty) => {
464 let inner_ty = self.adapter_type_from_vm_type(vm, ref_ty)?;
465 Type::Reference(false, Rc::new(inner_ty))
466 }
467 VRT::Type::MutableReference(ref_ty) => {
468 let inner_ty = self.adapter_type_from_vm_type(vm, ref_ty)?;
469 Type::Reference(true, Rc::new(inner_ty))
470 }
471
472 VRT::Type::Vector(inner) => {
473 let element_type = self.adapter_type_from_vm_type(vm, inner)?;
474 self.vector_type(element_type)?
475 }
476 VRT::Type::Datatype(_) => {
477 let type_information = vm
478 .type_information(vm_type)
479 .map_err(|e| self.convert_vm_error(e))?;
480 let Some(data_type_info) = type_information.datatype_info else {
481 invariant_violation!("Expected datatype info for datatype type {:?}", vm_type);
482 };
483 let datatype = Datatype {
484 abilities: type_information.abilities,
485 module: ModuleId::new(data_type_info.defining_id, data_type_info.module_name),
486 name: data_type_info.type_name,
487 type_arguments: vec![],
488 };
489 Type::Datatype(Rc::new(datatype))
490 }
491 ty @ VRT::Type::DatatypeInstantiation(inst) => {
492 let (_, type_arguments) = &**inst;
493 let type_information = vm
494 .type_information(ty)
495 .map_err(|e| self.convert_vm_error(e))?;
496 let Some(data_type_info) = type_information.datatype_info else {
497 invariant_violation!("Expected datatype info for datatype type {:?}", vm_type);
498 };
499
500 let abilities = type_information.abilities;
501 let module = ModuleId::new(data_type_info.defining_id, data_type_info.module_name);
502 let name = data_type_info.type_name;
503 let type_arguments = type_arguments
504 .iter()
505 .map(|t| self.adapter_type_from_vm_type(vm, t))
506 .collect::<Result<Vec<_>, _>>()?;
507
508 Type::Datatype(Rc::new(Datatype {
509 abilities,
510 module,
511 name,
512 type_arguments,
513 }))
514 }
515
516 VRT::Type::TyParam(_) => {
517 invariant_violation!(
518 "Unexpected type parameter in VM type: {:?}. This should not happen as we should \
519 have resolved all type parameters before this point.",
520 vm_type
521 );
522 }
523 })
524 }
525
526 fn load_vm_type_from_type_input(
530 &self,
531 type_arg_idx: usize,
532 ty: TypeInput,
533 ) -> Result<vm_runtime::Type, Mode::Error> {
534 fn to_type_tag_internal<Mode: ExecutionMode>(
535 env: &Env<Mode>,
536 type_arg_idx: usize,
537 ty: TypeInput,
538 ) -> Result<TypeTag, Mode::Error> {
539 Ok(match ty {
540 TypeInput::Bool => TypeTag::Bool,
541 TypeInput::U8 => TypeTag::U8,
542 TypeInput::U16 => TypeTag::U16,
543 TypeInput::U32 => TypeTag::U32,
544 TypeInput::U64 => TypeTag::U64,
545 TypeInput::U128 => TypeTag::U128,
546 TypeInput::U256 => TypeTag::U256,
547 TypeInput::Address => TypeTag::Address,
548 TypeInput::Signer => TypeTag::Signer,
549 TypeInput::Vector(type_input) => {
550 let inner = to_type_tag_internal(env, type_arg_idx, *type_input)?;
551 TypeTag::Vector(Box::new(inner))
552 }
553 TypeInput::Struct(struct_input) => {
554 let StructInput {
555 address,
556 module,
557 name,
558 type_params,
559 } = *struct_input;
560
561 let pkg = env
562 .linkable_store
563 .get_package(&address.into())
564 .ok()
565 .flatten()
566 .ok_or_else(|| {
567 let argument_idx = match checked_as!(type_arg_idx, u16) {
568 Err(e) => return e.into(),
569 Ok(v) => v,
570 };
571 Mode::Error::from_kind(ExecutionErrorKind::TypeArgumentError {
572 argument_idx,
573 kind: TypeArgumentError::TypeNotFound,
574 })
575 })?;
576 let module = to_identifier(module)?;
577 let name = to_identifier(name)?;
578 let tid = IntraPackageName {
579 module_name: module,
580 type_name: name,
581 };
582 let Some(resolved_address) = pkg.type_origin_table().get(&tid).cloned() else {
583 return Err(Mode::Error::from_kind(
584 ExecutionErrorKind::TypeArgumentError {
585 argument_idx: checked_as!(type_arg_idx, u16)?,
586 kind: TypeArgumentError::TypeNotFound,
587 },
588 ));
589 };
590
591 let tys = type_params
592 .into_iter()
593 .map(|tp| to_type_tag_internal(env, type_arg_idx, tp))
594 .collect::<Result<Vec<_>, _>>()?;
595 TypeTag::Struct(Box::new(StructTag {
596 address: resolved_address,
597 module: tid.module_name,
598 name: tid.type_name,
599 type_params: tys,
600 }))
601 }
602 })
603 }
604 let tag = to_type_tag_internal(self, type_arg_idx, ty)?;
605 self.load_vm_type_from_type_tag(Some(type_arg_idx), &tag)
606 }
607
608 pub fn deserialize_package(
609 &self,
610 module_bytes: &[Vec<u8>],
611 dep_ids: &[ObjectID],
612 ) -> Result<DeserializedPackage, Mode::Error> {
613 assert_invariant!(
614 !module_bytes.is_empty(),
615 "empty package is checked in transaction input checker"
616 );
617
618 let total_bytes = module_bytes.iter().map(|v| v.len()).sum();
619
620 let binary_config = self.protocol_config.binary_config(None);
621 let deserialized_modules = module_bytes
622 .iter()
623 .map(|b| {
624 CompiledModule::deserialize_with_config(b, &binary_config)
625 .map_err(|e| e.finish(Location::Undefined))
626 })
627 .collect::<VMResult<Vec<CompiledModule>>>()
628 .map_err(|e| self.convert_vm_error(e))?;
629 let computed_digest = MovePackage::compute_digest_for_modules_and_deps(
630 module_bytes,
631 dep_ids,
632 true,
633 );
634 Ok(DeserializedPackage {
635 deserialized_modules,
636 total_bytes,
637 computed_digest,
638 })
639 }
640}
641
642fn to_identifier<E: ExecutionErrorTrait>(name: String) -> Result<Identifier, E> {
643 Identifier::new(name)
644 .map_err(|e| E::new_with_source(ExecutionErrorKind::VMInvariantViolation, e.to_string()))
645}
646
647fn convert_vm_error<E: ExecutionErrorTrait>(
648 error: VMError,
649 store: &dyn PackageStore,
650 linkage: Option<&ExecutableLinkage>,
651 _protocol_config: &ProtocolConfig,
652) -> E {
653 use crate::error::convert_vm_error_impl;
654 convert_vm_error_impl(
655 error,
656 &|id| {
657 debug_assert!(
658 linkage.is_some(),
659 "Linkage should be set anywhere where runtime errors may occur in order to resolve abort locations to package IDs"
660 );
661 linkage
662 .and_then(|linkage| {
663 linkage
664 .0
665 .linkage
666 .get(&(*id.address()).into())
667 .map(|new_id| ModuleId::new((*new_id).into(), id.name().to_owned()))
668 })
669 .unwrap_or_else(|| id.clone())
670 },
671 &|id, function| {
673 debug_assert!(
674 linkage.is_some(),
675 "Linkage should be set anywhere where runtime errors may occur in order to resolve abort locations to package IDs"
676 );
677 linkage.and_then(|linkage| {
678 let version_id = linkage
679 .0
680 .linkage
681 .get(&(*id.address()).into())
682 .cloned()
683 .unwrap_or_else(|| ObjectID::from_address(*id.address()));
684 store.get_package(&version_id).ok().flatten().and_then(|p| {
685 p.modules().get(id).map(|module| {
686 let module = module.compiled_module();
687 let fdef = module.function_def_at(function);
688 let fhandle = module.function_handle_at(fdef.function);
689 module.identifier_at(fhandle.name).to_string()
690 })
691 })
692 })
693 },
694 )
695 .into()
696}