Por que limites de estreito diferentes do primeiro não são reconhecidos em um tipo associado?
Esse snippet é válido no Rust 1.26.1:
use std::ops::AddAssign;
trait Trait
where
for<'a> Self: AddAssign<Self> + AddAssign<&'a Self> + Sized,
{
}
trait Trait2 {
type Associated: Trait;
fn method(u32) -> Self::Associated;
}
fn func<T2: Trait2>() {
let mut t = T2::method(1);
let t2 = T2::method(2);
t += &t2;
}
Notar queTrait
implementa ambosAddAssign<Self>
eAddAssign<&'a Trait>
(nessa ordem, que é importante mais tarde). Portanto, emfunc
sabemos que ambost += t2
et += &t2
deve ser válido. Como vistono parquinho, t += &t2
é válido, masusandot += t2
não é:
error[E0308]: mismatched types
--> src/main.rs:19:10
|
19 | t += t2;
| ^^
| |
| expected reference, found associated type
| help: consider borrowing here: `&t2`
|
= note: expected type `&<T2 as Trait2>::Associated`
found type `<T2 as Trait2>::Associated`
Eu li esse erro como o compilador que não reconhece issoAddAssign<Self>
é implementado paraT::Associated
, o que está claramente errado, pois implementaTrait
, o que exigeAddAssign<Self>
.
Se mudarmos a ordem doAddAssign
limites emTrait
então o oposto vale:t += t2
é válido enquantot += &t2
não é.
Uma solução rápida para o problema é fazerfunc
genérico sobre ambas as características:
fn func<T: Trait, T2: Trait2<Associated = T>>() {
let mut t = T2::method(1);
let t2 = T2::method(2);
t += t2;
}
Isso não deveria ser necessário; o compilador pode reconhecer um dosAddAssign
s, por que não o outro? Parece que o último limite é aquele a ser reconhecido.
Minha primeira suspeita foi que isso tem algo a ver com o envio dinâmico. Eu descartei, já que a ordem dos limites não deveria importar nem mesmo em expedição dinâmica. Eu nem acho que ele usa, já que todos os tipos são conhecidos em tempo de compilação usando monomorfização.
Minha suspeita atual é um bug do compilador, em que o verificador tipográfico não responde por genéricos nos limites de características quando é um tipo associado. É fácil imaginar um caso tão específico sendo esquecido.
O que está acontecendo aqui?