We can't find the internet
Attempting to reconnect
Something went wrong!
Attempting to reconnect
← Generics and Traits step 20 of 24
Implementing traits with a newtype
Give vectors a display format by wrapping them in a type defined in your crate. Repair the starter's invalid trait implementation.
pub struct Wrap(pub Vec<i32>);
pub fn render(rows: Vec<Vec<i32>>) -> Vec<String>
Implement Display for Wrap. Render each row using the inner vector's
Debug format, with brackets and a comma followed by a space between values.
Preserve row order. Empty input produces no strings; an empty row produces
"[]".
[[1, 2, 3], [], [-1]] -> ["[1, 2, 3]", "[]", "[-1]"]
[] -> []
Delegate formatting with write!(f, "{:?}", self.0). In render, wrap
each row and call to_string(). The standard library supplies
ToString for types implementing Display.
Why the starter fails
The starter attempts impl Display for Vec<i32>. Both the trait and the
type come from the standard library, so this implementation violates the
orphan rule and produces E0117.
Imagine two unrelated libraries each supplying a different display format
for Vec<i32>. A program using both would have conflicting implementations.
Rust's coherence rules prevent ambiguous trait implementations. They include
both orphan checks, which restrict where implementations may be written,
and overlap checks, which reject implementations that apply to the same case.
A local type does not remove the overlap checks. Even a crate implementing its own trait must avoid conflicting implementations.
A wrapper is a distinct type
Wrap is a newtype: a tuple struct with one field. Because it is local,
implementing the foreign Display trait for it is allowed. This does not
change how bare vectors behave.
Moving a vector into the wrapper transfers ownership without cloning its
elements or allocating another vector buffer. Formatting still allocates
the resulting string. The ordinary struct declaration does not itself
guarantee identical layout or ABI to its field; use repr(transparent)
when that guarantee is needed and its requirements are satisfied.
A type alias would not help. type Wrap = Vec<i32> is another name for the
existing type, not a new local type.
Foreign traits with type parameters
For a trait without type arguments, such as Display, a foreign trait
needs a local implementing type. Traits with arguments have a broader rule:
a local type can appear in an argument too.
For impl<P...> Trait<T1, ..., Tn> for T0, if the trait is foreign,
consider T0, T1, ..., Tn in that order. At least one must be local,
and no uncovered type parameter may appear before the first local type.
A bare T is uncovered; ordinary type constructors can cover parameters
without becoming local themselves. Fundamental types such as Box
have special rules: Box<Local> counts as local, but Box<T> does not
cover T.
For example, this complete conversion is valid:
struct Local<T>(T);
impl<T> From<T> for Local<T> {
fn from(value: T) -> Self {
Local(value)
}
}
fn main() {
let wrapped: Local<i32> = 7.into();
assert_eq!(wrapped.0, 7);
}
By contrast, impl<T> From<Local<T>> for T fails with E0210: the bare
T in the implementing-type position precedes the local trait argument.
This is different from claiming that any generic From implementation
for a local wrapper is forbidden.
Choose the wrapper's API
The wrapper does not automatically inherit the vector's methods. Access the
inner vector through self.0, or add the methods and traits the wrapper's
callers need.
Deref can enable method lookup on the inner type, but introduces broader
pointer-like behavior. It does not erase the wrapper's distinct identity.
This formatting exercise needs only Display.
If you later add conversions, prefer From<Vec<i32>> for Wrap.
It automatically provides Into<Wrap> for the vector. Implementing
Into<Wrap> for Vec<i32> directly is allowed by the orphan rule because
Wrap is local, but does not automatically provide the corresponding From
implementation.
A passing submission must compile, pass the tests, and pass
clippy -D warnings.
References: trait coherence, E0210, and From conversions.
Your code, saved here
Sign in to access your accepted solutions and saved draft history. You can keep reading the lesson without an account.
Sign in to your accountStuck?
Rust reference solution
Sign in to track your attempts toward unlocking the reference solution.