E0369: Operador Não Pode Ser Aplicado
O erro E0369 ocorre quando você tenta usar um operador binário (como +, -, *, ==) em tipos que não implementam o trait correspondente. No Rust, operadores são definidos por traits — e tipos customizados precisam implementá-los explicitamente.
A Mensagem de Erro
error[E0369]: binary operation `+` cannot be applied to type `Vetor2D`
--> src/main.rs:10:22
|
10 | let soma = v1 + v2;
| -- ^ -- Vetor2D
| |
| Vetor2D
|
= note: an implementation of `std::ops::Add` is missing for `Vetor2D`
Outra variação com comparação:
error[E0369]: binary operation `==` cannot be applied to type `Produto`
--> src/main.rs:8:16
|
8 | if item1 == item2 {
| ----- ^^ ----- Produto
| |
| Produto
|
= note: an implementation of `PartialEq` is missing for `Produto`
O Que Significa
No Rust, cada operador é mapeado para um trait específico do módulo std::ops:
| Operador | Trait |
|---|---|
+ | std::ops::Add |
- | std::ops::Sub |
* | std::ops::Mul |
/ | std::ops::Div |
% | std::ops::Rem |
==, != | std::cmp::PartialEq |
<, >, <=, >= | std::cmp::PartialOrd |
- (unário) | std::ops::Neg |
! | std::ops::Not |
<<, >> | std::ops::Shl, std::ops::Shr |
&, |, ^ | std::ops::BitAnd, BitOr, BitXor |
Tipos primitivos (i32, f64, etc.) já implementam esses traits. Tipos customizados (structs, enums) precisam de implementação manual ou via #[derive].
Código com Erro
struct Vetor2D {
x: f64,
y: f64,
}
fn main() {
let v1 = Vetor2D { x: 1.0, y: 2.0 };
let v2 = Vetor2D { x: 3.0, y: 4.0 };
// ERRO: Vetor2D não implementa Add
let soma = v1 + v2;
// ERRO: Vetor2D não implementa PartialEq
let igual = v1 == v2;
}
Também acontece ao tentar operar entre tipos diferentes:
fn main() {
let texto = String::from("Olá");
let numero = 42;
// ERRO: não pode somar String com i32
let resultado = texto + numero;
}
Como Resolver
Solução 1: Usar #[derive] para Comparações
Para operadores de comparação, use derive:
#[derive(Debug, PartialEq, PartialOrd)]
struct Temperatura {
celsius: f64,
}
fn main() {
let t1 = Temperatura { celsius: 25.0 };
let t2 = Temperatura { celsius: 30.0 };
println!("Iguais: {}", t1 == t2); // PartialEq
println!("Menor: {}", t1 < t2); // PartialOrd
}
Solução 2: Implementar Traits de Operadores Manualmente
Para +, -, * e outros operadores aritméticos, implemente o trait correspondente:
use std::ops::Add;
#[derive(Debug, Clone, Copy)]
struct Vetor2D {
x: f64,
y: f64,
}
impl Add for Vetor2D {
type Output = Vetor2D;
fn add(self, outro: Vetor2D) -> Vetor2D {
Vetor2D {
x: self.x + outro.x,
y: self.y + outro.y,
}
}
}
fn main() {
let v1 = Vetor2D { x: 1.0, y: 2.0 };
let v2 = Vetor2D { x: 3.0, y: 4.0 };
let soma = v1 + v2;
println!("{:?}", soma); // Vetor2D { x: 4.0, y: 6.0 }
}
Implementando múltiplos operadores:
use std::ops::{Add, Sub, Mul, Neg};
#[derive(Debug, Clone, Copy, PartialEq)]
struct Vetor2D {
x: f64,
y: f64,
}
impl Sub for Vetor2D {
type Output = Vetor2D;
fn sub(self, outro: Vetor2D) -> Vetor2D {
Vetor2D {
x: self.x - outro.x,
y: self.y - outro.y,
}
}
}
impl Mul<f64> for Vetor2D {
type Output = Vetor2D;
fn mul(self, escalar: f64) -> Vetor2D {
Vetor2D {
x: self.x * escalar,
y: self.y * escalar,
}
}
}
impl Neg for Vetor2D {
type Output = Vetor2D;
fn neg(self) -> Vetor2D {
Vetor2D {
x: -self.x,
y: -self.y,
}
}
}
fn main() {
let v = Vetor2D { x: 1.0, y: 2.0 };
println!("Dobro: {:?}", v * 2.0);
println!("Negativo: {:?}", -v);
}
Solução 3: Converter Tipos Antes de Operar
Quando os tipos são diferentes, converta antes:
fn main() {
let texto = String::from("Olá, ");
let complemento = "mundo!";
// String + &str funciona!
let resultado = texto + complemento;
println!("{}", resultado);
// Para concatenar sem mover, use format!
let a = String::from("Olá");
let b = String::from("mundo");
let resultado = format!("{}, {}!", a, b);
println!("{}", resultado);
}
Para números:
fn main() {
let inteiro: i32 = 10;
let decimal: f64 = 3.14;
// ERRO: i32 + f64 não é permitido
// let resultado = inteiro + decimal;
// Converta primeiro:
let resultado = f64::from(inteiro) + decimal;
println!("{}", resultado); // 13.14
}
Dica: AddAssign, SubAssign, etc.
Para usar operadores de atribuição composta (+=, -=), implemente os traits correspondentes:
use std::ops::AddAssign;
#[derive(Debug)]
struct Contador {
valor: i32,
}
impl AddAssign<i32> for Contador {
fn add_assign(&mut self, rhs: i32) {
self.valor += rhs;
}
}
fn main() {
let mut c = Contador { valor: 0 };
c += 5;
c += 3;
println!("{:?}", c); // Contador { valor: 8 }
}