What is a marker trait in Rust?
Asked Answered
S

2

10

I am learning Rust and want to dive into marker traits. Definition from official documentation is not clear for me: https://doc.rust-lang.org/std/marker/index.html

Definition:

Primitive traits and types representing basic properties of types. Rust types can be classified in various useful ways according to their intrinsic properties. These classifications are represented as traits.

  1. Why do we define a special group of traits and calling this group "marker traits"? What is special about these traits?

  2. Did I understand correctly that all these traits have default implementation and we can derive these traits for our custom structs without implementation?

Could you please answer with help of examples?

Southeasterly answered 10/6, 2023 at 10:0 Comment(0)
C
14

Marker traits are used to mark types as having some property. They usually don't have any associated types and methods and are used to tell the compiler about some property of a type. Note that some of those traits are auto traits, which means that the compiler will automatically implement them for types, if it reasons it is safe to do so (you can still implement them manually, but it may require unsafe keyword).

Currently (rustc 1.70.0) there are 5 stable traits in std::marker module. They have the following meaning. If type T implements:

  • Copy it means that it can be Cloned by using bitwise copy
  • Send it means that value of type T can be send across thread boundary
  • Sync it means that value of type T can be shared between threads (that is &T is Send)
  • Sized means that size of type T is known at compile time
  • Unpin means that value of type T can be moved after it was pinned

Of those above Send, Sync and Unpin are auto traits. There are also two more stable auto traits in std::panic module.

To answer your questions.

Why do we define a special group of traits and calling this group "marker traits"? What is special about these traits?

We call these traits "markers", to distinguish between implementation of interfaces and providing information about type properties to the compiler, both of which are accomplished in rust with traits. However there is nothing special about them. These are normal traits as all others. This is just a semantic name for us, humans.

Did I understand correctly that all these traits have default implementation and we can derive these traits for our custom structs without implementation?

They don't have default implementation strictly speaking, because by this term we understand default implementation of trait's method that is shared with all types that implement given trait and can be by them overwritten. Like for example std::io::Write::write_all.

However since they don't have any methods we can simply implement them for our types by just saying that this type implements this trait. For example we can implement Copy for our type like this (we will used #[derive(Clone)] so that we don't have to implement it manually, since Clone is a supertrait of Copy):

#[derive(Clone)]
struct Foo {
    a: i32,
    b: f32,
    c: bool,
}

impl Copy for Foo {}

You can also implement auto traits, that compiler didn't implement automatically. For example any type that contains a raw pointer is automatically marked as !Send (negative implementations are unstable feature that compiler uses). However if it is safe to send such type between threads you can explicitly implement Send for it (note that you must use unsafe keyword, since wrong implementations of Send can result in undefined behavior:

struct Bar {
    ptr: *const (),
}

unsafe impl Send for Bar {}

Once exception however is trait Sized, which can solely be implemented by the compiler. Trying to implement it manually will result in an E0322 error.

Chism answered 10/6, 2023 at 11:9 Comment(2)
"Copy is a supertrait of Clone" -- If I am not mistaken, it is the other way around.Courteous
@Courteous "The trait your trait definition is relying on is called a supertrait of your trait." (source). You are right. Thank you.Chism
M
2

The term marker is used in computer languages for traits without much code. Only the presence of some trait (=the object is marked) is exploited in processing. For example using a list of that marker trait. Java's Number or Serializable might be such a marker.

Mucker answered 10/6, 2023 at 10:26 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.