Propiedad y seguridad de la memoria

seed utiliza propiedad, recursos de solo movimiento, léxico loans/provenance, capacidades estructurales, limpieza determinista, linear ty regiones. No tiene GC, sintaxis de por vida del verificador de préstamos ni desenredado de excepciones. Las reglas semánticas autorizadas están en seed/compiler/llvm/SEMANTIC_RULES.md; Los límites actuales se rastrean en Estado actual.

Copiar, mover, pedir prestado, clonar

Operación Significado
copiar el origen y el destino permanecen disponibles; sólo para valores con capacidad de copia
moverse transferencias de propiedad y el lugar de origen deja de estar disponible
pedir prestado una vista sin copia está vinculada a un almacenamiento de respaldo probado
clonar independiente explícita value/handle según capacidad estructural

Escalares y agregados que contienen solo copiar campos. string, bytes, shared_bytes, propietarios de usuarios-destructores, agregados de recursos y linear t obedecer a sus move/clone/cleanup capacidades.

shared_bytes no se puede copiar bit a bit: .clone() conserva explícitamente otro identificador sin copiar la carga útil. Se pueden asignar clonaciones de string/bytes de propiedad o agregados que los contengan. Los efectos y capacidades de asignación de clones sobreviven a la compilación .sdi sin fuente.

Lugares y propiedad parcial

El compilador rastrea locales, campos y campos anidados, índices de matriz fija conocidos, cargas útiles ADT activas, campos de unión sin formato, tuple/array/nominal agregados, instancias genéricas, option/result, valores de función, channels/tasks, alias, bloques, llamadas, devoluciones y uniones de flujo de control.

Un traslado parcial hace que el lugar trasladado no esté disponible e impide el uso total del propietario cuando se requiere integridad. Los campos restantes independientes siguen siendo utilizables cuando un destructor de usuario no requiere un propietario completo. Los movimientos de índice dinámico de elementos de recursos siguen siendo rechazados porque el conjunto de limpieza dependería del tiempo de ejecución.

limpieza

La limpieza se planifica a partir de los datos de propiedad de HIR escritos, se verifican por separado y se bajan a las salidas estructuradas normales. Los propietarios en vivo limpian exactamente una vez en el orden inverso de inicialización exitosa. La reasignación limpia al propietario vivo anterior antes de almacenar el reemplazo. Los bucles utilizan puntos fijos de flujo de datos en la entrada, los bordes posteriores, la interrupción, la continuación y el retorno.

El pánico, la trampa y el aborto terminan sin relajarse. No ejecutan limpieza léxica ni destructores de usuarios.

Destructores

fn type_name.drop() recibe el consumo implícito self. Debe ser único y devolver void. Llamar a value.drop() manualmente consume al propietario, lo que evita una segunda llamada automática. Los propietarios que regresan transfieren su obligación de limpieza a la persona que llama. Los valores globales Cleanup/resource se rechazan porque el desmontaje global no es un servicio de lenguaje implícito.

La limpieza de ADT se envía solo sobre la variante activa. Los sindicatos crudos requieren una disciplina insegura en el campo activo; Las alternativas etiquetadas seguras deben utilizar ADT o un contenedor auditado.

Propiedad de cierre

Un cierre simple |...| posee almacenamiento de captura de pila generado por el compilador. La inicialización de la captura sigue el primer orden de uso léxico: los valores con capacidad de copia se copian y otros valores propios se mueven. Las capturas son inmutables; una captura de recursos movidos hace que el cierre en sí sea de solo movimiento. El propietario coloca capturas en vivo exactamente una vez en orden de inicialización inverso.

Los cierres simples son reutilizables y no se escapan. No pueden capturar valores que no pueden permanecer almacenados de forma segura después de una llamada, incluidas vistas, capturas mutables, valores vinculados a regiones, raw/reference valores, format_args, o lugares ya movidos. No se pueden devolver, retener en un ámbito externo, enviar a una tarea ni pasar a través de un límite de puntero de función de plataforma.

box |...| asigna almacenamiento de captura explícitamente y devuelve result<box fn(...) -> t, alloc_error>. El propietario en caja se puede devolver o almacenar, pero sigue siendo de solo movimiento, no se puede clonar ni enviar. El error de asignación elimina las capturas transferidas una vez; La caída exitosa ejecuta el procesador de captura y libera el entorno una vez. Un cierre de caja asignado en region(...) no puede escapar de esa región.

Valores lineales

linear t conservas t's representación y agrega una obligación exactamente una vez. Se quita copy/clone/shared capacidad mientras conserva datos válidos de movimiento, préstamo, envío, sincronización y limpieza. La implementación propaga la obligación a través de alias, bloques, agregados, option/result, ADT, genéricos, canales, valores de funciones y llamadas indirectas, captura de tareas, parameters/returns y esquema-16 .sdi.

Se rechaza dejar un valor lineal activo al salir del alcance, consumirlo dos veces, clonarlo, descartarlo, sobrescribirlo o almacenarlo en un almacenamiento no lineal preexistente.

Texto, buffers y vistas

No existe una sintaxis de por vida. @borrow los métodos receptores crean préstamos léxicos compartidos; Las vistas devueltas permanecen vinculadas al receptor a través de .sdi resúmenes. @mut Los métodos del receptor crean un préstamo exclusivo con alcance de llamada y mutan el lugar de la persona que llama directamente. Se rechazan los receptores inmutables y las vistas en vivo superpuestas; La llamada no oculta ningún movimiento o clonación.

Regiones

fn work() -> result<i64, alloc_error> {
    region(4096) {
        // allocating operations use the active checked bump allocator
        result.ok(42)
    }
}

La capacidad se evalúa una vez, se verifica el desbordamiento de la asignación alineada y el agotamiento se devuelve como alloc_error por API falibles. Las regiones anidadas son LIFO. Los recursos del cuerpo se limpian antes de que se libere el almacenamiento de respaldo. Los propietarios, vistas y punteros seguros vinculados a una región no pueden escapar mediante resultados, retornos o asignaciones a un enlace externo.

El trabajo generado captura el contexto del asignador. Las tareas vinculadas a la región permanecen estructuradas y se unen antes de la limpieza de la región.

transferencia de tareas

spawn registros copy/move modo de captura. Mantener el valor original y el de una tarea requiere una clonación explícita. Cruzar el límite de una tarea requiere send; El acceso compartido también requiere sync. El estado global mutable no se puede capturar. Cada grupo de tareas drena recursos antes de que su propietario léxico limpie los recursos.

Límite inseguro

La asignación sin formato, el acceso al puntero, FFI, las llamadas al sistema, los atómicos, el acceso volátil, las conversiones de espacio de direcciones, el acceso a la unión sin formato y el ensamblaje sin formato requieren unsafe. El código inseguro no desactiva la propiedad de los valores seguros circundantes; asume obligaciones específicas que deberían ocultarse detrás de estrechos envoltorios seguros y auditados.

unsafe struct parámetros: un unsafe struct con un campo de puntero sin formato y @repr("null_niche") es un tipo de recurso que no se puede pasar por valor como parámetro de función. Pasarlo por valor mueve al propietario subyacente, lo que hace que no esté disponible para su uso posterior. Métodos con @mut El receptor requiere un lugar mutable y no se puede invocar con un valor movido. Para utilizar un tipo de este tipo a través de los límites de la función, inserte la lógica o devuelva el propietario junto con el resultado.

¿Qué versión cambia?

--release y --release-small optimizan la misma semántica segura. Los controles de límites, discriminación, procedencia, propiedad y limpieza permanecen a menos que se demuestre que son redundantes. No se implementa ningún perfil de versión no verificado.