1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
|
# "Tudo dentro do Rust, nada fora do Rust"
Essa é a mentalidade que eu venho percebido dos programadores Rust que acredito
que isso deveria ser retificado. E eu acredito que eu tenha entendido a fonte
desse problema, então queria fazer um post sobre isso.
## O foco é no object-code
Um programa é basicamente uma grande ROM. Pode ter cabeçalhos ELF pra poder
auxiliar o carregamento e execução do software, ou ela pode ser um binário limpo
pra ser injetado de um hardware, mas no fim a ideia é a mesma, é uma ROM, e como
toda ROM, essa memória tem seções e regiões pra auxiliar na execução.
O pessoal do Rust parece ter esquecido desse detalhe. O Rust não vira um
executável, ele vira uma ROM, um object-code com headers pra auxiliar na próxima
etapa de montar um programa.
## Linkage
Como é uma merda gigantesca fazer um grande object-code, normalmente quebramos
esse object-code em vários mini object-codes que depois são linkados pra formar
uma única grande ROM. Esses object-codes podem ser organizados em pacotes pra
poderem ser reutilizados depois. O linker usa os cabeçalhos adicionados por um
compilador (ou pelo próprio programador) pra auxiliar na montagem do programa.
Esses cabeçalhos contém informações de *simbolos*, e esses simbolos são usados
pra ligar as referencias a memória a outra.
Com C, os object-codes tem seus simbolos exportados como qualquer coisa que não
seja `static`. Se uma região de memória ou função não for `static`, ele vai ser
exportado no object-code.
Em C e assembly, você pode declarar que certos simbolos virão de fora da source
code usando o `extern`. O `extern` acaba sendo uma ferramenta extremamente
importante quando você vê o programa final como uma grande ROM, pois isso
facilita e muito a manutenção, a geração de código e também a organização do
código em pacotes.
## O que é uma linguagem?
Dado essa informação, o que é uma linguagem? Simplesmente notação. Lembre-se, o
foco principal é o object-code, a linguagem é só uma ferramenta de notação para
se construir esse object-code com os simbolos necessários pra montar o nosso
programa. Você pode usar C, C++, assembly, Ada, Carbon, qualquer coisa.
Inclusive, eu até recomendo você fazer mini-programas que gerem código a partir
de uma notação que seja melhor pra certas situações. Por exemplo, um python que
lê alguma source em YAML, e exporta um código C com uma tabela de ponteiro de
funções pra ser usada por um outro object-code.
## Rust se esqueceu de que a linguagem é só uma ferramenta de notação
Rust surgiu de uma necessidade de segurança, principalmente de devs de
navegadores, pra se fazer um código seguro, e isso é: sem problemas relacionados
a memória, race conditions e afins, e muito do que o Rust tem acaba servindo
como uma bicicleta com rodinhas pra se fazer em C ou C++, mesmo eu falando dos
problemas do Rust eu acho que você deveria aprender Rust mesmo que seja só pra
aprender as tecnicas de segurança que Rust adota. Porém Rust acabou sofrendo do
mesmo problema de "feature-creep" do C++ e, da mesma forma que C++, acabou se
perdendo no foco, e você percebe que o Rust se perdeu no foco ao observar uma
feature do Rust: `unsafe`.
O `unsafe` poderia ser facilmente substituído apenas por um `extern`. Na verdade
toda a syntax do `unsafe` poderia ser jogada no lixo e o Rust ser só uma notação
segura pra uma unidade de compilação que ele está trabalhando, e partes mais
inseguras da codebase poderiam ser feita em linguagens mais maduras, que seriam
linkadas pra formar a grande ROM que estavamos falando anteriormente.
Mas o time do Rust decidiu ir por um caminho como se todo o Rust fosse
responsável pela segurança de um programa, e isso torna a linguagem Rust
extremamente invasiva e a migração para essa linguagem um tanto confusa, e é
isso que o pessoal de baixo-nível acaba reclamando mais do Rust. E também o Rust
acabou tomando certas decisões quanto a ABI que, ao meu ver, parecem muito mais
uma grande pirraça mais do que qualquer outra coisa, que vem muito do pessoal
mais de programação funcional que tenta forçar tudo a ser funcional. Não me
levem a mal também, eu gosto da ideia da programação funcional, mas ao meu ver
existem certos espaços que parecem forçados (por exemplo, programação funcional
é boa pra composibilidade, mas são *péssimos* pra assincronicidade). Por fim,
acaba sendo aquele grande dilema que ocorre em campos acadêmicos desde os anos
80~90 acabando por invadir um espaço que o pragmatismo deveria ser o rei.
Por isso, por mais que eu estude Rust de vez em quando pra me atualizar quanto
as tecnicas de segurança, eu nunca vou usar Rust. Eu não vou usar uma linguagem
que me obrigue a tratar todo o projeto como se fosse um projeto "do Rust" ou
feito "em Rust", por mais que sim, meus programas seriam mais seguros se fossem
feitos em Rust. Talvez se alguém fizer uma versão do Rust que seja mais
pragmática e minimalista eu use, mas essa versão atual do Rust, não, e eu só
queria expressar esse meu desgosto pelo estado do Rust e expor os meus pontos
contra o Rust. Não odeio a ideia do que o Rust esteja tentando fazer, mas não
gosto de _como_ o Rust vem feito.
|