rust - ¿Por qué el compilador no puede analizar "a como u32<b" o similar?
syntax-error (1)
El siguiente código parece ser trivial y no ambiguo ( Playground ):
let a: u16 = 5;
let b: u32 = 10;
let c = a as u32 < b;
Sin embargo, el compilador (a partir del 2017-05-30) falla con un error de sintaxis:
error: expected one of `!`, `(`, `+`, `,`, `::`, `<`, or `>`, found `;`
--> src/main.rs:6:25
|
6 | let c = a as u32 < b;
|
¿Qué pasa con el compilador?
Nota: Los últimos compiladores de Rust ahora proporcionan un mensaje de error más útil ( # 42578 ):
error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison
--> src/main.rs:6:22
|
6 | let c = a as u32 < b;
| -------- ^ -- interpreted as generic arguments
| | |
| | not interpreted as comparison
| help: try comparing the casted value: `(a as u32)`
Este es un problema conocido del compilador ( # 22644 ). En pocas palabras, dado que un tipo ( u32
) fue seguido por <
, el compilador intentó analizar <
como el comienzo de una lista de parámetros de tipo. Por lo tanto, el compilador esperaba algo así como u32 < b >
, que sería sintácticamente válido, aunque no tenga sentido. Sin embargo, un ejemplo que hace que Rust sea perfectamente válido es foo as Rc < fmt::Debug >
, y si la sintaxis era demasiado ansiosa para hacer <
el operador menor que este, fallaría de todos foo as Rc < fmt::Debug >
.
Por supuesto, técnicamente hay formas de evitarlo: C ++ y C # han tenido la misma ambigüedad desde el principio, simplemente tienen algunos mecanismos que eliminan la ambigüedad de estos casos (como la anticipación de un número arbitrario de tokens), aunque también hacen el analizador más complejo. La inclusión de esos mecanismos en Rust podría llevar a romper los cambios en la sintaxis (o probablemente solo en la caja de sintaxis de rustc).
Como actualmente no hay una discusión activa para abordar este problema, una solución bastante simple y de largo plazo es envolver al elenco entre paréntesis:
let c = (a as u32) < b;