Repository: MystenLabs/sui
File: external-crates/move/crates/move-vm-runtime/src/execution/dispatch_tables.rs (Rust)

Code before:
                    return Err(partial_vm_error!(
                        UNKNOWN_INVARIANT_VIOLATION_ERROR,
                        "Runtime ID resolution of {defining_id} \
                            => {package_key} does not match runtime ID of loaded type: {}",
                        datatype.original_id.address()
                    )
                    .finish(Location::Undefined));
                }
                // The defining ID should match the defining ID of the datatype that we
                // have loaded.
                if datatype.defining_id.address() != &defining_id {
                    return Err(partial_vm_error!(
                        UNKNOWN_INVARIANT_VIOLATION_ERROR,
                        "Defining ID {defining_id} does not match defining ID of loaded type: {}",
                        datatype.defining_id.address()
                    )
                    .finish(Location::Package(defining_id)));
                }
                if datatype.type_parameters().is_empty() && struct_tag.type_params.is_empty() {
                    Type::Datatype(key)
                } else {
                    let mut type_params = vec![];
                    for ty_param in &struct_tag.type_params {
                        type_params.push(self.load_type(ty_param)?);
                    }
                    self.verify_ty_args(datatype.type_param_constraints(), &type_params)
                        .map_err(|e| e.finish(Location::Package(defining_id)))?;
                    Type::DatatypeInstantiation(Box::new((key, type_params)))
                }
            }
        })
    }

    // Verify the kind (constraints) of an instantiation.
    // Function invocations call this function to verify correctness of type arguments provided
    pub fn verify_ty_args<'a, I>(&self, constraints: I, ty_args: &[Type]) -> PartialVMResult<()>
    where
        I: IntoIterator<Item = &'a AbilitySet>,
        I::IntoIter: ExactSizeIterator,
    {
        let constraints = constraints.into_iter();
        if constraints.len() != ty_args.len() {
            return Err(partial_vm_error!(NUMBER_OF_TYPE_ARGUMENTS_MISMATCH));
        }
        for (ty, expected_k) in ty_args.iter().zip(constraints) {
            if !expected_k.is_subset(self.abilities(ty)?) {
                return Err(partial_vm_error!(CONSTRAINT_NOT_SATISFIED));
            }
        }
        Ok(())
    }

Review comment (suggestion):
For both this and `find_function`, it might be nice to make some

```
fn make_vtable_lookup_error(msg: &string) -> PartialVmError {
    partial_vm_error!(
        EXTERNAL_RESOLUTION_REQUEST_ERROR,
        msg,
    )
}
```

Code after:
    }

    #[cfg(test)]
    pub(crate) fn to_virtual_table_key_for_testing(
        &self,
        original_id: &OriginalId,
        module: &IdentStr,
        name: &IdentStr,
    ) -> Option<VirtualTableKey> {
        self.try_to_virtual_table_key(original_id, module, name)
    }
}

// ------------------------------------------------------------------------
// Type-related functions over the VMDispatchTables.
// ------------------------------------------------------------------------

impl VMDispatchTables {
    // -------------------------------------------
    // Helpers for loading and verification
    // -------------------------------------------

    // Load a type from a TypeTag into a VM type.
    // NB: the type `TypeTag` _must_ be defining ID based. Otherwise, the type resolution will
    // fail.
    pub(crate) fn load_type(&self, type_tag: &TypeTag) -> VMResult<Type> {
        Ok(match type_tag {
            TypeTag::Bool => Type::Bool,
            TypeTag::U8 => Type::U8,
            TypeTag::U16 => Type::U16,
            TypeTag::U32 => Type::U32,
            TypeTag::U64 => Type::U64,
            TypeTag::U128 => Type::U128,
            TypeTag::U256 => Type::U256,
            TypeTag::Address => Type::Address,
            TypeTag::Signer => Type::Signer,
            TypeTag::Vector(tt) => Type::Vector(Box::new(self.load_type(tt)?)),
            // NB: Note that this tag is slightly misnamed and used for all Datatypes.
            TypeTag::Struct(struct_tag) => {
                let defining_id = struct_tag.address;
                let package_key = *self.defining_id_origins.get(&defining_id).ok_or_else(|| {
                    partial_vm_error!(
                        EXTERNAL_RESOLUTION_REQUEST_ERROR,
                        "Defining ID {defining_id} for type {type_tag} not found in loaded packages"
                    )
                    .finish(Location::Undefined)
                })?;

                let Some((datatype, key)) = self.try_resolve_type_for_external(
                    package_key,
                    &struct_tag.module,