1

Primitives should be passed by value as usual and anything that is passed by reference ('borrowed') should be cloned. Something like:

let a = 7;
let b = duplicate(a);  // let b = a;

let a = struct{}{};
let b = duplicate(a);  // let b = a.clone();

This assumes that every value in Rust implements either the Clone or the Copy trait. Is this assumption true? If not, is it possible to define a trait Duplicate that is kind of an enum { Clone, Copy }?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
tifrel
  • 421
  • 8
  • 20

3 Answers3

11

This assumes that every value in Rust implements either the Clone or the Copy trait. Is this assumption true?

No.

is it possible to define a trait Duplicate

Yes, but it doesn't seem to serve any value beyond what the existing Clone trait does.


You may wish to learn more about ownership, as you can make your code compile without doing any cloning at all:

fn duplicate<T>(x: T) -> T { x } // sic

fn main() {
    let a = 7;
    let b = duplicate(a);

    let a = String::from("example");
    let b = duplicate(a);
}

If you actually want to duplicate, just use Clone, as anything that implements Copy must implement Clone:

pub trait Copy: Clone { }

You will usually see it as the method syntax:

fn main() {
    let a = 7;
    let b: i32 = a.clone();

    let a = String::from("example");
    let b: String = a.clone();
}

If you want a function, use the fully-qualified syntax:

fn main() {
    let a = 7;
    let b: i32 = Clone::clone(&a);

    let a = String::from("example");
    let b: String = Clone::clone(&a);
}

Or

fn main() {
    let a = 7;
    let b: i32 = i32::clone(&a);

    let a = String::from("example");
    let b: String = String::clone(&a);
}

All the explicit types (: foo) are redundant here, just for demonstration purposes.

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • Doesn't your proposed `duplicate` function take ownership of `x`? That is exactly what I wanted to circumvent. – tifrel Jul 18 '18 at 20:46
  • @tillyboy yes, which is why I added `// sic` to it. The code you've written doesn't show any need for anything else. – Shepmaster Jul 18 '18 at 20:48
4

Copy implies Clone. You can just use .clone() for your duplicate function.

Sebastian Redl
  • 69,373
  • 8
  • 123
  • 157
-1
unsafe fn duplicate <T> (item: &T) -> T {
  std::ptr::read(item)
}

EDIT - USER DISCRETION ADVISED:

  • When the type is not self-memory-managed, it may or may not exist in-memory as the same type, or it may be that the memory is no longer accessible, in which case a SEGFAULT would occur.

  • For any type, non-Copy or not, it will do a bitwise copy of the memory area based on the layout of the type.. It will not do nested copying by dereferencing addresses, it will copy the references/addresses; ie, shallow-copy (from the language-agnostic taxonomy).

For any Copy type, this should be A-OK, but not useful?

I think a use-case for this, is in some situation when a type may not implement Copy and Clone because another trait requires it does not implement it, and so when one wants to move it to another scope/variable/thread one would read it's memory directly.

I'm not sure though, comment if you have a use-case!