Вопрос: Правильно ли решил задачу?

Лучший ответ: Можно сделать коллекцию из этих строк
"Two turtle-doves",  "Three French hens"
тогда алгоритм упрощается. Визуальная копи-паста уходит.

Худший ответ: Задачка прикольная для обучения, позволяет поработать сразу со многими конструкциями языка.

Для начала комментарии по Вашему решению:
1. Тип String алоцирует память на куче, операция += над типом String может приводить к реалокации памяти. Алокация памяти не дешевая операция, в данной задаче можно обойтись вообще без нее.
2. Для повторяющихся операций придумали циклы, а с циклами хорошо сочетаются коллекции, например массивы и слайсы.
3. Уже писали в комментах, но все же, if true - бесполезная штука.

Теперь давайте посмотрим на текст песни. У нас 12 куплетов.
Каждый куплет начинается с очень похожих строчек: "On the first day of Christmas", "On the second day of Christmas", и т.д., меняется только числительное.
Потом всегда идет строчка "My true love sent to me" в каждом куплете.
Затем идет от 1 до 12 строчек, повторяющиеся из куплета в куплет, но в i-том куплете будет только i таких строчек. Притом тут есть особенность, что первая строчка в куплете иногда отличается от своих аналогов в последующих куплетах.
Ну и наконец, в 12 куплете мы видим, что строка "And a partridge in a pear tree" присутствует 2 раза, что выбивается из общего правила.

Решение с объяснением
Для начала вынесем факт того, что у нас 12 куплетов в константу, это нам пригодится для дальнейшего объявления массивов и итерации по ним.
const NUMBER_OF_VERSES: usize = 12;

Заведем массив числительных, которые меняются в первых строчках куплетов.const NUMERALS: [&str; NUMBER_OF_VERSES] = [
    "first", "second", "third", "fourth", "fifth", "sixth", "seventh", "eighth", "ninth", "tenth",
    "11th", "12th",
];

Так же заведем массив, для повторяющихся строчек куплетов.const LINES: [&str; NUMBER_OF_VERSES] = [
    "And a partridge in a pear tree",
    "Two turtle-doves",
    "Three French hens",
    "Four calling birds",
    "Five golden rings (five golden rings)",
    "Six geese a-laying",
    "Seven swans a-swimming",
    "Eight maids a-milking",
    "Nine ladies dancing",
    "Ten lords a-leaping",
    "Eleven pipers piping",
    "12 drummers drumming",
];

Так же нам понадобится массив первых строчек куплетов, так как среди них есть отличающиеся. Я нашел такие в 1 и 11 куплете (так как массивы у нас индексируются с 0, то они будут под индексами 0 и 10 соответственно). Остальные же будут такими же как в массиве LINES, а значит можно по экономить размер бинаря и занимаемую память за счет того что в массивах у нас только ссылки на строки, которые можно копировать.
Тут конечно можно написать что-то вродеconst DIFFERING_LINES: [&str; NUMBER_OF_VERSES] = [
    "A partridge in a pear tree",
    LINES[1],
    LINES[2],
    // ...
];но это дикая копипаста, которая плохо читается и подвержена ошибкам.
Благо в Rust есть константные функции, которые могут выполняться в compile-time и возвращают константы, а значит можно наш константный массив сгенерировать. Правда константные функции довольно сильно ограничены, в них можно пользоваться лишь ветвлениями, циклами, простейшей арифметикой (в том числе над указателями, а значит и получать доступ к элементам массива по индексу). Так же можно вызывать другие константные функции. Цикл for нам к сожалению тут не доступен, так как он работает поверх итераторов, а методы IntoIter::into_iter и Iterator::next, которые он вызывает, не являются константными. Но цикл со счетчиком можно сделать и через while. По итогу получим такую функцию:const fn gen_differing_lines() -> [&'static str; NUMBER_OF_VERSES] {
    let mut i = 0;
    let mut lines = [""; NUMBER_OF_VERSES];
    while i < NUMBER_OF_VERSES {
        lines[i] = match i {
            0 => "A partridge in a pear tree",
            10 => "I sent 11 pipers piping",
            i => LINES[i],
        };
        i += 1;
    }
    lines
}
И инициализируем ей наш массив:const DIFFERING_LINES: [&str; NUMBER_OF_VERSES] = gen_differing_lines();

Теперь еще особенность, в самих куплетах, строчки из LINES в них идут в обратном порядке. То есть для 4 куплета (индекс 3) нам помимо строчки DIFFERING_LINES[3] нам нужно напечатать строки под индексами 2, 1 и 0 из LINES. Для удобства вынесем печать строк из LINES в отдельную функцию:fn print_verse(mut i: usize) {
    while i > 0 {
        i -= 1;
        println!("{}", LINES[i]);
    }
}

Ну и осталось написать основной код для печати:fn main() {
    for i in 0..NUMBER_OF_VERSES {
        println!("On the {} day of Christmas", NUMERALS[i]);
        println!("My true love sent to me");
        println!("{}", DIFFERING_LINES[i]);
        print_verse(i);
    }
    println!("{}", LINES[0]);
}

А полное решение можно посмотреть и запустить тут:
https://play.rust-lang.org/?version=stable&mode=re...