Propriedade e segurança da memória
seed usa propriedade, recursos somente de movimentação, léxico loans/provenance, capacidades estruturais, limpeza determinística, linear te regiões. Não possui GC, sintaxe de vida útil do verificador de empréstimo ou desenrolamento de exceção. As regras semânticas autorizadas estão em seed/compiler/llvm/SEMANTIC_RULES.md; os limites atuais são rastreados em Status Atual.
Copiar, mover, emprestar, clonar
| Operação | Significado |
|---|---|
| copiar | a origem e o destino permanecem disponíveis; apenas para valores com capacidade de cópia |
| mover | transferências de propriedade e o local de origem fica indisponível |
| pedir emprestado | uma visão de cópia zero está vinculada ao armazenamento de apoio comprovado |
| clonar | independente explícito value/handle de acordo com a capacidade estrutural |
Escalares e agregados contendo apenas cópia de campos. string, bytes, shared_bytes, proprietários de destruidores de usuários, agregados de recursos e linear t obedecer aos seus move/clone/cleanup capacidades.
shared_bytes não pode ser copiado bit a bit: .clone() retém explicitamente outro identificador sem copiar a carga útil. A clonagem de string/bytes de propriedade ou agregados que os contenham pode ser alocada. Os efeitos e recursos de alocação de clones sobrevivem à compilação .sdi excluída da origem.
Lugares e propriedade parcial
O compilador rastreia locais, campos e campos aninhados, índices de matriz fixa conhecidos, cargas úteis ADT ativas, campos de união bruta, tuple/array/nominal agregados, instâncias genéricas, option/result, valores de função, channels/tasks, aliases, blocos, chamadas, retornos e junções de fluxo de controle.
Uma mudança parcial torna o local movido indisponível e impede o uso por todo o proprietário quando a integridade é necessária. Os campos restantes independentes permanecem utilizáveis quando um destruidor de usuário não requer um proprietário completo. As movimentações de índice dinâmico de elementos de recursos permanecem rejeitadas porque o conjunto de limpeza dependeria do tempo de execução.
Limpeza
A limpeza é planejada a partir de fatos de propriedade do HIR digitados, verificados separadamente e transferidos para saídas estruturadas normais. Os proprietários ativos limpam exatamente uma vez na ordem inversa de inicialização bem-sucedida. A reatribuição limpa o proprietário ativo anterior antes de armazenar a substituição. Os loops usam pontos fixos de fluxo de dados na entrada, nas bordas posteriores, na interrupção, na continuação e no retorno.
Pânico, armadilha e aborto terminam sem desenrolar. Eles não executam limpeza lexical ou destruidores de usuários.
Destruidores
fn type_name.drop() recebe consumo implícito de self. Deve ser exclusivo e retornar void. Chamar value.drop() consome manualmente o proprietário, evitando uma segunda chamada automática. Os proprietários devolvidos transferem sua obrigação de limpeza para o chamador. Os globais Cleanup/resource são rejeitados porque a desmontagem global não é um serviço de linguagem implícito.
A limpeza do ADT é despachada somente na variante ativa. Os sindicatos brutos exigem disciplina insegura no campo ativo; alternativas marcadas seguras devem usar ADTs ou um wrapper auditado.
Propriedade de fechamento
Um fechamento |...| simples possui armazenamento de captura de pilha gerado pelo compilador. A inicialização da captura segue a primeira ordem de uso léxico: os valores com capacidade de cópia são copiados e outros valores de propriedade são movidos. As capturas são imutáveis; uma captura de recurso movida torna o próprio fechamento apenas para movimentação. O proprietário descarta capturas ao vivo exatamente uma vez na ordem inversa de inicialização.
Os fechos simples são reutilizáveis e não escapam. Eles não podem capturar valores que não possam permanecer armazenados com segurança após uma chamada, incluindo visualizações, capturas mutáveis, valores vinculados à região, raw/reference valores, format_args, ou lugares já movidos. Eles não podem ser retornados, retidos em um escopo externo, enviados para uma tarefa ou passados através de um limite de ponteiro de função da plataforma.
box |...| aloca armazenamento de captura explicitamente e retorna result<box fn(...) -> t, alloc_error>. O proprietário da caixa pode ser devolvido ou armazenado, mas permanece apenas para movimentação, não clonável e não enviável. A falha na alocação descarta as capturas transferidas uma vez; O drop bem-sucedido executa a conversão de drop de captura e libera o ambiente uma vez. Um fechamento em caixa alocado em region(...) não pode escapar dessa região.
Valores lineares
linear t conservas trepresentação e adiciona uma obrigação exatamente uma vez. Ele remove copy/clone/shared capacidade enquanto retém fatos válidos de movimentação, empréstimo, envio, sincronização e limpeza. A implementação propaga a obrigação através de aliases, blocos, agregados, option/result, ADTs, genéricos, canais, valores de função e chamadas indiretas, captura de tarefas, parameters/returns e esquema-16 .sdi.
Deixar um valor linear ativo na saída do escopo, consumi-lo duas vezes, cloná-lo, descartá-lo, substituí-lo ou armazená-lo em um armazenamento não linear pré-existente é rejeitado.
Texto, buffers e visualizações
- o texto literal é estático emprestado
str; stringpertence a UTF-8 válido e se move;bytesé um proprietário binário mutável exclusivo e movimentos;shared_bytesé um identificador somente leitura compartilhado com clone explícito;- propriedade
stringtoma emprestado automaticamente comostrquando esperado; - derivado do proprietário
str,[]temut []tas vistas carregam a proveniência; - uma visualização ao vivo evita movimentação, substituição, liberação, realocação ou mutação do seu proprietário de apoio;
mut []t.split_at_mut(index)verificaindex <= len, não aloca nada e retorna duas visualizações lexicais exclusivas; As ligaçõesmatchpodem usarmut name;- o proprietário de apoio não pode ser lido, movido, redimensionado ou liberado enquanto o a tupla de partição está ativa; as partições aninhadas permanecem confinadas ao seu pai;
- retornar ou armazenar uma visualização é permitido somente quando seu static/input/receiver a procedência comprova vida útil suficiente;
- local/temporary-derived visões não podem escapar através de retornos, globais, contêineres, tarefas ou biblioteca dinâmica ABI.
Não há sintaxe vitalícia. @borrow métodos receptores criam empréstimos lexicais compartilhados; as visualizações retornadas permanecem vinculadas ao receptor por meio .sdi resumos. @mut os métodos do receptor criam um empréstimo exclusivo com escopo de chamada e alteram o local do chamador diretamente. Receptores imutáveis e visualizações ao vivo sobrepostas são rejeitados; nenhum movimento ou clone é ocultado pela chamada.
Regiões
fn work() -> result<i64, alloc_error> {
region(4096) {
// allocating operations use the active checked bump allocator
result.ok(42)
}
}
A capacidade é avaliada uma vez, a alocação alinhada é verificada pelo estouro e a exaustão é retornada como alloc_error por APIs falíveis. As regiões aninhadas são LIFO. Os recursos do corpo são limpos antes que o armazenamento de apoio seja liberado. Proprietários seguros, visualizações e ponteiros vinculados a uma região não podem escapar por meio de resultado, retorno ou atribuição a uma ligação externa.
O trabalho gerado captura o contexto do alocador. As tarefas vinculadas à região permanecem estruturadas e unidas antes da limpeza da região.
Transferência de tarefas
spawn registros copy/move modo de captura. Manter o valor original e um valor de tarefa requer um clone explícito. Cruzar um limite de tarefa requer send; o acesso compartilhado também requer sync. O estado global mutável não pode ser capturado. Cada grupo de tarefas é drenado antes que seu proprietário léxico limpe os recursos.
Limite inseguro
Alocação bruta, acesso a ponteiro, FFI, syscalls, atômicos, acesso volátil, conversões de espaço de endereço, acesso de união bruta e montagem bruta requerem unsafe. O código inseguro não desativa a propriedade dos valores seguros circundantes; ele assume obrigações específicas que devem ser escondidas atrás de invólucros seguros auditados e restritos.
unsafe struct parâmetros: um unsafe struct com um campo de ponteiro bruto e @repr("null_niche") é um tipo de recurso que não pode ser passado por valor como parâmetro de função. Passá-lo por valor move o proprietário subjacente, tornando-o indisponível para uso posterior. Métodos com @mut o receptor requer um local mutável e não pode ser chamado em um valor movido. Para usar esse tipo além dos limites da função, incorpore a lógica ou retorne o proprietário junto com o resultado.
Quais mudanças na versão
--release e --release-small otimizam a mesma semântica segura. As verificações de limites, discriminantes, procedência, propriedade e limpeza permanecem, a menos que se prove serem redundantes. Nenhum perfil de lançamento não verificado é implementado.