How to implement struct with Displayable attribute

Hi, I'm trying the rustlings exercices and I'm stuck on the generics3.rs...

I need to implement a struct with one of its attribute being generics as long as it implement Display traits.

Here is the code :

// An imaginary magical school has a new report card generation system written in rust!
// Currently the system only supports creating report cards where the student's grade 
// is represented numerically (e.g. 1.0 -> 5.5). However, the school also issues alphabetical grades
// (A+ -> F-) and needs to be able to print both types of report card!

// Make the necessary code changes to support alphabetical report cards, thereby making the second
// test pass.
use std::fmt::Display;

// I AM NOT DONE
pub struct ReportCard<T: Display> {
    pub grade: T,
    pub student_name: String,
    pub student_age: u8,
}

impl ReportCard<T: Display>{
    pub fn print(&self) -> String {
        format!("{} ({}) - achieved a grade of {}", &self.student_name, &self.student_age, &self.grade)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn generate_numeric_report_card() {
        let report_card = ReportCard {
            grade: 2.1, 
            student_name: "Tom Wriggle".to_string(), 
            student_age: 12,
        };
        assert_eq!(report_card.print(), "Tom Wriggle (12) - achieved a grade of 2.1");
    }

    #[test]
    fn generate_alphabetic_report_card() {
        // TODO: Make sure to change the grade here after you finish the exercise.
        let report_card = ReportCard {
            grade: "A+", 
            student_name: "Gary Plotter".to_string(), 
            student_age: 11,
        };
        assert_eq!(report_card.print(), "Gary Plotter (11) - achieved a grade of A+");
    }
}

I'm getting the following errors :

error[E0107]: wrong number of type arguments: expected 1, found 0
  --> exercises/generics/generics3.rs:17:6
   |
17 | impl ReportCard<T: Display>{
   |      ^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument

error[E0229]: associated type bindings are not allowed here
  --> exercises/generics/generics3.rs:17:17
   |
17 | impl ReportCard<T: Display>{
   |                 ^^^^^^^^^^ associated type not allowed here

I've been stuck for hours and I'm not getting anywhere...
I hope someone can help me, thanks

Like this

impl<T: Display> ReportCard<T>{
    pub fn print(&self) -> String {
        format!("{} ({}) - achieved a grade of {}", &self.student_name, &self.student_age, &self.grade)
    }
}

The T on the impl introduces the generic parameter, and the T on ReportCard uses the generic parameter

1 Like

Oh it was that easy... Thank you !
Just to be curious , how would it be if there was one other attribute that implements a different trait ?
Just simply that ? :

impl<T: Display,R: OtherTrait> ReportCard<T,R>{ ...

Yep, just like that

1 Like

Yes. You have to introduce the trait parameter by name, together with any constraints, before you can refer to it. Otherwise there is no binding between the declaration and the new trait that you are referencing in the impl. (Note that the constraints may physically occur later in the declaration, in where clauses.)

1 Like

Thank you !!

Instead of a print function you can use

use std::fmt;
impl<T: Display> Display for ReportCard<T> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(f, "{} ({}) - achieved a grade of {}", &self.student_name, &self.student_age, &self.grade)
    }
}

You'll get a to_string implementation for free, and you can print out ReportCard using the usual format mechanisms.

1 Like

This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.