0% found this document useful (0 votes)
4 views

COMP3007_Modern_Programming_Languages (4)

The document outlines the key concepts of error handling, generic types, traits, and lifetimes in Rust programming for the COMP3007 course. It emphasizes Rust's explicit error handling approach, distinguishing between recoverable and unrecoverable errors, and introduces the use of Result and panic! macros. Additionally, it covers the importance of generics for code reusability, traits for shared behavior, and lifetimes for ensuring reference validity.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
4 views

COMP3007_Modern_Programming_Languages (4)

The document outlines the key concepts of error handling, generic types, traits, and lifetimes in Rust programming for the COMP3007 course. It emphasizes Rust's explicit error handling approach, distinguishing between recoverable and unrecoverable errors, and introduces the use of Result and panic! macros. Additionally, it covers the importance of generics for code reusability, traits for shared behavior, and lifetimes for ensuring reference validity.
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 26

COMP3007 - Modern Programming Languages

Week 6: Rust - Error Handling, Generic Types, Traits, and Lifetimes

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel

Department of Computer Engineering

Fall 2024-2025

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 1 / 26
Outline

1 Introduction to Error Handling in Rust


2 Unrecoverable Errors with panic!
3 Recoverable Errors with Result
4 Shortcuts for Panic on Error
5 Propagating Errors
6 To panic! or Not to panic!
7 Creating Custom Types for Validation
8 Conclusion
9 Generic Types, Traits, and Lifetimes

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 2 / 26
Error Handling Philosophy in Rust

Rust doesn’t have exceptions


Errors are handled explicitly
Two main categories of errors:
Recoverable errors (Result<T, E>)
Unrecoverable errors (panic!)
Emphasis on compile-time error checking

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 3 / 26
The panic! Macro

1 fn main () {
2 panic !("crash and burn");
3 }

Used for unrecoverable errors


Prints a failure message, unwinds, cleans up the stack, and quits
Can be used to check for conditions that should never happen

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 4 / 26
Using a panic! Backtrace

Set the RUST_BACKTRACE environment variable to get a backtrace


Useful for debugging panic situations
Example: RUST_BACKTRACE=1 cargo run

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 5 / 26
The Result Enum

1 enum Result <T, E> {


2 Ok(T),
3 Err(E),
4 }

T: The type of the value that will be returned in a success case


E: The type of the error that will be returned in a failure case

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 6 / 26
Using the Result Type

1 use std::fs:: File;


2
3 fn main () {
4 let f = File :: open("hello.txt");
5
6 let f = match f {
7 Ok(file) => file ,
8 Err(error) => panic !("Problem opening the file: {:?}", error),
9 };
10 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 7 / 26
Matching on Different Errors

1 use std::fs:: File;


2 use std::io:: ErrorKind;
3
4 fn main () {
5 let f = File :: open("hello.txt");
6
7 let f = match f {
8 Ok(file) => file ,
9 Err(error) => match error.kind () {
10 ErrorKind :: NotFound => match File :: create("hello.txt") {
11 Ok(fc) => fc ,
12 Err(e) => panic !("Problem creating the file: {:?}", e),
13 },
14 other_error => {
15 panic !("Problem opening the file: {:?}", other_error)
16 }
17 },
18 };
19 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 8 / 26
Shortcuts for Panic on Error: unwrap and expect

1 use std::fs:: File;


2
3 fn main () {
4 let f = File :: open("hello.txt").unwrap ();
5 }

1 use std::fs:: File;


2
3 fn main () {
4 let f = File :: open("hello.txt").expect("Failed to open hello.txt");
5 }

unwrap() calls panic! if the Result value is an Err


expect() lets us choose the panic! error message

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 9 / 26
Propagating Errors

1 use std::io;
2 use std::io:: Read;
3 use std::fs:: File;
4
5 fn read_username_from_file () -> Result <String , io::Error > {
6 let f = File :: open("hello.txt");
7
8 let mut f = match f {
9 Ok(file) => file ,
10 Err(e) => return Err(e),
11 };
12
13 let mut s = String ::new();
14
15 match f.read_to_string (& mut s) {
16 Ok(_) => Ok(s),
17 Err(e) => Err(e),
18 }
19 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 10 / 26
A Shortcut for Propagating Errors: the ? Operator

1 use std::io;
2 use std::io:: Read;
3 use std::fs:: File;
4
5 fn read_username_from_file () -> Result <String , io::Error > {
6 let mut f = File :: open("hello.txt")?;
7 let mut s = String ::new();
8 f.read_to_string (& mut s)?;
9 Ok(s)
10 }

The ? operator can only be used in functions that return Result


It’s a shorthand for the entire match expression

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 11 / 26
Guidelines for Error Handling

Use panic! when:


You’re in an unrecoverable state
Your code is in a bad state and it’s unexpected
You’re writing example code or prototypes
Use Result when:
An error is expected and can be handled
You’re writing a library and want to give users more control

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 12 / 26
Creating Custom Types for Validation

1 pub struct Guess {


2 value: i32 ,
3 }
4
5 impl Guess {x
6 pub fn new(value: i32) -> Guess {
7 if value < 1 || value > 100 {
8 panic !("Guess value must be between 1 and 100, got {}.", value);
9 }
10
11 Guess { value }
12 }
13
14 pub fn value (& self) -> i32 {
15 self.value
16 }
17 }

Encapsulate validation logic in types


Ensure invalid states are unrepresentable

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 13 / 26
Conclusion

Rust’s error handling is explicit and type-safe


Use panic! for unrecoverable errors
Use Result for recoverable errors
The ? operator simplifies error propagation
Custom types can encapsulate validation logic
Proper error handling leads to more robust and reliable code

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 14 / 26
Introduction to Generics

Generic types allow for flexible, reusable code


Reduce code duplication while maintaining type safety
Common in standard library collections
Zero-cost abstraction: No runtime overhead

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 15 / 26
Generic Functions

1 fn largest <T: PartialOrd >( list: &[T]) -> &T {


2 let mut largest = &list [0];
3
4 for item in list {
5 if item > largest {
6 largest = item;
7 }
8 }
9 largest
10 }
11
12 fn main () {
13 let numbers = vec ![34, 50, 25, 100, 65];
14 println !("Largest number: {}", largest (& numbers));
15
16 let chars = vec!['y', 'm', 'a', 'q'];
17 println !("Largest char: {}", largest (& chars));
18 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 16 / 26
Generic Structs

1 struct Point <T> {


2 x: T,
3 y: T,
4 }
5
6 struct MultiPoint <T, U> {
7 x: T,
8 y: U,
9 }
10
11 fn main () {
12 let integer_point = Point { x: 5, y: 10 };
13 let float_point = Point { x: 1.0, y: 4.0 };
14 let mixed_point = MultiPoint { x: 5, y: 4.0 };
15 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 17 / 26
Introduction to Traits

Traits define shared behavior across types


Similar to interfaces in other languages
Can be implemented for any type
Enable polymorphic behavior
Support default implementations

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 18 / 26
Defining and Implementing Traits
19 trait Summary {
20 fn summarize (& self) -> String;
21 fn default_behavior (& self) -> String {
22 String :: from("(Read more ...)")
23 }
24 }
25
26 struct NewsArticle {
27 headline: String ,
28 location: String ,
29 author: String ,
30 content: String ,
31 }
32
33 impl Summary for NewsArticle {
34 fn summarize (& self) -> String {
35 format !("{}, by {} ({})", self.headline , self.author , self.location)
36 }
37 }
38
39 struct Tweet {
40 username: String ,
41 content: String ,
42 }
43
44 impl Summary for Tweet {
45 fn summarize (& self) -> String {
46 format !("{}: {}", self.username , self.content)
47 }
48 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 19 / 26
Trait Bounds

49 fn notify <T: Summary >( item: &T) {


50 println !("Breaking news! {}", item.summarize ());
51 }
52
53 // Multiple trait bounds
54 fn complex_function <T: Summary + Display >( item: &T) {
55 println !("{}", item.summarize ());
56 }
57
58 // Where clause syntax
59 fn some_function <T, U>(t: &T, u: &U) -> i32
60 where T: Display + Clone ,
61 U: Clone + Debug
62 {
63 // Function body
64 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 20 / 26
Introduction to Lifetimes

Lifetimes ensure references are valid


Part of Rust’s borrow checker
Prevent dangling references
Most lifetimes are inferred
Generic lifetime parameters needed in some cases

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 21 / 26
Lifetime Annotation Syntax

65 // Lifetime annotation in function signatures


66 fn longest <'a>(x: &'a str , y: &'a str) -> &'a str {
67 if x.len() > y.len() {
68 x
69 } else {
70 y
71 }
72 }
73
74 // Lifetime annotations in structs
75 struct ImportantExcerpt <'a> {
76 part: &'a str ,
77 }
78
79 fn main () {
80 let string1 = String :: from("short");
81 let string2 = String :: from("longer");
82 let result = longest (&string1 , &string2);
83 println !("Longer string is {}", result);
84
85 let novel = String :: from("Call me Ishmael. Some years ago ...");
86 let first_sentence = novel.split('.').next ().expect("Could not find '.'");
87 let i = ImportantExcerpt {
88 part: first_sentence ,
89 };
90 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 22 / 26
Lifetime Elision Rules

Three rules that allow omitting lifetime annotations:


Each parameter gets its own lifetime parameter
If there is exactly one input lifetime parameter, it is assigned to all
output lifetime parameters
If there is a &self or &mut self parameter, its lifetime is assigned to all
output lifetime parameters
Compiler applies these rules automatically

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 23 / 26
Static Lifetime

91 // The 'static lifetime


92 let s: &'static str = "I have a static lifetime.";
93
94 // Generic type parameters , trait bounds , and lifetimes together
95 fn longest_with_announcement <'a, T>(
96 x: &'a str ,
97 y: &'a str ,
98 ann: T,
99 ) -> &'a str
00 where
01 T: Display ,
02 {
03 println !("Announcement! {}", ann);
04 if x.len() > y.len() {
05 x
06 } else {
07 y
08 }
09 }

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 24 / 26
Summary of Generics, Traits, and Lifetimes

Generic types provide code reuse with type safety


Traits define shared behavior between types
Lifetimes ensure reference validity
These features work together to provide:
Type-safe abstractions
Code reusability
Memory safety
Zero-cost abstractions

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 25 / 26
Thank You! Any Questions?

Dr. Öğr. Üyesi Yusuf Kürşat Tuncel (Department


COMP3007
of Computer
- Modern
Engineering)
Programming Languages Fall 2024-2025 26 / 26

You might also like