| |

Rust 55 🦀 Dereference Trait (Deref) and Implicit Deref Coercion

⏱️ Estimated read: 20 min | |

The previous chapter introduced Box<T> as a smart pointer that owns a heap value. When Box<String> is used, method calls on the box reach the inner String, and function arguments that expect &str accept a &Box<String>. This transparency is not a special property of Box. It is the Deref trait at work. The trait lets a type opt into behaving like a reference, and the compiler inserts dereferences automatically at coercion sites. Understanding Deref explains why Box, Rc, Arc, String, and Vec all feel transparent, and why writing a newtype wrapper often requires implementing Deref to keep it usable.

Key point: Deref is not about overloading the * operator for convenience. It is about describing a type as a transparent container for another type, so the compiler can insert dereferences where a reference is needed. Implementing Deref extends the set of places where the new type can be used, at the cost of a small amount of clarity about which type is actually receiving the call.


Why Deref exists

The wrapper transparency problem. A newtype like struct Meters(f64) is a distinct type, but semantically it is a number. Method calls on Meters should reach the inner f64 when no method on Meters matches. Without Deref, the developer must write self.0.abs() everywhere. With Deref, self.abs() works, and the compiler derefs through the wrapper.

The smart-pointer transparency problem. A Box<T> is a pointer, but code should be able to call T‘s methods on it without unwrapping. Rc<T> and Arc<T> have the same need. The Deref trait is the mechanism that makes smart pointers behave like the values they own.

The coercion problem. Function signatures often take references to the base type, such as &str or &[T]. A caller with a String or a Vec<T> should be able to pass a reference without an explicit conversion. Deref coercion inserts the conversion automatically.

The chain problem. A Box<Rc<String>> should deref through multiple layers to reach String. The compiler applies the deref chain repeatedly until it finds a type that matches the expected signature. This makes nested smart pointers usable without explicit unwrapping.

The method resolution problem. When a method is called, the compiler searches the receiver’s type, then the type it derefs to, and so on. This is why methods of the inner type are callable on a wrapper without any syntactic change.

The newtype trade-off. Implementing Deref on a newtype makes the newtype transparent for method calls, but it also weakens the type safety that motivated the newtype in the first place. A newtype that derefs to its inner type can be passed where the inner type is expected, which defeats the purpose of the wrapper. The design decision is whether the transparency is worth the loss of distinction.


a. The Deref and DerefMut traits

The Deref trait has one method, deref, which returns a reference to the target type. DerefMut adds a mutable version.

The Deref trait

pub trait Deref {
    type Target: ?Sized;
    fn deref(&self) -> &Self::Target;
}

The associated type Target is the type the wrapper derefs to. The ?Sized bound allows the target to be an unsized type such as str or [T]. The deref method returns a shared reference to the target.

The DerefMut trait

pub trait DerefMut: Deref {
    fn deref_mut(&mut self) -> &mut Self::Target;
}

DerefMut inherits from Deref and adds deref_mut, which returns a mutable reference. A type that implements DerefMut can be used in contexts that require mutable access to the target.

The Box implementation

The standard library’s Box<T> implements both traits.

impl<T: ?Sized> Deref for Box<T> {
    type Target = T;
    fn deref(&self) -> &T {
        &**self
    }
}

The implementation returns &**self, which is a reference to the inner value. The double dereference goes through the Box to reach the value.

The custom implementation

A newtype can implement Deref to expose its inner value.

struct Meters(f64);

impl std::ops::Deref for Meters {
    type Target = f64;
    fn deref(&self) -> &f64 {
        &self.0
    }
}

fn main() {
    let m = Meters(10.0);
    println!("{}", m.abs());  // Calls f64::abs via deref.
}

The method abs is not defined on Meters. The compiler derefs m to f64 and finds the method there.

The DerefMut for mutable access

If the inner value needs to be mutated, the wrapper must also implement DerefMut.

use std::ops::{Deref, DerefMut};

struct Wrapper(String);

impl Deref for Wrapper {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

impl DerefMut for Wrapper {
    fn deref_mut(&mut self) -> &mut String { &mut self.0 }
}

fn main() {
    let mut w = Wrapper(String::from("hi"));
    w.push_str(" there");
    println!("{}", *w);
}

The push_str method mutates the inner String through DerefMut.


b. Deref coercion

Deref coercion is the compiler’s automatic insertion of deref calls when a reference of one type is used where a reference of another type is expected.

The coercion sites

Deref coercion applies at three sites: function arguments, method receivers, and let bindings with explicit type annotations. The compiler inserts as many deref calls as needed to make the types match.

fn takes_str(s: &str) { }

fn main() {
    let s = String::from("hello");
    takes_str(&s);  // &String coerces to &str.
}

The argument is &String, the parameter is &str. The compiler inserts a deref call to convert.

The coercion chain

When the types do not match directly, the compiler follows the deref chain. Box<Rc<String>> derefs to Rc<String>, which derefs to String, which derefs to str. The compiler tries each step until the target type matches.

use std::rc::Rc;

fn takes_str(s: &str) { }

fn main() {
    let b = Box::new(Rc::new(String::from("hello")));
    takes_str(&b);  // &Box<Rc<String>> → &str
}

The chain is &Box<Rc<String>> → &Rc<String> → &String → &str. The compiler applies the deref chain once per step.

The mutability requirement

Deref coercion to a mutable reference requires DerefMut at every step. A Box<T> provides both Deref and DerefMut. A type that only implements Deref cannot be coerced to a mutable reference.

fn takes_str_mut(s: &mut String) { }

fn main() {
    let mut b = Box::new(String::from("hello"));
    takes_str_mut(&mut b);  // Requires DerefMut.
}

If Box did not implement DerefMut, the call would fail to compile.

The method receiver coercion

Method calls on a receiver are subject to a more permissive coercion. The compiler tries self, &self, and &mut self for each type in the deref chain. It stops at the first method that matches.

struct Wrapper(String);

impl std::ops::Deref for Wrapper {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

fn main() {
    let w = Wrapper(String::from("hello"));
    println!("{}", w.len());  // String::len via deref.
}

The compiler looks for len on Wrapper, finds nothing, derefs to String, and finds len there.

The method resolution order

The search order is: T, &T, &mut T, then U, &U, &mut U, where U is the deref target. The compiler stops at the first match. This is why a method defined on the wrapper shadows a method with the same name on the inner type.

struct Wrapper(String);

impl Wrapper {
    fn len(&self) -> usize { 999 }
}

impl std::ops::Deref for Wrapper {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

fn main() {
    let w = Wrapper(String::from("hello"));
    println!("{}", w.len());  // 999, the wrapper's method.
}

The wrapper’s method wins because it is found first in the search order.

The explicit deref

When the inner method is wanted and the wrapper has a method of the same name, the developer must use explicit deref syntax.

println!("{}", (*w).len());  // 5, String::len

The *w derefs the wrapper to reach the inner String, and the method call applies to that.


c. When to implement Deref

Implementing Deref is a design decision with trade-offs. The trait is powerful, but it is also easy to misuse.

The smart-pointer use case

Smart pointers implement Deref because they own or reference another value. Box<T>, Rc<T>, Arc<T>, and Cow<T> all implement Deref to expose the inner value. This is the canonical use case.

The newtype transparency use case

A newtype that semantically acts like its inner type can implement Deref to inherit the inner type’s methods.

struct Email(String);

impl std::ops::Deref for Email {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

fn send(to: &str) { }

fn main() {
    let e = Email(String::from("a@b.com"));
    println!("{}", e.len());  // String::len
    send(&e);  // &Email → &str
}

The Email wrapper adds semantic meaning but remains usable wherever a string is expected.

The misuse case

Implementing Deref on a newtype that is not semantically a transparent wrapper weakens the type safety that motivated the newtype. A Meters newtype that derefs to f64 can be added to a Feet newtype that also derefs to f64, which defeats the purpose of having separate types.

struct Meters(f64);
struct Feet(f64);

// Both implement Deref to f64.
// The compiler cannot prevent adding Meters to Feet.

The rule is: implement Deref only when the wrapper is a transparent container, not when the wrapper exists to distinguish one semantic from another.

The Deref inheritance trap

A type that implements Deref inherits all of the target’s methods. If the target has a method that should not be exposed, Deref exposes it anyway. This is the reason the Rust API guidelines recommend against Deref for inheritance.

struct Buffer(Vec<u8>);

impl std::ops::Deref for Buffer {
    type Target = Vec<u8>;
    fn deref(&self) -> &Vec<u8> { &self.0 }
}

fn main() {
    let mut b = Buffer(Vec::new());
    b.push(1);  // Vec::push is now exposed.
}

If Buffer is meant to control how elements are added, Deref breaks that control.

The Deref versus DerefMut distinction

Implementing Deref alone gives shared access. Implementing DerefMut additionally gives mutable access. A wrapper that should not allow mutation of its inner value implements only Deref.

struct ReadOnly(Vec<u8>);

impl std::ops::Deref for ReadOnly {
    type Target = Vec<u8>;
    fn deref(&self) -> &Vec<u8> { &self.0 }
}

// No DerefMut. Mutation through the wrapper is impossible.

This is the pattern for read-only views of owned data.

The alternative: explicit methods

Instead of Deref, a wrapper can expose the inner value through explicit methods. This preserves the wrapper’s control over its interface.

struct Email(String);

impl Email {
    fn as_str(&self) -> &str { &self.0 }
}

fn send(to: &str) { }

fn main() {
    let e = Email(String::from("a@b.com"));
    send(e.as_str());
}

The caller writes as_str() explicitly. The wrapper controls exactly what is exposed.

The standard library precedent

The standard library implements Deref for smart pointers and for String (target str) and Vec<T> (target [T]). These are all cases where the type is a container for another type. The pattern is the reference: Deref is for containers, not for domain distinctions.


Complete Example Session

// ============================================
// PART 1: THE BASIC DEREF
// ============================================

fn main() {
    let b = Box::new(5);
    assert_eq!(*b, 5);
    assert_eq!(*(&b), 5);
}

// ============================================
// PART 2: CUSTOM DEREF FOR A NEWTYPE
// ============================================

use std::ops::Deref;

struct Meters(f64);

impl Deref for Meters {
    type Target = f64;
    fn deref(&self) -> &f64 { &self.0 }
}

fn main() {
    let m = Meters(10.0);
    assert_eq!(m.abs(), 10.0);
    assert_eq!(*m, 10.0);
}

// ============================================
// PART 3: DEREFMUT FOR MUTABLE ACCESS
// ============================================

use std::ops::DerefMut;

struct Wrapper(String);

impl Deref for Wrapper {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

impl DerefMut for Wrapper {
    fn deref_mut(&mut self) -> &mut String { &mut self.0 }
}

fn main() {
    let mut w = Wrapper(String::from("hello"));
    w.push_str(" world");
    assert_eq!(*w, "hello world");
}

// ============================================
// PART 4: DEREF COERCION AT FUNCTION ARGUMENTS
// ============================================

fn takes_str(s: &str) { }

fn main() {
    let s = String::from("hello");
    takes_str(&s);  // &String → &str

    let b = Box::new(String::from("hello"));
    takes_str(&b);  // &Box<String> → &str
}

// ============================================
// PART 5: THE COERCION CHAIN
// ============================================

use std::rc::Rc;

fn takes_str(s: &str) { }

fn main() {
    let nested = Box::new(Rc::new(String::from("hello")));
    takes_str(&nested);  // &Box<Rc<String>> → &str
}

// ============================================
// PART 6: METHOD RECEIVER COERCION
// ============================================

struct Email(String);

impl Deref for Email {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

fn main() {
    let e = Email(String::from("a@b.com"));
    assert_eq!(e.len(), 5);  // String::len
    assert!(e.contains('@'));  // String::contains
}

// ============================================
// PART 7: METHOD SHADOWING
// ============================================

struct WithLen(String);

impl WithLen {
    fn len(&self) -> usize { 999 }
}

impl Deref for WithLen {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

fn main() {
    let w = WithLen(String::from("hello"));
    assert_eq!(w.len(), 999);       // Wrapper's method wins.
    assert_eq!((*w).len(), 5);      // Explicit deref reaches String.
}

// ============================================
// PART 8: DEREF VERSUS EXPLICIT METHODS
// ============================================

struct Email2(String);

impl Email2 {
    fn as_str(&self) -> &str { &self.0 }
}

fn send(to: &str) { }

fn main() {
    let e = Email2(String::from("a@b.com"));
    send(e.as_str());  // Explicit call.
}

// ============================================
// PART 9: READ-ONLY WRAPPER
// ============================================

struct ReadOnly(Vec<u8>);

impl Deref for ReadOnly {
    type Target = Vec<u8>;
    fn deref(&self) -> &Vec<u8> { &self.0 }
}

fn main() {
    let r = ReadOnly(vec![1, 2, 3]);
    assert_eq!(r.len(), 3);
    // r.push(4);  // Error: no DerefMut.
}

// ============================================
// PART 10: THE STANDARD LIBRARY PATTERNS
// ============================================

fn main() {
    // String derefs to str.
    let s = String::from("hello");
    let slice: &str = &s;

    // Vec<T> derefs to [T].
    let v = vec![1, 2, 3];
    let slice: &[i32] = &v;

    // Box<T> derefs to T.
    let b = Box::new(5);
    let r: &i32 = &b;

    // Rc<T> and Arc<T> deref to T.
    let rc = std::rc::Rc::new(5);
    let r: &i32 = &rc;
}

The ten parts progressed from basic Deref through custom implementations, DerefMut, coercion at function arguments, the coercion chain, method receiver coercion, method shadowing, the alternative of explicit methods, read-only wrappers, and the standard library patterns. The same wrapper examples ran through every part, showing how Deref extends a type’s usability.


Quick Reference

The Deref Traits

TraitMethodReturns
Derefderef(&self)&Target
DerefMutderef_mut(&mut self)&mut Target

Deref Coercion Sites

SiteExample
Function argumenttakes_str(&string)
Method receiverstring.len()
let with type annotationlet s: &str = &string;

Coercion Chains

FromToSteps
&String&str1
&Box<String>&str2
&Box<Rc<String>>&str3
&Vec<T>&[T]1
&Box<[T; N]>&[T]2

Standard Library Deref Implementations

TypeTarget
Box<T>T
Rc<T>T
Arc<T>T
Stringstr
Vec<T>[T]
PathBufPath
Cow<'a, T>T

When to Implement Deref

ScenarioImplement
Smart pointerYes
Transparent newtypeSometimes
Domain distinctionNo
Control over interfaceNo

Best Practices

✅ Do This:

// Implement Deref for smart pointers.
impl<T> Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &T { &self.0 }
}  // ✅

// Implement DerefMut only when mutation is intended.
impl<T> DerefMut for MyBox<T> {
    fn deref_mut(&mut self) -> &mut T { &mut self.0 }
}  // ✅

// Use Deref for transparent containers.
struct Email(String);
impl Deref for Email { /* target String */ }  // ✅

// Use explicit methods when the wrapper controls the interface.
impl Email {
    fn as_str(&self) -> &str { &self.0 }
}  // ✅

// Understand method shadowing.
(*wrapper).method()  // ✅ Explicit deref when needed

❌ Don’t Do This:

// Don't implement Deref for domain distinctions.
struct Meters(f64);
struct Feet(f64);
impl Deref for Meters { /* ... */ }  // ❌ Loses distinction

// Don't use Deref to inherit methods you don't want to expose.
impl Deref for Buffer { /* exposes Vec::push */ }  // ❌

// Don't implement DerefMut when mutation should be prevented.
impl DerefMut for ReadOnly { /* ... */ }  // ❌ Breaks read-only intent

// Don't rely on Deref for type conversion semantics.
// Use From and Into for explicit conversions.  // ❌

// Don't forget the search order.
wrapper.method()  // ❌ Might call wrapper's method, not inner

Common Pitfalls

PitfallWhy It HappensFix
Method not foundDeref not implementedImplement Deref or call explicitly
Wrapper’s method shadows innerSearch orderUse explicit * deref
Cannot coerce to &mutMissing DerefMutImplement DerefMut
Unexpected method exposedDeref inherits allUse explicit methods instead
Type safety lostDeref on domain newtypeDon’t implement Deref
Coercion failsChain doesn’t reach targetCheck the deref chain
Ambiguous method callMultiple deref targetsUse explicit type annotation
Deref recursionDeref returns selfReturn the inner value

Real-World Examples

1. Custom Box

impl<T> Deref for MyBox<T> {
    type Target = T;
    fn deref(&self) -> &T { &self.0 }
}

2. Transparent Email Newtype

struct Email(String);
impl Deref for Email {
    type Target = String;
    fn deref(&self) -> &String { &self.0 }
}

3. Read-Only Wrapper

impl Deref for ReadOnly {
    type Target = Vec<u8>;
    fn deref(&self) -> &Vec<u8> { &self.0 }
}
// No DerefMut.

4. Coercion to &str

fn takes_str(s: &str) { }
takes_str(&String::from("hi"));  // &String → &str

5. Coercion to &[T]

fn takes_slice(s: &[i32]) { }
takes_slice(&vec![1, 2, 3]);  // &Vec<i32> → &[i32]

6. Chained Coercion

fn takes_str(s: &str) { }
let nested = Box::new(Rc::new(String::from("hi")));
takes_str(&nested);  // &Box<Rc<String>> → &str

7. DerefMut for Mutation

w.push_str(" world");  // String::push_str via DerefMut

8. Explicit Deref

(*wrapper).len()  // Reach inner type's method

9. Deref on Rc

let rc = Rc::new(5);
assert_eq!(*rc, 5);

10. Deref on Arc

let arc = Arc::new(String::from("hi"));
assert_eq!(arc.len(), 2);

Visual

The Deref Chain

┌────────────────────────────────────────────────────────────┐
│  DEREF COERCION CHAIN                                      │
│                                                            │
│  &Box<Rc<String>>                                          │
│       │                                                    │
│       │  deref                                             │
│       v                                                    │
│  &Rc<String>                                               │
│       │                                                    │
│       │  deref                                             │
│       v                                                    │
│  &String                                                   │
│       │                                                    │
│       │  deref                                             │
│       v                                                    │
│  &str                                                      │
│                                                            │
│  The compiler follows the chain until the types match.     │
│  Each step is a separate Deref implementation.             │
│                                                            │
└────────────────────────────────────────────────────────────┘

Method Resolution Order

┌────────────────────────────────────────────────────────────┐
│  METHOD RESOLUTION SEARCH ORDER                            │
│                                                            │
│  For receiver type T with deref target U:                  │
│                                                            │
│  1. Try T::method(self)                                    │
│  2. Try T::method(&self)                                   │
│  3. Try T::method(&mut self)                               │
│  4. Try U::method(self)                                    │
│  5. Try U::method(&self)                                   │
│  6. Try U::method(&mut self)                               │
│  7. Continue up the deref chain.                           │
│                                                            │
│  The first match wins.                                     │
│  A method on T shadows a method of the same name on U.     │
│  Use (*t).method() to skip the wrapper's methods.          │
│                                                            │
└────────────────────────────────────────────────────────────┘

Deref vs DerefMut

┌────────────────────────────────────────────────────────────┐
│  Deref vs DerefMut                                         │
│                                                            │
│  Deref                                                     │
│  ┌──────────────────────────────────────────────────┐     │
│  │  fn deref(&self) -> &Target                       │     │
│  │  Shared access only.                              │     │
│  │  Coerces &Wrapper to &Target.                     │     │
│  │  Method calls that need &self work.               │     │
│  └──────────────────────────────────────────────────┘     │
│                                                            │
│  DerefMut                                                  │
│  ┌──────────────────────────────────────────────────┐     │
│  │  fn deref_mut(&mut self) -> &mut Target           │     │
│  │  Mutable access.                                  │     │
│  │  Coerces &mut Wrapper to &mut Target.             │     │
│  │  Method calls that need &mut self work.           │     │
│  └──────────────────────────────────────────────────┘     │
│                                                            │
│  DerefMut requires Deref.                                  │
│  Implement only Deref to prevent mutation through deref.   │
│                                                            │
└────────────────────────────────────────────────────────────┘

The Newtype Trade-Off

┌────────────────────────────────────────────────────────────┐
│  NEWTYPE DEREF TRADE-OFF                                   │
│                                                            │
│  WITH DEREF                                                │
│  ┌──────────────────────────────────────────────────┐     │
│  │  struct Email(String);                            │     │
│  │  impl Deref for Email { type Target = String; }   │     │
│  │                                                   │     │
│  │  email.len()        → String::len                 │     │
│  │  send(email)        → coerces to &str             │     │
│  │  email.push('!')    → String::push (if DerefMut)  │     │
│  │                                                   │     │
│  │  Convenient. Inherits all String methods.         │     │
│  │  Cannot prevent invalid mutation.                 │     │
│  └──────────────────────────────────────────────────┘     │
│                                                            │
│  WITHOUT DEREF                                             │
│  ┌──────────────────────────────────────────────────┐     │
│  │  struct Email(String);                            │     │
│  │  impl Email {                                     │     │
│  │    fn as_str(&self) -> &str { &self.0 }           │     │
│  │  }                                                │     │
│  │                                                   │     │
│  │  email.as_str()     → explicit method             │     │
│  │  send(email.as_str()) → explicit conversion       │     │
│  │                                                   │     │
│  │  Less convenient.                                 │     │
│  │  Controls exactly what is exposed.                │     │
│  └──────────────────────────────────────────────────┘     │
│                                                            │
│  Choose based on whether the wrapper is a container        │
│  or a domain distinction.                                  │
│                                                            │
└────────────────────────────────────────────────────────────┘

Summary

ItemValue
DerefTrait with one method, deref, returning &Target
DerefMutTrait inheriting Deref, returning &mut Target
TargetAssociated type; the deref destination
Deref coercionAutomatic deref insertion at coercion sites
Coercion sitesFunction arguments, method receivers, let with annotation
Coercion chainCompiler follows derefs until types match
Search orderT, &T, &mut T, then U, &U, &mut U
Method shadowingWrapper’s method wins over inner’s
Explicit deref(*wrapper).method() reaches the inner type
Standard implementationsBox, Rc, Arc, String, Vec

Key takeaways:

  • Deref describes a type as a transparent container. It answers the question: what does this type look like when it is dereferenced? Box<T> derefs to T, String derefs to str, and a custom newtype derefs to whatever it wraps.
  • Deref coercion is the compiler’s automatic insertion of derefs. At function arguments, method receivers, and annotated let bindings, the compiler follows the deref chain until the types match.
  • The coercion chain can be multiple steps. Box<Rc<String>> coerces to &str by following Box → Rc → String → str. Each step is a separate Deref implementation.
  • Method resolution follows the deref chain. The compiler searches the receiver’s type and each deref target in turn. The first matching method wins, which means a method on the wrapper shadows the same method on the inner type.
  • DerefMut enables mutable access. A type that implements DerefMut can be coerced to a mutable reference. A type that implements only Deref cannot.
  • Implementing Deref weakens type safety. A newtype that derefs to its inner type can be used wherever the inner type is expected, which defeats the purpose of having a distinct type.
  • Deref is for containers, not for domain distinctions. Smart pointers and transparent wrappers are the appropriate use cases. Meters and Feet are not, because the wrapper exists precisely to distinguish them.
  • Explicit methods are the alternative. A wrapper that should control its interface exposes the inner value through named methods like as_str() instead of implementing Deref. This preserves the wrapper’s control at the cost of convenience.

Remember: Deref is the trait that makes smart pointers and transparent wrappers feel like the values they contain. It defines what a type looks like when dereferenced, and the compiler uses that definition to insert dereferences automatically at function arguments, method receivers, and annotated bindings. The coercion chain follows the deref implementations until the types match, and method resolution follows the same chain until a method is found. DerefMut extends the trait with mutable access, and its absence prevents mutation through deref. Implementing Deref is a design decision: it is correct for containers and smart pointers, and questionable for domain newtypes that exist precisely to be distinct from their inner type. The standard library’s implementations on Box, Rc, Arc, String, and Vec are the reference examples, and they show the trait doing exactly what it was designed to do.


Was this helpful?


Stop using slow, ad-bloated tool sites! 🤮

🔎 Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
✅ Finance (Mortgage, Interest, Inflation)
✅ Tech (Base64, JSON, Dev Suite, IP)
✅ Health (BMI, BMR, TDEE)
✅ Productivity (Timer, Workspace, QR)

⚡️ Fast & Private
🔒 No data leaves your device
💎 100% Free

🔗 Use it now: https://tools.kandz.me
🔖 Bookmark it—you’ll need it later!