É possível que mudar o tipo de argumento de função de impl Trait
para genérico seja uma mudança drástica? A Rust Reference afirma que:
Nota: Para parâmetros de função, parâmetros de tipo genérico e
impl Trait
não são exatamente equivalentes. Com um parâmetro genérico como<T: Trait>
, o chamador tem a opção de especificar explicitamente o argumento genérico paraT
no site da chamada usando GenericArgs , por exemplo,foo::<usize>(1)
. Seimpl Trait
for o tipo de qualquer parâmetro de função, então o chamador não pode fornecer nenhum argumento genérico ao chamar essa função. Isso inclui argumentos genéricos para o tipo de retorno ou quaisquer genéricos const.Portanto, alterar a assinatura da função de uma para outra pode constituir uma alteração drástica para os chamadores de uma função.
Mas dado que, se houver pelo menos um impl Trait
parâmetro, então o chamador não pode nomear nenhum argumento genérico, isso não deveria implicar que mudar impl Trait
para <T: Trait>
can somente permite que os chamadores nomeiem argumentos genéricos? Como os genéricos já foram inferidos, não podemos também quebrar a inferência de tipo.
EDIT: Eu presumo que cada um impl Trait
é alterado para um tipo genérico diferente e únicoimpl Trait
(sem sobreposição com outros s ou genéricos anteriores). Violar isso seria obviamente quebrar, obrigado a @啊鹿Dizzyi por apontar isso.
Listo aqui uma lista de casos (que acredito ser exaustiva) onde impl Trait
é alterado para um genérico. Se algum deles puder quebrar downstream, por favor mostre como. E se eu perdi algum caso, por favor explique se ele está quebrando.
- Mudando apenas
impl Trait
// before
pub fn foo(_: impl Trait) {}
// after
pub fn foo<T: Trait>(_: T) {}
- Muitos
impl Trait
, mas mudando apenas alguns deles
// before
pub fn foo(_: impl Trait1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2>(_: T1, _: T2, _: impl Trait3) {}
- Muitos
impl Trait
, mudando todos eles
// before
pub fn foo(_: impl Trait1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2, T3: Trait3>(_: T1, _: T2, _: T3) {}
- Alguns tipos genéricos, alterando alguns
impl Trait
s, mas deixando pelo menos um
// before
pub fn foo<T1: Trait1>(_: T1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2>(_: T1, _: T2, _: impl Trait3) {}
- Alguns tipos genéricos, alterando todos os
impl Trait
s
// before
pub fn foo<T1: Trait1>(_: T1, _: impl Trait2, _: impl Trait3) {}
// after
pub fn foo<T1: Trait1, T2: Trait2, T3: Trait3>(_: T1, _: T2, _: T3) {}