diff options
-rw-r--r-- | src/lib.rs | 12 | ||||
-rw-r--r-- | src/transform.rs | 28 | ||||
-rw-r--r-- | ui-tests/src/bin/qualified_self_opt.rs | 10 | ||||
-rw-r--r-- | ui-tests/src/bin/qualified_self_opt.stderr | 5 |
4 files changed, 40 insertions, 15 deletions
@@ -373,7 +373,17 @@ fn generate_blanket_impl( } fn path_is_assoc_type(path: &TypePath) -> bool { - path.path.segments[0].ident == "Self" + if path.path.segments[0].ident == "Self" { + return true; + } + if let Some(qself) = &path.qself { + if let Type::Path(path) = qself.ty.as_ref() { + if path.path.segments[0].ident == "Self" { + return true; + } + } + } + false } fn match_assoc_type(item: &Type) -> bool { diff --git a/src/transform.rs b/src/transform.rs index 39d3cab..74ab9e6 100644 --- a/src/transform.rs +++ b/src/transform.rs @@ -3,14 +3,13 @@ use std::collections::HashMap; use proc_macro2::Span; use quote::quote; use syn::{ - spanned::Spanned, GenericArgument, Generics, Ident, PathArguments, QSelf, TraitBound, Type, + spanned::Spanned, GenericArgument, Generics, Ident, PathArguments, TraitBound, Type, TypeParamBound, TypePath, TypeReference, TypeTraitObject, WherePredicate, }; use crate::{ filter_map_assoc_paths, match_assoc_type, parse_assoc_type::{BoxType, DestType}, - path_is_assoc_type, syn_utils::{iter_path, iter_type, type_arguments_mut}, trait_sig::{MethodError, TypeTransform}, }; @@ -59,17 +58,6 @@ impl TypeConverter<'_> { } pub fn convert_type(&self, type_: &mut Type) -> Result<TypeTransform, (Span, TransformError)> { - if let Type::Path(TypePath { - qself: Some(QSelf { ty, .. }), - .. - }) = type_ - { - if let Type::Path(path) = ty.as_ref() { - if path_is_assoc_type(path) { - return Err((path.span(), TransformError::QualifiedSelfAssociatedType)); - } - } - } if !iter_type(type_).any(match_assoc_type) { return Ok(TypeTransform::NoOp); } @@ -125,7 +113,19 @@ impl TypeConverter<'_> { } } - if let Type::Path(TypePath { path, qself: None }) = type_ { + if let Type::Path(TypePath { + qself: Some(qself), .. + }) = type_ + { + if let Type::Path(self_path) = qself.ty.as_ref() { + if self_path.path.segments[0].ident == "Self" { + return Err(( + self_path.span(), + TransformError::QualifiedSelfAssociatedType, + )); + } + } + } else if let Type::Path(TypePath { path, qself: None }) = type_ { if path.segments[0].ident == "Self" { if path.segments.len() == 2 { let ident = &path.segments.last().unwrap().ident; diff --git a/ui-tests/src/bin/qualified_self_opt.rs b/ui-tests/src/bin/qualified_self_opt.rs new file mode 100644 index 0000000..5de8b71 --- /dev/null +++ b/ui-tests/src/bin/qualified_self_opt.rs @@ -0,0 +1,10 @@ +trait Foo { + type X: Into<String>; +} + +#[dynamize::dynamize] +trait Bar: Foo { + fn test(&self) -> Option<<Self as Foo>::X>; +} + +fn main() {} diff --git a/ui-tests/src/bin/qualified_self_opt.stderr b/ui-tests/src/bin/qualified_self_opt.stderr new file mode 100644 index 0000000..e032be5 --- /dev/null +++ b/ui-tests/src/bin/qualified_self_opt.stderr @@ -0,0 +1,5 @@ +error: dynamize does not support associated types of a qualified Self + --> src/bin/qualified_self_opt.rs:7:31 + | +7 | fn test(&self) -> Option<<Self as Foo>::X>; + | ^^^^ |