Skip to content

Commit

Permalink
Return error on incorrect PortableRegistry (#34)
Browse files Browse the repository at this point in the history
* Add an error for corruped PortableRegistry
---------

Co-authored-by: James Wilson <james@jsdw.me>
  • Loading branch information
pkhry and jsdw authored Jun 25, 2024
1 parent d9c3157 commit 87d263f
Show file tree
Hide file tree
Showing 5 changed files with 42 additions and 9 deletions.
4 changes: 3 additions & 1 deletion typegen/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1518,7 +1518,7 @@ fn ensure_unique_type_paths_test() {
]
);

ensure_unique_type_paths(&mut registry);
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");

let e2 = sorted_type_paths(&registry);
assert_eq!(
Expand Down Expand Up @@ -1661,6 +1661,7 @@ fn assoc_types_skip_params() {
#[derive(TypeInfo)]
#[scale_info(skip_type_params(T))]
pub struct X<T: Config> {
#[allow(dead_code)]
pub inner: T::Inner,
}

Expand Down Expand Up @@ -1715,6 +1716,7 @@ fn assoc_types_no_skip_params() {

#[derive(TypeInfo)]
pub struct X<T: Config> {
#[allow(dead_code)]
pub inner: T::Inner,
}

Expand Down
4 changes: 2 additions & 2 deletions typegen/src/tests/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ impl Testgen {

pub fn gen(self, settings: TypeGeneratorSettings) -> TokenStream {
let mut registry: PortableRegistry = self.registry.into();
ensure_unique_type_paths(&mut registry);
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
let type_gen = TypeGenerator::new(&registry, &settings);
let module = type_gen.generate_types_mod().unwrap();
module.to_token_stream(&settings)
Expand All @@ -50,7 +50,7 @@ impl Testgen {
) -> Result<TokenStream, TypegenError> {
let mut registry: PortableRegistry = self.registry.into();
if deduplicate {
ensure_unique_type_paths(&mut registry)
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry")
}
let type_gen = TypeGenerator::new(&registry, &settings);
type_gen.generate_types_mod().map(|module| {
Expand Down
10 changes: 10 additions & 0 deletions typegen/src/typegen/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,16 @@ pub enum TypegenError {
/// Use [`crate::utils::ensure_unique_type_paths`] on your [`scale_info::PortableRegistry`] to deduplicate type paths.
#[error("There are two types with the the same type path {0} but different structure. Use `scale_typegen::utils::ensure_unique_type_paths` on your `PortableRegistry` before, to avoid this error.")]
DuplicateTypePath(String),
/// PortableRegistry entry has incorrect Id.
#[error("PortableRegistry entry has incorrect type_id. expected type_id: {expected_ty_id}, got: {given_ty_id}.\nDefinition of the type: {ty_def}.\nThis can happen if registry was modified with calls to `::retain()` in older versions of scale-info. Try generating a new metadata to fix this.")]
RegistryTypeIdsInvalid {
/// Received type id
given_ty_id: u32,
/// Expected type id
expected_ty_id: u32,
/// Type definition
ty_def: String,
},
}

/// Error attempting to do type substitution.
Expand Down
7 changes: 6 additions & 1 deletion typegen/src/typegen/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use std::collections::btree_map::Entry;

use crate::{utils::types_equal, TypegenError};
use crate::{
utils::{sanity_pass, types_equal},
TypegenError,
};

use self::{
ir::module_ir::ModuleIR,
Expand Down Expand Up @@ -65,6 +68,8 @@ impl<'a> TypeGenerator<'a> {

/// Generate a module containing all types defined in the supplied type registry.
pub fn generate_types_mod(&self) -> Result<ModuleIR, TypegenError> {
sanity_pass(self.type_registry)?;

let flat_derives_registry = self
.settings
.derives
Expand Down
26 changes: 21 additions & 5 deletions typegen/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,23 @@ pub fn syn_type_path(ty: &Type<PortableForm>) -> Result<syn::TypePath, TypegenEr
Ok(ty_path)
}

pub(crate) fn sanity_pass(types: &PortableRegistry) -> Result<(), TypegenError> {
for (idx, ty) in types.types.iter().enumerate() {
let idx = idx as u32;
if ty.id != idx {
return Err(TypegenError::RegistryTypeIdsInvalid {
given_ty_id: ty.id,
expected_ty_id: idx,
ty_def: format!("{:#?}", ty.ty),
});
}
}
Ok(())
}

/// Deduplicates type paths in the provided Registry.
pub fn ensure_unique_type_paths(types: &mut PortableRegistry) {
pub fn ensure_unique_type_paths(types: &mut PortableRegistry) -> Result<(), TypegenError> {
sanity_pass(types)?;
let mut types_with_same_type_path_grouped_by_shape = HashMap::<&[String], Vec<Vec<u32>>>::new();

// First, group types if they are similar (same path, same shape).
Expand Down Expand Up @@ -71,6 +86,7 @@ pub fn ensure_unique_type_paths(types: &mut PortableRegistry) {
n += 1;
}
}
Ok(())
}

/// This attempts to check whether two types are equal in terms of their shape.
Expand Down Expand Up @@ -399,7 +415,7 @@ mod tests {
let _ = registry.register_type(&scale_info::meta_type::<Bar>()).id;
let mut registry = scale_info::PortableRegistry::from(registry);

ensure_unique_type_paths(&mut registry);
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");

let settings = crate::TypeGeneratorSettings::new();
let generated = crate::typegen::ir::ToTokensWithSettings::to_token_stream(
Expand Down Expand Up @@ -614,7 +630,7 @@ mod tests {
assert!(types_equal(id_w, id_y, &registry));
assert!(types_equal(id_z, id_y, &registry));

ensure_unique_type_paths(&mut registry);
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
let settings = crate::TypeGeneratorSettings::new();
let output = crate::TypeGenerator::new(&registry, &settings)
.generate_types_mod()
Expand Down Expand Up @@ -789,7 +805,7 @@ mod tests {
assert_eq!(ident(id_6), "Foo");

// after:
ensure_unique_type_paths(&mut registry);
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");

let ident = |id: u32| registry.resolve(id).unwrap().path.ident().unwrap();
assert_eq!(ident(id_1), "Foo1");
Expand Down Expand Up @@ -879,7 +895,7 @@ mod tests {

// Now, check that the generated output is sane and in line with this...

ensure_unique_type_paths(&mut registry);
ensure_unique_type_paths(&mut registry).expect("Corrupted PortableRegistry");
let settings = crate::TypeGeneratorSettings::new();
let output = crate::TypeGenerator::new(&registry, &settings)
.generate_types_mod()
Expand Down

0 comments on commit 87d263f

Please sign in to comment.