Unverified Commit 489642e7 authored by thiolliere's avatar thiolliere Committed by GitHub
Browse files

Fix type inference in derive decode (#256)

parent f386e412
Pipeline #125978 failed with stages
in 6 seconds
[package]
name = "parity-scale-codec"
description = "SCALE - Simple Concatenating Aggregated Little Endians"
version = "1.3.6"
version = "1.3.7"
authors = ["Parity Technologies <admin@parity.io>"]
license = "Apache-2.0"
repository = "https://github.com/paritytech/parity-scale-codec"
......@@ -11,7 +11,7 @@ edition = "2018"
[dependencies]
arrayvec = { version = "0.5.1", default-features = false, features = ["array-sizes-33-128", "array-sizes-129-255"] }
serde = { version = "1.0.102", optional = true }
parity-scale-codec-derive = { path = "derive", version = "^1.2.2", default-features = false, optional = true }
parity-scale-codec-derive = { path = "derive", version = "^1.2.3", default-features = false, optional = true }
bitvec = { version = "0.17.4", default-features = false, features = ["alloc"], optional = true }
byte-slice-cast = { version = "0.3.4", default-features = false, features = ["alloc"] }
generic-array = { version = "0.13.2", optional = true }
......
[package]
name = "parity-scale-codec-derive"
description = "Serialization and deserialization derive macro for Parity SCALE Codec"
version = "1.2.2"
version = "1.2.3"
authors = ["Parity Technologies <admin@parity.io>"]
license = "Apache-2.0"
edition = "2018"
......
......@@ -20,10 +20,22 @@ use syn::{
use crate::utils;
pub fn quote(data: &Data, type_name: &Ident, input: &TokenStream) -> TokenStream {
/// Generate function block for function `Decode::decode`.
///
/// * data: data info of the type,
/// * type_name: name of the type,
/// * type_generics: the generics of the type in turbofish format, without bounds, e.g. `::<T, I>`
/// * input: the variable name for the argument of function `decode`.
pub fn quote(
data: &Data,
type_name: &Ident,
type_generics: &TokenStream,
input: &TokenStream,
) -> TokenStream {
match *data {
Data::Struct(ref data) => match data.fields {
Fields::Named(_) | Fields::Unnamed(_) => create_instance(
quote! { #type_name #type_generics },
quote! { #type_name },
input,
&data.fields,
......@@ -49,6 +61,7 @@ pub fn quote(data: &Data, type_name: &Ident, input: &TokenStream) -> TokenStream
let index = utils::index(v, i);
let create = create_instance(
quote! { #type_name #type_generics :: #name },
quote! { #type_name :: #name },
input,
&v.fields,
......@@ -74,7 +87,7 @@ pub fn quote(data: &Data, type_name: &Ident, input: &TokenStream) -> TokenStream
}
}
fn create_decode_expr(field: &Field, name: &str, input: &TokenStream) -> TokenStream {
fn create_decode_expr(field: &Field, debug_name: &str, input: &TokenStream) -> TokenStream {
let encoded_as = utils::get_encoded_as_type(field);
let compact = utils::get_enable_compact(field);
let skip = utils::get_skip(&field.attrs).is_some();
......@@ -88,7 +101,7 @@ fn create_decode_expr(field: &Field, name: &str, input: &TokenStream) -> TokenSt
).to_compile_error();
}
let err_msg = format!("Error decoding field {}", name);
let err_msg = format!("Error decoding field {}", debug_name);
if compact {
let field_type = &field.ty;
......@@ -116,9 +129,10 @@ fn create_decode_expr(field: &Field, name: &str, input: &TokenStream) -> TokenSt
} else if skip {
quote_spanned! { field.span() => Default::default() }
} else {
let field_type = &field.ty;
quote_spanned! { field.span() =>
{
let #res = _parity_scale_codec::Decode::decode(#input);
let #res = <#field_type as _parity_scale_codec::Decode>::decode(#input);
match #res {
Err(_) => return Err(#err_msg.into()),
Ok(#res) => #res,
......@@ -130,6 +144,7 @@ fn create_decode_expr(field: &Field, name: &str, input: &TokenStream) -> TokenSt
fn create_instance(
name: TokenStream,
debug_name: TokenStream,
input: &TokenStream,
fields: &Fields
) -> TokenStream {
......@@ -137,11 +152,11 @@ fn create_instance(
Fields::Named(ref fields) => {
let recurse = fields.named.iter().map(|f| {
let name_ident = &f.ident;
let field = match name_ident {
Some(a) => format!("{}.{}", name, a),
None => format!("{}", name),
let debug_name = match name_ident {
Some(a) => format!("{}.{}", debug_name, a),
None => format!("{}", debug_name),
};
let decode = create_decode_expr(f, &field, input);
let decode = create_decode_expr(f, &debug_name, input);
quote_spanned! { f.span() =>
#name_ident: #decode
......@@ -156,9 +171,9 @@ fn create_instance(
},
Fields::Unnamed(ref fields) => {
let recurse = fields.unnamed.iter().enumerate().map(|(i, f) | {
let name = format!("{}.{}", name, i);
let debug_name = format!("{}.{}", debug_name, i);
create_decode_expr(f, &name, input)
create_decode_expr(f, &debug_name, input)
});
quote_spanned! { fields.span() =>
......
......@@ -194,9 +194,10 @@ pub fn decode_derive(input: proc_macro::TokenStream) -> proc_macro::TokenStream
let name = &input.ident;
let (impl_generics, ty_generics, where_clause) = input.generics.split_for_impl();
let ty_gen_turbofish = ty_generics.as_turbofish();
let input_ = quote!(__codec_input_edqy);
let decoding = decode::quote(&input.data, name, &input_);
let decoding = decode::quote(&input.data, name, &quote!(#ty_gen_turbofish), &input_);
let impl_block = quote! {
impl #impl_generics _parity_scale_codec::Decode for #name #ty_generics #where_clause {
......
// Copyright 2021 Parity Technologies
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//! Test for type inference issue in decode.
#[cfg(not(feature = "derive"))]
use parity_scale_codec_derive::Decode;
use parity_scale_codec::Decode;
pub trait Trait {
type Value;
type AccountId: Decode;
}
#[derive(Decode)]
pub enum A<T: Trait> {
_C(
(T::AccountId, T::AccountId),
Vec<(T::Value, T::Value)>,
),
}
#[derive(Decode)]
pub struct B<T: Trait>((T::AccountId, T::AccountId), Vec<(T::Value, T::Value)>);
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment