Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ฟังก์ชัน

ฟังก์ชันมีอยู่ทั่วไปในโค้ดของภาษา Rust คุณได้เห็นหนึ่งในฟังก์ชันที่สำคัญที่สุดในตัวภาษาไปเรียบร้อยแล้ว นั่นคือ ฟังก์ชัน main ซึ่งทำหน้าที่เป็นจุดเริ่มต้นการทำงาน (entry point) ของโปรแกรมส่วนใหญ่ และคุณยังได้เห็นคำสำคัญ fn ซึ่งใช้เพื่อประกาศสร้างฟังก์ชันใหม่ด้วยเช่นกัน

โค้ดภาษา Rust จะมีข้อตกลงและหลักปฏิบัติทั่วไปในการเขียนชื่อฟังก์ชันรวมถึงชื่อตัวแปรด้วยรูปแบบ snake case ซึ่งตัวอักษรทั้งหมดจะเป็นตัวพิมพ์เล็กและใช้เครื่องหมายขีดล่าง (underscore) คั่นระหว่างแต่ละคำ ต่อไปนี้เป็นตัวอย่างการประกาศนิยามฟังก์ชันในโปรแกรม:

Filename: src/main.rs

fn main() {
    println!("Hello, world!");

    another_function();
}

fn another_function() {
    println!("Another function.");
}

เรานิยามฟังก์ชันใน Rust ได้โดยเขียนคำสำคัญ fn ตามด้วยชื่อฟังก์ชันและเครื่องหมายวงเล็บ ปีกกาจะทำหน้าที่คอยบอกคอมไพเลอร์ว่าเนื้อหาภายในฟังก์ชัน (function body) เริ่มต้นตรงจุดใดและไปสิ้นสุดลงตรงจุดใด

เราสามารถสั่งเรียกใช้งานฟังก์ชันใดๆ ที่เราสร้างไว้ได้โดยป้อนพิมพ์ชื่อของฟังก์ชันตามด้วยเครื่องหมายวงเล็บ เนื่องจากฟังก์ชัน another_function ได้รับการประกาศจัดทำไว้ในตัวโปรแกรม มันจึงสามารถถูกสั่งเรียกใช้งานจากขอบเขตด้านในฟังก์ชัน main ได้ พึงสังเกตว่าเราเลือกเขียนประกาศนิยาม another_function ไว้ ถัดจาก ฟังก์ชัน main ในโครงสร้างของซอร์สโค้ด ซึ่งตามจริงแล้วเราสามารถเขียนสลับไปนิยามไว้ก่อนหน้าฟังก์ชัน main ก็ได้เช่นกัน Rust ไม่ได้ใส่ใจเรื่องลำดับจุดที่คุณระบุตำแหน่งนิยามฟังก์ชัน ขอเพียงแค่ให้พวกมันถูกประกาศไว้ที่ใดสักแห่งในขอบเขตการทำงานที่ผู้เรียกใช้งานจะมองเห็นได้ก็เพียงพอแล้ว

มาลองเริ่มสร้างโปรเจกต์ไบนารีใหม่ชื่อว่า functions เพื่อร่วมกันศึกษาเรียนรู้ฟังก์ชันเพิ่มเติมกัน ให้ลองเขียนตัวอย่างฟังก์ชัน another_function ข้างต้นลงในไฟล์ src/main.rs แล้วรันโปรแกรมดู คุณควรจะพบผลลัพธ์แสดงดังต่อไปนี้:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.28s
     Running `target/debug/functions`
Hello, world!
Another function.

บรรทัดคำสั่งต่างๆ จะได้รับการประมวลผลตามลำดับก่อนหลังที่ระบุไว้ในฟังก์ชัน main โดยอันดับแรก ข้อความ “Hello, world!” จะแสดงขึ้นมาก่อน หลังจากนั้นฟังก์ชัน another_function จะถูกเรียกทำงานและแสดงผลข้อความย่อยภายในของมันออกมา

พารามิเตอร์ (Parameters)

เราสามารถประกาศออกแบบฟังก์ชันให้มี พารามิเตอร์ (parameters) ได้ ซึ่งพารามิเตอร์คือตัวแปรชนิดพิเศษที่เป็นองค์ประกอบส่วนหนึ่งในลายเซ็นของฟังก์ชัน (function’s signature) เมื่อฟังก์ชันมีพารามิเตอร์ คุณจะสามารถส่งมูลค่าที่ชัดเจนของข้อมูลไปผูกกับพารามิเตอร์เหล่านั้นได้ ซึ่งในเชิงวิชาการแล้ว ค่าข้อมูลจริงที่ส่งไปนั้นจะเรียกว่า อาร์กิวเมนต์ (arguments) แต่ในระดับบทสนทนาทั่วไป ผู้คนมักจะพูดคุยโดยหยิบใช้คำว่า parameter และ argument สลับแทนที่กันในความหมายเดียวกันได้ ไม่ว่าจะหมายถึงตัวแปรในนิยามต้นแบบของฟังก์ชัน หรือหมายถึงค่าข้อมูลเดี่ยวที่ส่งเข้าไปเมื่อตอนเรียกใช้ฟังก์ชัน

ในโครงสร้างเวอร์ชันนี้ของ another_function เราได้เติมพารามิเตอร์เพิ่มเข้าไปดังนี้:

Filename: src/main.rs

fn main() {
    another_function(5);
}

fn another_function(x: i32) {
    println!("The value of x is: {x}");
}

ลองสั่งรันตัวโปรแกรมนี้ดู คุณควรจะได้รับรายงานผลลัพธ์ปรากฏดังนี้:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 1.21s
     Running `target/debug/functions`
The value of x is: 5

การประกาศของ another_function จะมีพารามิเตอร์ตัวแปรอยู่ 1 ตัวชื่อว่า x โดยที่ชนิดข้อมูลของ x จะถูกกำหนดจำเพาะเป็นประเภท i32 และเมื่อเราสั่งป้อนค่า 5 เข้าไปในการเรียกใช้งาน another_function ทางมาโคร println! จะดำเนินการนำเอาเลข 5 เข้าไปแทนที่ตำแหน่งเครื่องหมายปีกกาคู่ที่มีตัวแปร x บรรจุอยู่ภายในข้อความควบคุม

ในส่วนของลายเซ็นฟังก์ชัน คุณ จำเป็นต้อง ประกาศชนิดข้อมูลของแต่ละพารามิเตอร์กำกับไว้เสมอ นี่จัดเป็นการตัดสินใจออกแบบอย่างจงใจตั้งแต่ขั้นวางรากฐานของภาษา Rust: การบังคับให้ป้อนชนิดข้อมูลในนิยามต้นแบบฟังก์ชันช่วยให้ตัวคอมไพเลอร์ไม่จำเป็นต้องมาขอร้องให้นักพัฒนาคอยระบุชนิดข้อมูลเหล่านั้นในส่วนอื่นๆ ของโค้ดเพื่อช่วยเดาความหมายชนิดข้อมูล และนอกจากนี้คอมไพเลอร์ยังสามารถส่งคืนข้อความแสดงความผิดพลาดที่เป็นประโยชน์และชี้แนะทางแก้ได้ดียิ่งขึ้นเมื่อมันรับทราบว่าตัวฟังก์ชันกำลังคาดหวังชนิดข้อมูลประเภทใด

เมื่อต้องการกำหนดออกแบบพารามิเตอร์หลายๆ ตัว ให้ใช้เครื่องหมายจุลภาคคั่นระหว่างการประกาศพารามิเตอร์แต่ละตัว ดังนี้:

Filename: src/main.rs

fn main() {
    print_labeled_measurement(5, 'h');
}

fn print_labeled_measurement(value: i32, unit_label: char) {
    println!("The measurement is: {value}{unit_label}");
}

ในกรณีตัวอย่างนี้จะเป็นการสร้างฟังก์ชันชื่อว่า print_labeled_measurement โดยประกอบด้วยพารามิเตอร์ 2 ตัว พารามิเตอร์แรกชื่อว่า value ซึ่งเป็นข้อมูลชนิด i32 ส่วนตัวที่สองชื่อว่า unit_label เป็นข้อมูลชนิด char จากนั้นภายในฟังก์ชันจะสั่งพิมพ์ข้อความรายงานข้อมูลซึ่งรวมมูลค่าของทั้ง value และ unit_label ออกมา

ลองมาทดสอบรันโค้ดส่วนนี้ดู ให้ลองนำตัวอย่างด้านบนนี้ไปเขียนแทนที่โค้ดเดิมในไฟล์ src/main.rs ของโปรเจกต์ functions ของคุณ แล้วรันผ่านคำสั่ง cargo run:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.31s
     Running `target/debug/functions`
The measurement is: 5h

และเนื่องจากเราดำเนินการเรียกใช้ฟังก์ชันโดยส่งผ่านอาร์กิวเมนต์ตัวเลข 5 เป็นมูลค่าของ value และส่งตัวอักษร 'h' เป็นมูลค่าของ unit_label ผลลัพธ์การรายงานของโปรแกรมจึงแสดงค่าตัวแปรทั้งคู่ปรากฏให้เราเห็น

คำสั่งและนิพจน์ (Statements and Expressions)

เนื้อหาในขอบเขตการทำงานของฟังก์ชันจะประกอบขึ้นมาจากกลุ่มของประโยคคำสั่ง (statements) และอาจมีหรือไม่มีจุดลงท้ายด้วยนิพจน์ (expression) ก็ได้ จนถึงบรรทัดนี้ ฟังก์ชันต่างๆ ที่เราเขียนร่วมกันมายังไม่ได้ใส่ส่วนขอบเขตนิพจน์ปิดท้ายการทำงานเลย แต่คุณอาจจะพบเห็นนิพจน์แทรกตัวทำงานร่วมเป็นส่วนหนึ่งของประโยคคำสั่งแล้ว เนื่องจากภาษา Rust ถูกจัดเป็นภาษาที่มีรากฐานแนวคิดบนรูปแบบนิพจน์ (expression-based language) ประเด็นข้อแตกต่างนี้จึงมีความสำคัญอย่างมากที่ผู้เรียนจำเป็นต้องทำความเข้าใจ ในภาษาโปรแกรมอื่นอาจจะไม่มีการแบ่งรายละเอียดจำแนกเรื่องพวกนี้ชัดเจนนัก มาลองดูกันเลยว่าคำสั่งและนิพจน์คืออะไร และความแตกต่างของพวกมันส่งผลอย่างไรต่อโครงสร้างเนื้อหาของฟังก์ชัน

  • ประโยคคำสั่ง (Statements) คือคำสั่งที่มีหน้าที่ระบุให้โปรแกรมดำเนินการทางพฤติกรรมบางอย่าง และไม่ส่งคืนผลลัพธ์มูลค่าข้อมูลใดๆ กลับออกมา
  • นิพจน์ (Expressions) คือโครงสร้างส่วนที่คำนวณและประเมินผลลัพธ์ออกมาเป็นมูลค่าค่าหนึ่ง

มาลองพิจารณาตัวอย่างพฤติกรรมร่วมกัน

จริงๆ แล้วเราเคยได้หยิบเอาประโยคคำสั่งและนิพจน์มาเขียนโปรแกรมใช้งานอยู่บ่อยครั้งแล้ว ขั้นตอนจัดตั้งตัวแปรและส่งมอบข้อมูลเข้าไปจัดเก็บด้วยคำสำคัญ let จะนับเป็นประโยคคำสั่ง ในรายการที่ 3-1 ข้อความคำสั่ง let y = 6; คือตัวแทนของประโยคคำสั่ง

fn main() {
    let y = 6;
}

ขั้นตอนการประกาศนิยามจัดทำฟังก์ชัน (function definitions) ก็นับเป็นประโยคคำสั่งเช่นเดียวกัน ตัวอย่างซอร์สโค้ดด้านบนทั้งหมดข้างต้นจึงจัดเป็นรูปประโยคคำสั่งในตัวมันเองด้วย (แต่ทว่าขั้นตอนสั่งการเรียกใช้ฟังก์ชันจะไม่ได้นับเป็นประโยคคำสั่ง ดังที่เราจะสังเกตเห็นได้ในอีกไม่ช้า)

ประโยคคำสั่งจะไม่คืนค่าข้อมูลใด ๆ กลับออกมาเลย ดังนั้นคุณจึงไม่สามารถสั่งเขียนผูกนำเอาประโยคคำสั่ง let ไปมอบให้แก่ตัวแปรอื่นได้ เช่นเดียวกับที่ตัวอย่างโค้ดด้านล่างนี้พยายามจะเขียนขึ้น ซึ่งจะทำให้ระบบเกิดข้อผิดพลาดขึ้นทันที:

Filename: src/main.rs

fn main() {
    let x = (let y = 6);
}

เมื่อคุณสั่งรันตัวโปรแกรมนี้ ข้อผิดพลาดที่รายงานขึ้นบนหน้าจอจะมีลักษณะดังนี้:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
error: expected expression, found `let` statement
 --> src/main.rs:2:14
  |
2 |     let x = (let y = 6);
  |              ^^^
  |
  = note: only supported directly in conditions of `if` and `while` expressions

warning: unnecessary parentheses around assigned value
 --> src/main.rs:2:13
  |
2 |     let x = (let y = 6);
  |             ^         ^
  |
  = note: `#[warn(unused_parens)]` (part of `#[warn(unused)]`) on by default
help: remove these parentheses
  |
2 -     let x = (let y = 6);
2 +     let x = let y = 6 ;
  |

warning: `functions` (bin "functions") generated 1 warning
error: could not compile `functions` (bin "functions") due to 1 previous error; 1 warning emitted

ประโยคคำสั่ง let y = 6 จะไม่ส่งคืนผลลัพธ์ข้อมูลใด ๆ ออกมาเลย ส่งผลให้โปรแกรมไม่มีมูลค่าชิ้นใดหลงเหลืออยู่นำไปส่งผูกต่อให้แก่ตัวแปร x ได้เลย พฤติกรรมนี้จะต่างไปจากผลลัพธ์ของภาษาโปรแกรมอื่นอย่างเช่นภาษา C หรือ Ruby ที่ขั้นตอนกำหนดเก็บค่าตัวแปรจะดำเนินการส่งคืนมูลค่าข้อมูลที่จัดเก็บนั้นกลับออกมาด้วย ซึ่งในระบบของภาษาเหล่านั้นคุณจะสามารถเขียนคำสั่งผูกต่อเนื่องย่อเป็น x = y = 6 เพื่อส่งผลลัพธ์ให้ทั้ง x และ y ร่วมถือครองเลข 6 ไปพร้อมๆ กันได้ แต่เงื่อนไขนี้ไม่สามารถนำมาใช้กับภาษา Rust ได้

นิพจน์จะคำนวณและคืนผลลัพธ์ออกเป็นมูลค่าข้อมูล ซึ่งเนื้อหาโครงสร้างส่วนใหญ่ที่เหลือของโค้ดที่คุณเขียนในภาษา Rust จะสร้างขึ้นด้วยรูปแบบของนิพจน์ ลองมาดูตัวอย่างการคำนวณเลขอย่าง 5 + 6 ซึ่งนับเป็นนิพจน์ที่ประเมินผลคืนค่าออกมาเป็นมูลค่าเลข 11 นิพจน์นั้นสามารถฝังรวมอยู่เป็นส่วนหนึ่งของประโยคคำสั่งได้ เช่นในตารางที่ 3-1 ตัวเลข 6 ในคำสั่ง let y = 6; ก็นับเป็นนิพจน์ที่ประเมินตัวมันเองออกมามีค่าเป็น 6 การเรียกฟังก์ชันก็นับเป็นนิพจน์ การรันชุดคำสั่งมาโครก็นับเป็นนิพจน์ รวมถึงการประกาศบล็อกจัดพื้นที่ขอบเขตใหม่ด้วยการปีกกาคร่อมก็ถือเป็นรูปแบบนิพจน์ด้วยเช่นกัน ตัวอย่างเช่น:

Filename: src/main.rs

fn main() {
    let y = {
        let x = 3;
        x + 1
    };

    println!("The value of y is: {y}");
}

ตัวนิพจน์ด้านล่างนี้:

{
    let x = 3;
    x + 1
}

คือโครงสร้างบล็อกคำสั่งซึ่งในกรณีนี้ประเมินมูลค่าออกมารายงานได้ค่าเป็น 4 ซึ่งมูลค่าดังกล่าวจะถูกนำไปผูกมัดเก็บไว้กับตัวแปร y ภายใต้ขั้นตอนการรันประโยคคำสั่ง let พึงระลึกและสังเกตว่าบรรทัด x + 1 จะเขียนระบุไว้ปราศจากเครื่องหมายอัฒภาค (semicolon) ลงท้ายบรรทัด ซึ่งจะต่างไปจากโครงสร้างส่วนใหญ่ที่คุณเคยเห็นผ่านหูผ่านตามาก่อนหน้านี้ เนื่องจากนิพจน์จะไม่อนุญาตให้เขียนปิดท้ายบรรทัดด้วยเครื่องหมายอัฒภาคเป็นอันขาด หากคุณเผลอใส่สัญลักษณ์อัฒภาคกำกับปิดท้ายนิพจน์ รูปประโยคส่วนนั้นจะถูกสลับแปรสภาพไปนับเป็นโครงสร้างประโยคคำสั่ง (statement) ทันที ซึ่งจะไม่ส่งมูลค่าคืนผลลัพธ์ข้อมูลใด ๆ ออกมาอีกเลย โปรดจดจำเงื่อนไขข้อนี้ให้ขึ้นใจเพื่อนำไปประยุกต์ใช้งานกับการศึกษาเรื่องการส่งคืนค่าฟังก์ชันในสเต็ปถัดไป

ฟังก์ชันที่มีการส่งคืนค่าผลลัพธ์ (Functions with Return Values)

ฟังก์ชันสามารถส่งคืนผลลัพธ์ข้อมูลกลับไปยังจุดโค้ดที่รันสั่งเรียกใช้มันได้ตามสมควร เราไม่จำเป็นต้องตั้งชื่อเฉพาะให้กับข้อมูลขากลับนี้ แต่เรามีหน้าที่ต้องเขียนระบุชนิดประเภทของข้อมูลขากลับนั้นตามหลังป้ายสัญลักษณ์ลูกศร (->) เสมอ ในภาษา Rust ค่าข้อมูลคืนกลับของฟังก์ชันจะทำหน้าที่เปรียบเสมือนค่าข้อมูลตัวเดียวกับนิพจน์สุดท้าย (final expression) ที่ปรากฏอยู่ด้านในบล็อกเนื้อความฟังก์ชัน คุณสามารถระบุสั่งขอหยุดการทำงานฟังก์ชันและคืนผลลัพธ์ล่วงหน้าทันทีได้ผ่านการป้อนคำสำคัญ return ร่วมกับการระบุค่าข้อมูลที่ประสงค์จะคืนกลับ แต่ปรกติโดยทั่วไปแล้ว ฟังก์ชันใน Rust ส่วนใหญ่จะส่งคืนค่านิพจน์สุดท้ายโดยอัตโนมัติ (implicitly) ต่อไปนี้เป็นตัวอย่างฟังก์ชันที่มีการส่งคืนค่าขากลับ:

Filename: src/main.rs

fn five() -> i32 {
    5
}

fn main() {
    let x = five();

    println!("The value of x is: {x}");
}

ไม่พบกระบวนการเรียกใช้งานฟังก์ชันอื่น ไม่พบคู่มือมาโคร และไม่มีแม้แต่ประโยคคำสั่ง let อยู่ภายในขอบเขตฟังก์ชัน five เลย มีเพียงมูลค่าตัวเลข 5 โดดๆ วางอยู่ตัวเดียวเท่านั้น แต่นี่คือโครงสร้างฟังก์ชันที่ถูกต้องและสมบูรณ์ทุกประการของภาษา Rust พึงระลึกว่าชนิดขากลับของฟังก์ชันได้รับการระบุกำกับไว้เช่นกันเป็นลูกศร -> i32 ลองมาทดสอบรันโค้ดส่วนนี้ดู ผลลัพธ์ควรจะรายงานผลปรากฏดังนี้:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.30s
     Running `target/debug/functions`
The value of x is: 5

เลข 5 ด้านในฟังก์ชัน five ทำหน้าที่เป็นมูลค่าข้อมูลขากลับของฟังก์ชัน จึงเป็นเหตุผลว่าเหตุใดถึงเขียนระบุชนิดขากลับกำกับเป็น i32 มาลองดูพฤติกรรมนี้ให้ละเอียดขึ้นอีกสักนิด โดยมีประเด็นสำคัญอยู่ 2 จุดด้วยกัน: ประการแรกคือ แถวโค้ด let x = five(); ชี้ให้เห็นว่าเราสามารถนำเอาค่าผลลัพธ์ขากลับจากการทำงานของฟังก์ชันมาใช้ประกาศตั้งต้นมูลค่าตัวแปรได้ เนื่องจากฟังก์ชัน five ส่งคืนมูลค่าข้อมูลเป็น 5 บรรทัดดังกล่าวจึงมีผลเทียบเท่ากับการพิมพ์คำสั่งตรงๆ ว่า:

#![allow(unused)]
fn main() {
let x = 5;
}

และประการที่สองคือ ฟังก์ชัน five ไม่มีพารามิเตอร์ใด ๆ พ่วงมาด้วยและมีการระบุข้อมูลชนิดขากลับไว้ครบถ้วน ทว่าเนื้อหาภายในตัวของฟังก์ชันมีเพียงข้อมูลสเกลาร์เลข 5 ตั้งอยู่เดี่ยวๆ ปราศจากเครื่องหมายอัฒภาคลงท้ายเนื่องจากมันคือนิพจน์ที่เราต้องการส่งค่าคืนกลับไปนั่นเอง

มาลองพิจารณาตัวอย่างถัดไปเพิ่มเติม:

Filename: src/main.rs

fn main() {
    let x = plus_one(5);

    println!("The value of x is: {x}");
}

fn plus_one(x: i32) -> i32 {
    x + 1
}

ขั้นตอนการสั่งรันโค้ดส่วนนี้จะแสดงผลออกมาเป็น The value of x is: 6 แต่จะเกิดอะไรขึ้นหากเรานำสัญลักษณ์อัฒภาค (semicolon) ไปใส่ลงท้ายบรรทัดโค้ดส่วนนิพจน์ x + 1 เพื่อเปลี่ยนแปลงระบบคำนวณจากรูปนิพจน์ไปเป็นรูปแบบประโยคคำสั่งแทน?

Filename: src/main.rs

fn main() {
    let x = plus_one(5);

    println!("The value of x is: {x}");
}

fn plus_one(x: i32) -> i32 {
    x + 1;
}

ขั้นตอนการประกอบคอมไพล์โค้ดชุดดังกล่าวจะทำให้เกิดข้อผิดพลาดขึ้น ดังรายงานผลลัพธ์นี้:

$ cargo run
   Compiling functions v0.1.0 (file:///projects/functions)
error[E0308]: mismatched types
 --> src/main.rs:7:24
  |
7 | fn plus_one(x: i32) -> i32 {
  |    --------            ^^^ expected `i32`, found `()`
  |    |
  |    implicitly returns `()` as its body has no tail or `return` expression
8 |     x + 1;
  |          - help: remove this semicolon to return this value

For more information about this error, try `rustc --explain E0308`.
error: could not compile `functions` (bin "functions") due to 1 previous error

ใจความสำคัญของข้อผิดพลาดระบุปัญหาชนิดข้อมูลไม่เข้ากัน (mismatched types) ซึ่งชี้ต้นเหตุของข้อผิดพลาดในโค้ดตัวอย่างนี้ โดยโครงสร้างนิยามของฟังก์ชัน plus_one ประกาศกฎเกณฑ์ไว้ชัดเจนว่าจะต้องทำการคืนค่าขากลับเป็นข้อมูลชนิด i32 แต่ประโยคคำสั่ง (statements) จะคำนวณและรายงานมูลค่าตัวแปรออกเป็นค่าว่างเปล่า ซึ่งแทนสภาพด้วยยูนิต () (unit type) ส่งผลให้ฟังก์ชันไม่มีผลลัพธ์มูลค่าข้อมูลขากลับส่งต่อไปให้ผู้รับ ซึ่งมีเงื่อนไขขัดแย้งกับลายเซ็นฟังก์ชันที่ตกลงกันไว้และเกิดปัญหาขึ้นตามมา ในหน้าต่างรายงานผลลัพธ์การแครชนี้ Rust ได้ระบุคำชี้แนะถึงหนทางช่วยแก้ปัญหาที่เหมาะสมไว้ด้วย นั่นคือเสนอแนะให้ลบเครื่องหมายอัฒภาค (semicolon) ท้ายบรรทัดออกไป ซึ่งจะช่วยแก้ไขปัญหาของโปรแกรมนี้ให้กลับมาคอมไพล์ได้สำเร็จ