CodeBlanks Logo Icon CodeBlanks

Newtype pattern

Resolve trait conflicts with the newtype pattern.

The newtype pattern

The orphan rule forbids implementing another crate's trait for another crate's type: impl Display for Vec<String> can't be written. The solution is wrapping the type in your own single-field struct; since the wrapper is your type, the implementation is allowed:

struct Liste(Vec<String>);

impl std::fmt::Display for Liste {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        write!(f, "[{}]", self.0.join(", "))
    }
}

A newtype adds no runtime cost; in memory it's the same as the inner type.

Newtypes for type safety

Values with the same base type but different meanings can no longer be mixed up:

struct KullaniciId(u64);
struct SiparisId(u64);

fn siparis_bul(id: SiparisId) { .. }
// siparis_bul(KullaniciId(7));   // error: type mismatch

Validation can go in the constructor too: if Eposta::new(s) returns Some only for valid addresses, the rest of the program can trust that every Eposta is valid.

Practice Printable list

Write the Liste newtype above and its Display implementation. Print Liste(vec!["elma".into(), "armut".into()]) with {}.

Starter code

main.rs
use std::fmt;

fn main() {
    // buraya yaz
}

Sample solution

main.rs
use std::fmt;

struct Liste(Vec<String>);

impl fmt::Display for Liste {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "[{}]", self.0.join(", "))
    }
}

fn main() {
    let l = Liste(vec!["elma".into(), "armut".into()]);
    println!("{}", l);
}

Expected output

[elma, armut]

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 What is the newtype's downside and how is it eased?

  • It's slow
  • It wastes memory
  • No downside
  • The inner type's methods are lost; implement Deref or forward the needed ones Correct answer

Explanation: Deref opens everything and can weaken the wrapper's purpose; forwarding only the needed methods by hand is more controlled.

2 Wrapper

Question
struct Liste____;

impl std::fmt::Display for Liste { .. }
Answer
struct Liste(Vec<String>);

impl std::fmt::Display for Liste { .. }

Explanation: A single-field tuple struct is the newtype pattern.

3 Implementation and permission

Term Meaning
impl Display for Vec<String> Forbidden
impl Display for Liste Allowed
KullaniciId(u64) Type safety
size_of::<Liste>() Same as Vec

All lessons in Advanced