Skip to content

← Generics and Traits step 2 of 24

Easy Primitives

Select type arguments with a turbofish

A generic function can use a type supplied by its caller. Here, tn<T> returns a diagnostic description of that type:

fn tn<T>() -> &'static str {
    std::any::type_name::<T>()
}

Your task

Complete describe_instantiations(kinds: Vec<String>) -> Vec<String>. For each recognized label, call tn with the corresponding type and return the resulting name as an owned String.

Input label Type argument Output used by this exercise
u8 u8 u8
i64 i64 i64
bool bool bool
String String alloc::string::String
Vec<i64> Vec<i64> alloc::vec::Vec<i64>
Vec<String> Vec<String> alloc::vec::Vec<alloc::string::String>
Option<u8> Option<u8> core::option::Option<u8>
&str &str &str
(u8, bool) (u8, bool) (u8, bool)

Match labels exactly, including spaces and capitalization. Return "unknown" for every other label. Preserve input order and duplicates; an empty input produces an empty output.

For example, ["u8", "f64", "u8"] produces ["u8", "unknown", "u8"]. Rust supports f64; it is simply outside this exercise's table. This function selects from predefined calls, rather than parsing arbitrary Rust types at runtime.

Supply the missing type argument

The starter has only a u8 arm and the fallback arm. Its call to tn() fails with E0282 because there is no argument or return-type constraint from which Rust can infer T. Every instantiation returns &'static str.

Fix that call with an explicit type argument, then add the other table rows:

tn::<u8>()

The ::<...> syntax is commonly called the turbofish. In this call, it supplies T directly. You can also use reference and tuple types, such as tn::<&str>() and tn::<(u8, bool)>().

tn declares one type parameter. Supplying two, as in tn::<u8, bool>(), produces E0107. Assigning its string-slice result to an incompatible type produces E0308.

What the names tell you

The paths shown above reflect where these library types are defined; familiar std paths can be re-exports. But type_name is a diagnostic aid, not a stable naming format. Its output can change between compiler versions, can omit type details, and need not uniquely identify a type. Do not use it as a serialization format or a persistent type identifier.

This exercise checks the spellings in the table. If a future toolchain changes them, the exercise's expected outputs need updating too. Call type_name through tn as requested rather than hardcoding its output.

How this relates to monomorphisation

Rust normally generates specialized code for the concrete generic arguments a program needs. This is called monomorphisation. Each match arm here chooses a type at compile time; the input string chooses which arm runs.

Seeing different names demonstrates which type arguments you supplied. It does not count emitted functions or measure the cost of generics. Inlining, constant folding and other optimizations can change the final machine code. More instantiations can increase compilation work and code size, but there is no rule that five type arguments leave five separate function bodies.

The helper uses T in type_name::<T>(), so it needs no artificial argument or marker field to make the type parameter useful. Keep the implementation focused on the table. Submissions must compile, pass the cases and pass the Rust Clippy gate.