Выражения вызовов
Syntax
CallExpression → Expression ( CallParams? )
CallParams → Expression ( , Expression )* ,?
Выражение вызова вызывает функцию. Синтаксис выражения вызова: выражение, называемое функциональным операндом, за которым следует заключенный в круглые скобки разделенный запятыми список выражений, называемых операндами аргументов.
Если функция в конечном итоге возвращает значение, то выражение завершается.
Для не-функциональных типов выражение f(...) использует метод одного из следующих трейтов в зависимости от функционального операнда:
FnилиAsyncFn— разделяемая ссылка.FnMutилиAsyncFnMut— изменяемая ссылка.FnOnceилиAsyncFnOnce— значение.
Автоматическое заимствование будет выполнено при необходимости. Функциональный операнд также будет автоматически разыменован по мере необходимости.
Некоторые примеры выражений вызовов:
#![allow(unused)] fn main() { fn add(x: i32, y: i32) -> i32 { 0 } let three: i32 = add(1i32, 2i32); let name: &'static str = (|| "Rust")(); }
Разрешение неоднозначности вызовов функций
Все вызовы функций являются синтаксическим сахаром для более явного полностью квалифицированного синтаксиса.
Вызовы функций могут нуждаться в полной квалификации в зависимости от неоднозначности вызова в свете элементов в области видимости.
Note
В прошлом термины “Unambiguous Function Call Syntax”, “Universal Function Call Syntax” или “UFCS” использовались в документации, issues, RFC и других материалах сообщества. Однако этим терминам не хватает описательной силы, и они потенциально запутывают суть вопроса. Мы упоминаем их здесь для удобства поиска.
Несколько ситуаций часто возникают, которые приводят к неоднозначностям относительно получателя или референта вызовов методов или ассоциированных функций. Эти ситуации могут включать:
- Несколько трейтов в области видимости определяют методы с одинаковыми именами для одних и тех же типов
- Авто-
derefнежелателен; например, различение методов на самом умном указателе и референте указателя - Методы, которые не принимают аргументов, такие как
default(), и возвращают свойства типа, такие какsize_of()
Чтобы разрешить неоднозначность, программист может ссылаться на желаемый метод или функцию, используя более конкретные пути, типы или трейты.
Например,
trait Pretty { fn print(&self); } trait Ugly { fn print(&self); } struct Foo; impl Pretty for Foo { fn print(&self) {} } struct Bar; impl Pretty for Bar { fn print(&self) {} } impl Ugly for Bar { fn print(&self) {} } fn main() { let f = Foo; let b = Bar; // мы можем сделать это, потому что у нас только один элемент с именем `print` для `Foo` f.print(); // более явно и, в случае `Foo`, не необходимо Foo::print(&f); // если вы не любите краткость <Foo as Pretty>::print(&f); // b.print(); // Ошибка: найдено несколько 'print' // Bar::print(&b); // Все еще ошибка: найдено несколько `print` // необходимо из-за элементов в области видимости, определяющих `print` <Bar as Pretty>::print(&b); }
Обратитесь к RFC 132 для получения дополнительных деталей и мотивации.