aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-11-21 08:33:52 +0100
committerMartin Fischer <martin@push-f.com>2021-11-21 08:36:10 +0100
commit34dc166a9bc003bad36c28aeb29b625195d20a74 (patch)
tree1a4b7fbcd673f8094b019263cbe954ef38abb97c
parentbd6f84036426c43e08078cf11e4ee70b7714ba2f (diff)
better errors for assoc types in where clauses
-rw-r--r--src/lib.rs8
-rw-r--r--src/parse_trait_sig.rs1
-rw-r--r--src/transform.rs22
-rw-r--r--tests/doctests.md38
4 files changed, 63 insertions, 6 deletions
diff --git a/src/lib.rs b/src/lib.rs
index 17cea6d..439288e 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -110,9 +110,11 @@ pub fn dynamize(_attr: TokenStream, input: TokenStream) -> TokenStream {
MethodParseError::AssocTypeInUnsupportedReturnType
| MethodParseError::UnconvertibleAssocTypeInFnInput,
)) => return abort!(span, "dynamize does not know how to convert this type"),
- Err((span, MethodParseError::UnconvertibleAssocTypeInTraitBound)) => {
- return abort!(span, "dynamize does not support associated types here")
- }
+ Err((
+ span,
+ MethodParseError::UnconvertibleAssocTypeInTraitBound
+ | MethodParseError::UnconvertibleAssocTypeInWhereClause,
+ )) => return abort!(span, "dynamize does not support associated types here"),
Err((span, MethodParseError::ImplTraitInInputs)) => {
return abort!(
span,
diff --git a/src/parse_trait_sig.rs b/src/parse_trait_sig.rs
index 508e131..82b8ee9 100644
--- a/src/parse_trait_sig.rs
+++ b/src/parse_trait_sig.rs
@@ -28,6 +28,7 @@ pub enum MethodParseError {
AssocTypeInUnsupportedReturnType,
UnconvertibleAssocTypeInFnInput,
UnconvertibleAssocTypeInTraitBound,
+ UnconvertibleAssocTypeInWhereClause,
UnconvertibleAssocType,
}
diff --git a/src/transform.rs b/src/transform.rs
index 676cfd8..b13b7cf 100644
--- a/src/transform.rs
+++ b/src/transform.rs
@@ -141,11 +141,27 @@ pub fn dynamize_function_bounds(
}
}
- // TODO: return error if predicate_type.bounded_ty contains associated type
+ // just to provide better error messages
+ if let Some(assoc_type) =
+ iter_type(&predicate_type.bounded_ty).find_map(filter_map_assoc_paths)
+ {
+ return Err((
+ assoc_type.span(),
+ MethodParseError::UnconvertibleAssocTypeInWhereClause,
+ ));
+ }
+ // just to provide better error messages
for bound in &mut predicate_type.bounds {
- if let TypeParamBound::Trait(_bound) = bound {
- // TODO: return error if bound.path contains associated type
+ if let TypeParamBound::Trait(bound) = bound {
+ if let Some(assoc_type) =
+ iter_path(&bound.path).find_map(filter_map_assoc_paths)
+ {
+ return Err((
+ assoc_type.span(),
+ MethodParseError::UnconvertibleAssocTypeInWhereClause,
+ ));
+ }
}
}
}
diff --git a/tests/doctests.md b/tests/doctests.md
index 3318dba..8fa8306 100644
--- a/tests/doctests.md
+++ b/tests/doctests.md
@@ -54,3 +54,41 @@ trait Trait {
fn b<A: std::fmt::Display>(&self, a: A) -> Self::A;
}
```
+
+## Where clause must not contain associated types in complex predicates
+
+Works:
+
+```rust
+#[dynamize::dynamize]
+trait TraitWithCallback {
+ type A: Into<String>;
+
+ fn a<G>(&self, a: G) where G: Fn(Self::A);
+}
+```
+
+Fails:
+
+```rust compile_fail
+#[dynamize::dynamize]
+trait TraitWithCallback {
+ type A: Into<String>;
+
+ fn a<G>(&self, a: G) where G: Into<Self::A>;
+}
+```
+
+Fails:
+
+```rust compile_fail
+struct MyType<A>(A);
+trait SomeTrait {}
+
+#[dynamize::dynamize]
+trait TraitWithCallback {
+ type A: Into<String>;
+
+ fn a<G>(&self, a: G) where MyType<Self::A>: SomeTrait;
+}
+```