derive-into-owned

Crates.ioderive-into-owned
lib.rsderive-into-owned
version0.2.0
sourcesrc
created_at2017-05-30 16:41:17.195996
updated_at2022-01-08 19:22:08.234225
descriptionCustom derives to help with types containing Cow fields
homepagehttps://github.com/koivunej/derive-into-owned
repositoryhttps://github.com/koivunej/derive-into-owned
max_upload_size
id16920
size32,809
Joonas Koivunen (koivunej)

documentation

README

derive-into-owned

Build Status crates.io docs.rs

Rust procedural macros for deriving methods to help with working with types that contain Cow fields. Please note that this derive somewhat strangely works with duck-typing, at least for now. It was originally created to help me reduce the boilerplate with Cow types.

[derive(IntoOwned)] generates a method similar to:

use std::borrow::Cow;

struct Foo<'a> {
	field: Cow<'a, str>,
}

impl<'a> Foo<'a> {
	/// This method would be derived using #[derive(IntoOwned)]
	pub fn into_owned(self) -> Foo<'static> {
		Foo {
			field: Cow::Owned(self.field.into_owned()),
		}
	}
}

Originally based off of deep-clone-derive example but supports:

But wait there is even more! [derive(Borrowed)] generates a currently perhaps a bit limited version of a method like:

impl<'a> Foo<'a> {
	pub fn borrowed<'b>(&'b self) -> Foo<'b> {
		Foo {
			field: Cow::Borrowed(self.field.as_ref()),
		}
	}
}

Types with lifetimes

If your struct has a field with type Bar<'a> then Bar is assumed to have a method fn into_owned(self) -> Bar<'static>.

Note, there's no trait implementation expected because I didn't find one at the time and didn't think to create my own, assumed the Cow::into_owned might be getting an extension in standard library which never happened and so on.

Limitations

Currently deriving will fail miserably for at least but not limited to:

  • IntoOwned: borrowed fields like &'a str
  • Borrowed: struct/enum has more than one lifetime
  • both: arrays not supported
  • both: into_owned/borrowed types inside tuples inside vectors

Using with incompatible types results in not so understandable error messages. For example, given a struct:

#[derive(IntoOwned)]
struct Foo<'a> {
	field: &'a str,
}

The compiler error will be:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
  |
note: first, the lifetime cannot outlive the lifetime 'a as defined on the impl at 4:10...
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
note: ...so that reference does not outlive borrowed content
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
  = note: but, the lifetime must be valid for the static lifetime...
note: ...so that expression is assignable (expected Foo<'static>, found Foo<'_>)
 --> tests/does_not_compile.rs:4:10
  |
4 | #[derive(IntoOwned)]
  |          ^^^^^^^^^
error: aborting due to previous error(s)
Commit count: 47

cargo fmt