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

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.