Clause
← All documentation

Differences from Erlang/OTP

Observable behavior where Clause knowingly differs from the pinned OTP 29 (maint-29, see otp-reference.md). Each entry links to the contract that owns it. Remove an entry once the difference is fixed. Features not implemented yet (reported as notimpl) are not listed here; see features.md and the plan.

Maps

DifferenceOTPClauseOwner
Map generator order (K := V <- M)Flat maps (up to 32 keys) iterate in key order, but atom keys in atom-table order, which varies between VM runs; larger maps in hash orderAlways canonical key order (term order)patterns
bad_generators payload of a map generator in a zip groupIts iterator: {K, V, Next} chain ending in none, in OTP's orderThe same chain, built in canonical key orderpatterns
maps:iterator/1,2, maps:next/1, erts_internal:map_next/3, the order maps funs run in (intersect_with/3, merge_with/3, ...), proplists:get_keys/1, sets of version 2 (to_list/1, fold/3)Internal order (atom-table order for atom keys, hash order above 32 keys); an iterator is a position or a {K, V, Next} chainCanonical key order; an iterator continues over a key listbuiltins
Map printing (erlang:display/1, ~w, ~p)Internal layout order (atom-table order for atom keys, hash order above 32 keys)Map-key order, as OTP's ~kwterms
Order of digraph:vertices/1, edges/1, source_vertices/1, sink_vertices/1 and of digraph_utils' orderings and components where they start from those listsThe vertex and edge tables' hash orderClause's hash order (ETS); paths and neighbour lists follow edge insertion in bothbuiltins
Order of maps:keys/1, values/1, to_list/1, fold/3, of the members json:encode/1 writes, of the fields erl_parse:abstract/1,2 and erl_syntax:abstract/1 give a map, and of graph's vertex lists and traversalsThe map's internal order (atom-table order for atom keys, hash order above 32 keys)Key orderlibrary
Native record printing (erlang:display/1)Fields in atom-table index orderDefinition order, as ~wnative records
== between native records whose fields differ only as integer/floatThe compiler may fold it to =:= (false)Numeric comparison (true)native records
External native record construction of a module that is not loadedFails until the defining module is loadedEvery batch module is loaded at startup; a module outside the batch always failsnative records
Local fun printing (#Fun<M.Index.Uniq>)Index from the compiler's lambda numbering, Uniq a hash of the module codeIndex of the module's local funs in source order, Uniq always 0funs
Order of two local funs of one moduleBy OTP's indexBy source-order index, so funs of different functions can order differentlyfuns
Anonymous fun names in stack traces (-f/1-fun-N-)N from the compiler's numberingN counts the funs of f/1 in source orderfuns
An anonymous fun in a record field defaultEach construction site expands its own copy: funs from two sites are unequalOne fun for the default: funs from any construction site are equalfuns
Captured value order of funs created inside comprehensionsFree variables of the comprehension's generated functionDefinition order in the enclosing function; visible only when comparing two such funsfuns

Pids, references and processes

DifferenceOTPClauseOwner
timer one-shot and interval timers other than sends to local pidsRun by the timer_server process, started under kernel_sup on first use; exit_after/2,3 signals come from itNo timer server: each timer is a process of its own, which sends exit_after's signal; cancel/1 returns before that process has seen the cancellationbuiltins
Pid numbersThe first user process is about <0.80.0>; numbers are reused after the pid table wrapsThe first process is <0.1.0>; numbers come from one sequence and are never reusedterms
Code after spawn(Fun) of a fun of another arityThe compiler's type analysis may treat the code after the call as unreachable and drop it, so the caller returns the pid at onceThe caller goes on; only the new process fails with {badarity, {Fun, []}}processes
Stack of a function_clause raised by a lists builtin (lists:sublist/2, lists:max/1, ...)The top frame is the Erlang function, often an internal helper (lists:sublist_2/2), with its argumentsThe caller is on top: builtins push no framebuiltins
Last bit of math results (math:erfc(1), ...)The C library OTP was built withThe C library Clause programs link (Windows: 0.15729920705028513 for erfc(1), OTP 0.1572992070502851)builtins
binary:compile_pattern/1 result{bm, Ref} or {ac, Ref} with an opaque reference{bm, [Pattern]} or {ac, Patterns}builtins
binary:referenced_byte_size/1 of a sub-binaryThe size of the binary it refers intoIts own sizebuiltins
Memory of replaced or erased persistent termsReclaimed by a literal-area collector process that has every process copy the value out, in the backgroundEach process copies it out at its next slice (parked ones at once, by the put/erase), then the area is freed; no collector processruntime
Persistent terms sent in messagesStay shared, like literals: the receiver's heap does not growCopied into the receiver's heap like any other termruntime
persistent_term:info/0 and get/0Include the terms OTP's kernel and stdlib store at boot (26 on OTP 29)Only the program's own termsbuiltins
code:is_loaded/1, code:which/1, code:all_loaded/0 of a compiled moduleThe .beam file it was loaded frompreloaded: every module is linked into the executablebuiltins
priority option of send/3, link/2, exit/3, exit_signal/3Priority messages and signals overtake ordinary onesAccepted; delivered as ordinary messages and signalsprocesses
spawn/2,4, spawn_link/2,4, spawn_monitor/2,4 naming another nodeA warning report ** Can not start ... on Node ** is loggedNothing is printed; the useless pid still ends with noconnectionprocesses
system_flag/2 flags other than backtrace_depth and min_heap_size (fullsweep_after, schedulers_online, multi_scheduling, max_heap_size, ...)Change the emulatorChecked and read back without an effect; system_logger starts as undefined (no logger process); cpu_topology, erts_alloc, scheduler_bind_type are badargbuiltins
A suspended process's timers (receive ... after, send_after/3 and start_timer/3 to its pid)Suspended with the process until it is resumed (OTP 28, 29)Keep running: a timeout that expires while suspended is taken once the process resumes; a timer message waits in its mailboxprocesses
process_display/2 outputOTP's stack dump with addresses and stack slotsOne Module:Function/Arity per frameprocesses
process_flag(save_calls, N)Saves the last N calls for process_info(Pid, last_calls)Kept and read back; no calls are savedprocesses
adler32_combine/3, crc32_combine/3 with a second size above 2^31 - 1 on WindowsCombinedbadarg (zlib's z_off_t is 32 bits there)builtins
init:get_arguments/0, init:get_argument/1The emulator's flags: root, bindir, progname, home and every -Flag of the command lineOnly home; an executable has no emulator flagsbuiltins
init:script_name/0, init:script_id/0The boot script's path and {"Erlang/OTP", "29"}The executable's absolute path and {"Clause", "29"}builtins
init:get_status/0, init:ensure_loaded/1 in the entry{starting, started} and code loading while escript, -s or -eval code runs during boot; {started, started} and not_allowed once startedAlways the started answersbuiltins
init:stop/0,1, init:reboot/0Return ok; init then takes the applications down and halts, while the caller keeps runningHalt at once; the call never returnsbuiltins
init:get_argument(home) on Windows without HOMEDRIVE/HOMEPATHThe shell's profile folderUSERPROFILE, normally the same folderbuiltins
erlang:halt(Slogan), init:stop(Slogan)Prints the slogan, writes erl_crash.dump in the current directory and says so on stderr; exit status 1Prints the slogan on stderr, writes no crash dump; exit status 1executables
init:restart/0,1, init:boot/1, init:make_permanent/2Restart the system in the same node, boot it, or set the boot script of the next restartRefused: notsup error, {error, notsup} from make_permanent/2builtins
atomics:new/2 arityAny positive integer the allocator can serve; a huge one ends the node with a crash dump1 to 2^27, else badargbuiltins
counters with write_concurrencyPer-scheduler counters summed on read; info/1 memory grows with the scheduler countOne atomics array; info/1 memory is the array'sbuiltins
erts_internal:term_type/1The internal representation: flatmap or hashmap, heap_binary, refc_binary or sub_binary, ...Every map flatmap, every bitstring sub_binarybuiltins
erl_prim_loader:get_path/0The boot code path["."] until set_path/1ports
file:read_link_info/1,2 of a symbolic link on WindowsThe link's own reparse-point dataThe target's size and times with type symlinkports
inet:gethostbyname/1,2The resolver's canonical name and aliases (inet_res, hosts file, native)The name asked and no aliases; addresses from the system resolverports
socket moduleThe socket NIF APIMissing: a reference is a compile-time error; use gen_tcp, gen_udp, inetlibrary
net:getifaddrs/1,2 with a namespace, inet:getifaddrs([{netns, _}])net calls itself without end (OTP 29); inet reads the namespace on Linux{error, enotsup}builtins
zlib output listsOne binary per internal chunk, nested where a stream ended and restartedOne binary per call, [] when there is none; the bytes are OTP'sbuiltins
zlib:safeInflate/2 and long zlib callsReturn after a bounded amount of output ({continue, Output}) and yieldInflate all queued input in one call ({finished, Output}); a long call holds its scheduler threadbuiltins
Long re matchesre:run/3 and the global loop yield after a bounded amount of workOne match runs to its end and holds its scheduler thread; a global run yields between matches onlybuiltins
re:compile/2 with export, re:import/1An exported pattern {re_exported_pattern, ...} that another node importsexport is badarg; import/1 raises {not_implemented, import, 1}builtins
re argument errorsbadarg raised from re:run/3 (or replace, split) with the caller's arguments and error_infobadarg raised from the re helper that rejected the argument, with that helper's argumentsbuiltins
code:is_sticky/1true for modules of kernel, stdlib and compiler, and for the modules of directories code:stick_dir/1 namedAlways false; stick_dir/1 only checks that the directory can be listedbuiltins
code:root_dir/0 and the initial code pathOTP's installation directory; the path holds its lib/*/ebin directoriesThe executable's directory; the path holds the ebin directories of lib/ beside it and of ERL_LIBS, then "."builtins
code:load_file/1, load_abs/1, load_binary/3, atomic_load/1, prepare_loading/1 with valid object codeLoad the module{error, badfile}: every module is linked into the executable (D01)builtins
code:coverage_support/0 and the coverage functionstrue with the JIT; coverage modes and countersfalse; the others raise badarg, as OTP does without coverage supportbuiltins
code:get_doc/1 of a module the program hasIts EEP 48 documentation chunk{error, missing}: executables embed no documentationbuiltins
Formatting a large term (io:format/1,2)Runs in Erlang code (io_lib) and the group leader, so the process can be preempted while formattingRuns to completion in one builtin call; other processes waitbuiltins
process_flag/2 flagstrap_exit, priority, message_queue_data, min_heap_size and othersOnly trap_exit and min_heap_size; every other flag raises badargprocesses
Error report order of processes crashing at the same timeLogger orderThe order their workers finish themprocesses
Exit signals (exit/2, exit_signal/2) to a process running on another schedulerQueued in its signal queue and handled later, while the sender goes onThe sender waits until the target's time slice ends, then acts at once; observable only as timing (messages are buffered and the sender goes on)processes
term_to_binary/1 of a local fun or a native recordEncoded (NEW_FUN_EXT, ...)error:notsup; fun M:F/A is encodedbuiltins
term_to_binary/1 of a map with more than 32 keysHash order unless deterministicAlways key order (deterministic's bytes)builtins
binary_to_term/1 of another node's pid, port or reference; option local of term_to_binary/2External identities; LOCAL_EXT encodingbadargbuiltins
Timer time limitDepends on the native time unit (about 2^49.7 ms on Windows)Relative time 0..2^49-1 ms on every platformprocesses
unique_integer/0,1 without positiveMay be negativeAlways positive and increasingbuiltins
process_info/2 items current_function, initial_call, current_stacktrace, ...Reportederror:{notsup, Item}; process_info/1 omits themprocesses
process_info/2 reductions; statistics/1 reductions, garbage_collection, ioCounted0 (not kept)builtins
garbage_collect/0,1,2Collects before returningCollects at the target's next safepointprocesses
erlang:system_info(machine), and so epp's ?MACHINE and the macro it names"BEAM", 'BEAM'"Clause", 'Clause'builtins
erlang:system_info(schedulers) of a program started with an affinity mask (start /affinity, taskset)One scheduler per logical processor of the host (32 under a 7-CPU mask), schedulers_online one per CPU of the maskBoth one per CPU of the mask: Clause starts only the online workersprocesses
spawn_opt/2..5 tuning options (priority, min_heap_size, ...)AppliedChecked and accepted, not appliedprocesses
hibernate/3Discards the stack; the process ends when M:F returnsKeeps the stack; M:F's result returns to the caller of hibernate/3processes
monitor(port, Item, Options) with optionsAcceptedbadargprocesses
spawn_request_abandon/1true while the reply is pendingAlways false: the reply is sent before spawn_request returnsprocesses
math:log2/1 last bit (Windows)OTP's Windows build divides log(X) by log(2) (math:log2(1.0e308) is 1023.1538532253077)The C library's log2 (1023.1538532253076)builtins
phash/2, phash2/1,2 of pids, ports, references, funs and native recordsHashes of OTP's process, port and reference numbers, a fun's index and unique number, a record definition's hashHashes of Clause's numbers, a fun's module, arity or index and captures, a record's field values; every other term hashes to OTP's valuebuiltins
dict:fold/3, map/2, filter/2 with a non-funfunction_clause, or {badfun, F} when the first bucket OTP visits holds an entryfunction_clausebuiltins
erlang:is_builtin/3 of lists:reverse/2 and other C-implemented library functionstruefalse: only the runtime's builtins and apply/2,3funs
fun_info/1,2 pid, uniq, new_uniq of a local funCreator pid, compiler checksumsundefined, MD5 of the module namefuns
md5_init/0 contextOTP's 92-byte stateClause's 96-byte state; digests are equalbuiltins
erlang:delete_module/1 of a loaded moduleMakes its code old (true)error:notsup: linked code staysbuiltins
erlang:prepare_loading/2Prepares a valid BEAM binaryAlways {error, badfile}builtins
erlang:pre_loaded/0The preloaded boot modulesEvery module of the programbuiltins
list_to_pid/1 of a number never issuedReturns a pid termbadarg: only pids this program created are admittedterms
list_to_port/1 of a number never issuedReturns a port termbadarg: only ports this program opened are admittedports
port_info/1,2 valuesid is a table index; memory, queue_size, locking describe the driverid is the port number; memory and queue_size are 0; locking is port_levelports
Writing a file opened only for reading{error, eacces} on Windows, {error, ebadf} elsewhere{error, ebadf} everywhereports
win32reg's portThe linked-in registry__drv__ port ({spawn, "registry__drv__ rw"}), answering commands with port messagesThe clause_registry driver ({spawn_driver, ...}), answering the same replies through port_control/3; port_info/2 names it clause_registryports
argparse's program name without the progname optionThe emulator's progname (erl)The executable's name without its extension (init has no progname)library
Top stack frame of an argparse command validation errorThe validating function (argparse:validate_command/2, validate_option/2, a fun inside them) with [Entity]argparse:validate/2 with [Entity]builtins
escript:script_name/0The escript's path, the first plain argumentThe executable's path: a Clause program is its own scriptlibrary
escript:extract/2 with compile_sourceThe source compiled to a beam{error, {compile, ...}}: Clause programs have no compilerlibrary
erl_abstract_code:debug_info(core_v1, ...) (beam_lib's Core Erlang)Core Erlang from the compiler{error, failed_conversion}: Clause programs have no compilerlibrary
zstd:get_frame_header/1 of a truncated frame headerThe fields of uninitialized memoryThe fields zero ('ZSTD_frame', sizes 0)builtins
file:open/2 with raw or ramA #file_descriptor{} record served in the caller (is_pid/1 false); io requests on it fail; a ram file has no read_line/1 (undef) and a closed one answers {error, einval}A file server pid like other files; positioned I/O and sendfile/5 answer as for OTP's raw files; a ram file answers read_line/1 and I/O requests with {error, enotsup}, and {error, terminated} once closedports
file:truncate/1 on a file opened only for readingThe platform's error (eacces on Windows, einval elsewhere)The C runtime's error for the descriptor (ebadf or einval); the server stops as OTP'sports
Files opened or set to {utf16, _} or {utf32, _}Lines and characters decoded in the encodingLines end at a byte 10 before they are decodedports
io_ansi sequences on Linux and macOSFrom the terminfo database of TERM where it has the capability (setaf, sgr0, ...); tput/1,2, tigetnum/1, tigetflag/1, tinfo/0 read itThe built-in ANSI sequences OTP uses without terminfo (as OTP on Windows); tigetnum/1, tigetflag/1, tinfo/0 answer {error, enotsup}, tput/1,2 raise {enotsup, Capability}; enabled/0,1 wants a TERM other than dumblibrary
io_ansi:scan/1 and tput/1,2 on WindowsFail with try_clause on terminfo's {error, enotsup}scan/1 matches the built-in sequences; tput/1,2 raise {enotsup, Capability}library
socket on Windows: recvmsg, sendmsg, sendfile, sendmmsg, recvmmsgRaise notsupWork as on Linux and macOSlibrary
socket on Windows: a datagram longer than recv's length{error, {completion_status, ...more_data...}}The datagram truncated, as elsewherelibrary
socket on Linux and macOS: ioctl/2,3,4, getopt_native/3, setopt_native/3, open/1,2 of a descriptor, local domain, SCTPSupportedRefused as OTP on Windows refuses them ({error, {invalid, ...}}, notsup); local is {error, eafnosupport}library
socket:info/1, i/0,1,2The NIF's counters and states, fd the descriptorCounters of the calls made, states as the module tracks them; Fd is the port numberlibrary
inet_res answersgethostbyname, getbyname and gethostbyaddr answers are cached by TTL in inet_db; a cached lookup can list addresses in another orderNothing is cached: every lookup asks the name serverslibrary
Resolver configuration on Linux and macOSinet_db also reads host.conf/nsswitch.conf and inetrc files, follows changes to resolv.conf, and on Linux derives the domain from the host nameresolv.conf's nameserver, domain and search lines and the hosts file, read oncelibrary
os:set_signal(Signal, handle) (Linux, macOS)The signal is sent to erl_signal_server, whose default handler stops the system on sigterm, halts on sigusr1 and sigquitNo erl_signal_server: sigterm and sigquit exit with status 0, sigusr1 with status 1, others are dropped; without set_signal, SIGTERM keeps the system's default actionports
Empty arguments of {spawn_executable, F} on WindowsDropped from the command linePassed as ""ports
{exit_status, S} and eof of a spawned programUnspecified order, exit_status may arrive before the last dataAfter all data, before eofports
Busy portsA port with too much queued output suspends senders, socket ports included; port_command/3 force works on drivers that allow itOnly ports of spawned programs become busy; fd and socket ports never do; force raises notsup on every driverports
{active, N} of socketsAn integer N counts messages before {tcp_passive, S}exit(badarg); only true, false and onceports
Socket options of inet_drv itself (header, deliver, exit_on_close, send_timeout, send_timeout_close, delay_send, watermarks, packet_size, show_econnreset, buffer, read_packets, recvtos, recvttl, line_delimiter)AppliedKept and reported by getopts/2 with OTP's defaults, not applied; the system's options (nodelay, keepalive, linger, buffers, tos, multicast, ...) are appliedports
Other socket options ({packet, line | http | ...}, {raw, ...}, bind_to_device, netns)Workexit(badarg) when opening, {error, einval} from setopts/2 and getopts/2ports
inet:getopts(S, [multicast_if]) on WindowsReads uninitialized memory for a TCP socket, and the any address after a UDP socket set oneThe system's value; the any address when the socket has noneports
port_info(Socket, input | output), inet:info/1's input and outputThe bytes of the driver commands and replies0: socket traffic is counted by inet:getstat/1,2 onlyports
Socket error reasonsEvery POSIX reason the system reportsThe common ones (econnrefused, eaddrinuse, econnreset, etimedout, ...); others are eioports
Port input while the connected process holds 1,024 messages and can runKeeps reading and deliveringStops delivering until the process's time slice ends; past 64 KiB held, stops reading, so the writing program blocksports
gen_tcp:close/1 with queued outputWaits up to the linger/send_timeout setting for the output to leaveReturns at once; the I/O thread sends the queued output, then closesports
monitor/2 typesprocess, port, time_offsetprocess and port; time_offset raises badarg (no time offset changes)processes
exit/2, exit_signal/2 to a referenceSends to the process alias, if the reference is an active oneNothing: exit signals never go to aliasesprocesses
Reference numbersMix a scheduler identifier and per-scheduler counters (#Ref<0.178111994.4235460610.214105>)One program-wide counter (#Ref<0.0.0.1>), so references order by creationterms

Errors, stack traces and reports

DifferenceOTPClauseOwner
Stack trace locations[{file, F}, {line, L}], error_info for error/3Always []; no error_info, so erl_error:format_exception/3,4 shows no locations or *** argument lines for themABI
erlang:raise/3 with {Fun, Args} stack entriesAcceptedRejectedABI
function_clause top frameArgument listArityABI
undef top frame of a M:F(A1, ..., An) call{M, F, [A1, ..., An], []}{M, F, N, []}: the arity in place of the arguments (apply/3 and fun calls show the arguments)funs
Dynamic call of an export an executable cannot reach (its module named only through a stack trace, an exception or a message from outside the program)Calls itundef, unless built with --keep-exports; function_exported/3 and module_info(exports) still list itexecutables
Failing BIF/operator framesPresent ({erlang, '+', Args, ...})Absent; nothing below the entry functionABI
Atom table full (list_to_atom/1)The emulator aborts (no more index entries in atom_tab) and writes a crash dumpclau: runtime failure: entry call failed: resource_limit, exit 70builtins
list_to_integer/1,2 with characters above 255Its first digits use only each character's low byte ([16#131] is 1)badargbuiltins
erlang:function_exported/3 of a BIFTrue for every BIF of the emulatorTrue only for the builtins this runtime providesbuiltins
Error reports of crashed processesSent to the logger, written later by its default handler (on standard output under erl, often lost when an escript halts first)Written on stderr when the process ends, before any later output; not a logger event, so handlers and filters do not see itprocesses
Calls to functions that never returnCompiled as tail calls (caller missing from the trace)Ordinary calls (caller present)ABI
Exceptions inside a known anonymous fun at -O2 (F = fun ... end, F(X), lists:map(fun ... end, L) and the other list loops, maps:fold(fun ... end, A, M))Frames of the fun (-f/1-fun-0-) and of the lists and maps helpers (lists:map_1/2)The fun's body runs inlined in the caller: those frames are missing, and an improper list tail of map/2, foldl/3, all/2, any/2, flatmap/2, filtermap/2, partition/2, search/2, takewhile/2, dropwhile/2, splitwith/2, zipwith/3, zipwith3/4 (and lists of different lengths) raises function_clause with the caller on topfuns
Exceptions inside a small local function (leaf) at -O2, called locally or as ?MODULE:f() (badarith, badmatch, a failing builtin)The function's frame is in the stack traceThe leaf's body, and those of the leaves it calls, run inlined in the caller: their frames are missing and the caller is on top; function_clause (no clause matching) still has the function on topspecialization
Profiles and the Erlang stack of inlined code at -O2 (known funs, small local functions)Every call counts for the called function (eprof, tprof), and its frame is on the stackInlined code runs in its caller's frame: its entries and time are the caller's, and debuggers see it only as an inlined native frameprofiling
Host memory exhaustedThe emulator reports that it cannot allocate memory, writes a crash dump and stopsclau: runtime failure: entry call failed: out_of_memory, exit 70, no dumpruntime heap
Storage of maps above 32 keysAn on-heap HAMT of 16-way hashed nodesAn on-heap B+ tree of up to 16 entries per node in key order; heap sizes of large maps differ from OTP'sruntime heap
Process memory capmax_heap_size (in words, heap and stack) kills the process with reason killed and logs an error report--max-heap / --max-stack (bytes) and the runtime-wide --max-memory fail the requesting process as resource_limit: clau: runtime failure: entry call failed: resource_limit, exit 70runtime heap
Program argumentsescript passes every argument to main/1; emulator flags (+t) come from %%! or ERL_FLAGSLeading runtime options (--max-atoms, --max-heap, --max-stack, --max-memory, --min-heap-size, --args-file, --) are taken out first; CLAUSE_FLAGS holds the same optionsexecutables
Uncaught exception in an ordinary entry moduleescript exits 127Exits 1 with one uncaught exception <class>: <reason> line (escript sources keep 127)executables
Compiler diagnosticserl_lint wording (variable 'X' is unbound) and warningsOwn wording (unbound variable X); OTP lint warnings are mostly not emitted (also native record warnings: unknown fields in access, update and patterns, own-module qualified construction without values, unused or header-defined records; a later pattern matching a name exported from a branch)semantic
Behaviour module with a hand-written behaviour_info/1Calls it while compiling users and warns about missing, ill-defined or deprecated callbacksNot evaluated: its users' callbacks are not checkedsemantic
Behaviour modules neither in the batch nor in the Clause library (application, ...)Loaded from the code path; their callbacks are checkedbehaviour M undefined warningsemantic
Default logger handlerlogger_std_h writing asynchronously with overload protection (sync, drop and flush modes, burst limits, overload kill)Also on standard_io (standard_error with CLAUSE_LOGGER_TYPE=standard_error), but each event is written before the logging call returns; the overload options are checked and kept without an effectlibrary
Handler processes of logger_std_hSupervised by logger_sup, restarted after overload_kill_restart_afterLinked to the logger server; a handler whose process dies is removedlibrary
net_adm:names/0,1Asks epmd: {ok, Names} when an epmd runs on the host{error, address}: Clause has no epmd clientlibrary
net_kernel:start/1,2Starts distribution, or OTP's error when it cannotNot available (not_implemented)library
Tracing: erlang:trace/3, trace_pattern/2,3, trace_info/2, trace_delivered/1, system_monitor/0,1,2, system_profile/0,2, seq_trace/2, seq_trace_info/1, seq_trace_print/1,2, dt_*, the trace module, erl_tracer:enabled/3, trace/5Traceerror:notsupbuiltins
seq_trace tokensPassed on with messages; serial numbers count them; a system tracer receives trace messagesKept per process only: not passed on, serials stay as set, no trace messageslibrary
pg scopes and globalReplicate between connected nodes; pg monitors nodes through net_kernelOne node, no peers or node monitoringlibrary
Application resources.app files found on the code path when loaded; sys.config, -config and -App Key Value arguments set environmentsCompiled into the executable from the build's resource files; changing them needs a rebuild; no configuration files or argumentslibrary
kernel and stdlib applicationsStarted by boot; kernel has a master and a top supervisorLoaded and running without masters: get_supervisor(kernel) is undefined, info/0 lists them as running undefinedlibrary
application:ensure_all_started/3 with concurrentStarts independent applications at once; the list follows completion orderStarts them one after another, dependencies firstlibrary
application:takeover/2Waits for the distributed application controllerExits noproc (no dist_ac), as load/2 with nodes does on bothlibrary
I/O requests to an application masterRelayed to the group leader the application started underAnswered on standard I/Olibrary
erlang:process_flag(error_handler, Module)The runtime calls Module:undefined_function/3 and undefined_lambda/3 for undefined callsbadarg; process_info/2 always reports error_handler, and undefined calls raise undef directly, except calls into interpreted modules, which enter error_handler:undefined_function/3library
Crash report details (proc_lib)erl_error's exception text with extended error information; neighbours with current_function, initial_call and current_stacktrace; real reductionsThe exception's class line and stack frames without extended error information; neighbours without those items; reductions 0library
client_info of gen_server, gen_statem and gen_fsm error reportsThe calling process's current_stacktrace[]: Clause keeps no current stack of another processlibrary
-behaviour with a value that is not an atomWarning prints the term with ~w (behaviour [115,116,114] undefined)Prints the attribute's source text (behaviour "str" undefined); the error is the samesemantic
module_info(md5) and the vsn OTP derives from itMD5 of the compiled BEAM codeMD5 of the module's printed source; the derived vsn integer differs accordinglysemantic
module_info(compile)version of OTP's compiler application, options given to itClause's version; options always []semantic
module_info(functions)Also lists the functions OTP generates for funs ('-f/0-fun-0-'/0)Source functions and the predefined ones onlysemantic
-nominal in module_info(attributes)Kept as {nominal,[{Name,AbstractType,Params}]} with abstract formatLeft outsemantic
A function of a Clause library module that Clause has not implemented (an erlang BIF, lists:rmerge/2, ...)RunsCompiles; raises error({not_implemented, F, A}) when called, with M:F/A on top of the stack (statuses)library, builtins
Import of a module outside the batchCompiles; the call raises undef at run time if the module is missingunknown module M compile error when the import is called (unused imports need no module)semantic
import directive overrides auto-imported BIF warningFor every auto-imported BIF of erl_internal:bif/2Only for the auto-imported BIFs Clause implementssemantic
Attributes after the first function definition other than records, types, -spec, -doc, -moduledoc and -dialyzer (-export, -import, -compile, -behaviour, user attributes)Error attribute A after function definitionsAccepted (only -export_record is rejected)semantic

Language edge cases

DifferenceOTPClauseOwner
Integer segment wider than the integer limit, value past it (<<V:4194241>> of all ones)The x86 JIT matches with an invalid term; using it crashes the VMNo matchterms
Zip group whose relaxed and strict generators share a variableSkip test keeps strict-pattern variables in the relaxed patternsA rejected step is skipped whenever the strict patterns match on their ownpatterns
Calling an external fun, M:F(Args) or apply/3 of a module outside the programLoads the module from the code path, undef when absentundef; library modules join the program only when it names them with a literal atomfuns, library
Files without #! given as escriptsescript file.erl skips the first lineCompiled as ordinary modulesexecutables
Precompiled beam and archive escriptsRunNot supportedexecutables
Module name of an escript without -module<name>__escript plus a timestamp/unique suffix<name>__escript, deterministicexecutables
include_lib of an application found in several <app>-<version> directoriesThe code path holds one version (boot picks the highest); no diagnosticThe highest version below each searched directory, with one warning per run listing thempreprocessor
A -spec whose types share no value with the inferred result, entry domain or a call's argumentsCompiles; Dialyzer may warnA contradicted argument entry domain is a compile error naming the declared and inferred types; a contradicted result or call is a warning, and the inferred types are usedsemantic analysis

ETS

DifferenceOTPClauseOwner
Order of first/1, next/2, tab2list/1, foldl/3 and i/1 over set, bag and duplicate_bag tables, and what slot/2 numbersLinear hash slots visited lock by lock; the order changes as the table growsParts, then buckets in order, then keys in insertion order within a bucket; a slot is one bucketruntime
ets:all/0Includes the tables of OTP's kernel and stdlib; order of the scheduler repliesOnly the program's tables, in no particular orderbuiltins
info/2 memoryAllocated words of the table and its objectsStored object words plus Clause's own overheadsbuiltins
{write_concurrency, auto}Lock count adapts to contention (64 to 8192)64 fixed parts, as for true; stats reports 64 locksruntime
compressedStores elements other than the key in external formatAccepted and reported; objects are stored as they arebuiltins
info/2 stats of an ordered_set with write_concurrency; data; binaryCA tree {RouteNodes, BaseNodes, MaxDepth}; prints the table; the table's off-heap binariesfalse; true without printing; []builtins
badarg of an ets builtinCarries error_info with a cause (id, access, type, ...)Plain badargbuiltins
Order of select, match and match_object results of hash tables, and which results each chunk of select/3 holdsResults of each walk step consed, newest first; linear hash slotsWalk order of Clause's parts and buckets; each chunk the first Limit results gatheredbuiltins
select_delete/2, select_replace/2 over a whole tableTrap every 1000 objects (the table fixed meanwhile)Run in one piece, each part under its lockruntime
Match specifications naming a variable numbered 25 or aboveRenumbers every '$N' atom of the specification, even inside {const, ...} (so {const, '$30'} gives '$0')Variables keep their numbers; {const, '$30'} gives '$30'runtime
Match specification guards and bodies nested deeper than 1000 levelsCompile until the C stack runs low (system_limit)system_limitruntime
Trace actions in erlang:match_spec_test/3: enable_trace, disable_trace, trace with valid flagsChange the caller's trace flags (29.1.1 crashes without a tracer)true after checking the flags (and that a pid argument is alive); nothing changesbuiltins
ets:tab2file/2,3 and file2tab/1,2Through a disk_log process named by a fresh referenceWritten and read directly with filebuiltins
{process_dump} and {current_stacktrace} in erlang:match_spec_test/3The process's dump text; its stack trace<<>>; []builtins

dets

DifferenceOTPClauseOwner
Requests waiting together at a tableLookups, inserts and deletes queued at once share one cache update; lookups are answered before the writes are made; a fixed table makes some writers sleep 1 msEach request in turn, in arrival orderbuiltins
Long dets operations (repairs, init_table/2,3, compactions, flushes of a large cache)Erlang code, preempted by reductionsOne builtin call each; the table's worker runs nothing else meanwhilebuiltins
dets processesThe dets server and dets_sup under kernel_safe_sup, tables under dets_supA dets server started on first use, unsupervised; table processes linked to itbuiltins
dets:all/0 orderThe registry's ETS orderClause's ETS order (ETS)builtins
ReportsA repair is logged at info level; verbose/0,1 and DETS_DEBUG log more; an internal failure is {dets_bug, ...}Nothing is loggedbuiltins

io

DifferenceOTPClauseOwner
~p, ~w and io_lib writers of containers nested more than 256 deepPrintedsystem_limitio
io_lib:print/4 with a column or line length that is not an integerDepends on the term: printed (guards fail quietly), function_clause or badarithbadarith for any container termio_lib
Negative precision or pad count (~.*c with -1)Loops foreverbadargio

erl_scan

DifferenceOTPClauseOwner
Location of a tokens/3,4 continuation (continuation_location/1, undocumented)Where the scanner stopped, inside the unfinished tokenThe start of the unfinished token, which is scanned again with the next characterserl_scan
{compiler_internal, [ssa_checks]}Scans %ssa% check comments into tokensIgnored: they stay commentserl_scan
A based float (16#1.8#e1, base other than 10) whose digits exceed 53 bitsThe mantissa converted as ERTS converts big integersAccumulated in a double; the last bit may differerl_scan
A list element that is not a character inside a string, quoted atom or escapefunction_clause, case_clause or if_clause, depending on the clausefunction_clauseerl_scan

erl_parse

DifferenceOTPClauseOwner
'%ssa%' tokens (SSA check clauses of OTP's compiler tests)Parsed into ssa_check_when clausesA syntax error; erl_scan never produces the tokenerl_parse

erl_eval

DifferenceOTPClauseOwner
Stack trace of an error the evaluator raises ({badmatch, V}, undef of a local call, ...)The evaluating process's current stack (process_info/2 current_stacktrace)The stack at the evaluator's throw that collects it, in Clause's frameserl_eval

Module interpreter

Compared with the same module compiled by compile:forms/2 and loaded by code:load_binary/3.

DifferenceOTPClauseOwner
Stack trace an interpreted try or catch sees for an exception raised in its own body or by compiled code it callsThe module's frameserl_eval's and the interpreter's frames; an exception that left an interpreted function call has the interpreted frameslibrary
Frames of interpreted funs (-f/1-fun-N-) and of compiled code between interpreted calls (lists:map/2 calling an interpreted fun, compiled code calling back into an interpreted module)PresentAbsent: the interpreted functions' frames, then the compiled frames below the outermost interpreted call; a fun's lines count for the interpreted function it runs underlibrary
fun F/A of an interpreted function, and interpreted funsFuns of the moduleerl_eval funs; at most 20 arguments ({argument_limit, _})library
module_info(compile), module_info(md5)The compiler's version, options and source; the object code's MD5[{options, []}, {source, File}] after clause_interp:load/1, the image's compile information after code:load_binary/3; the MD5 of the formslibrary
erlang:get_module_info/1,2 and erlang:hibernate/3 of an interpreted module from compiled codeWorkbadarg, undef (M:module_info/0,1 works)builtins
-on_load of an interpreted moduleRuns when the module loadsNot runlibrary
Process dictionary of a process running interpreted codeOnly the program's keysAlso '$clause_interp_stack' (the interpreted frames) and '$clause_interp_raised'library

compile

compile:file/1,2 and compile:forms/1,2 compared with OTP's compile.

DifferenceOTPClauseOwner
The binary of forms/1,2 and of file/1,2 with binary, and the .beam file writtenBEAM codeAn interpreter image: an AtU8 chunk with only the module, Attr, CInf, Dbgi, extra chunks and the forms (ClFm); no Code, ImpT, ExpT, LocT, Line, Type or Docs chunk. Only Clause programs with clause_interp load itlibrary
The vsn attribute of a compiled module and beam_lib:md5/1MD5 of the BEAM codeMD5 of the forms (as module_info(md5))library
Warnings of the passes after erl_lint (v3_core, sys_core_fold, ...: no clause will ever match, the result of an expression is ignored, ...)ReportedNot reported: only erl_lint's, epp's and parse transforms'library
Options of the Core Erlang, SSA and assembly passes (to_core, dssa, 'S', to_asm, core_transform, ...), from_core, from_asm, makedep, dcover, encrypted debug_infoListings, Core or assembly input, dependencies, encrypted debug informationError {none, compile, {clause_unsupported, Option}}: "the Option option needs OTP's code generator, which Clause does not have"library
-moduledoc/-doc attributesSaved in the Docs chunk unless no_docsRemoved; no Docs chunklibrary
code:load_binary/3 of a binary of another module{error, badfile} and an error report on the logger{error, badfile}, no reportlibrary
code:load_binary/3 in a program without compile or clause_interpLoads BEAM code{error, badfile}, as for any binary (D01)library

erl_syntax

DifferenceOTPClauseOwner
An error raised while revert_forms/1 reverts a form (a malformed node)Caught and raised again as exit({Reason, Stacktrace})Raised as the error it issyntax_tools
concrete/1 of a binary tree whose field is not a literal{badarg, Node} with the field's tree{badarg, Form} with the field reverted to its erl_parse formsyntax_tools

erl_prettypr

DifferenceOTPClauseOwner
The text of an error or warning marker {Line, Module, Descriptor} whose module the program does not linkModule:format_error/1 loads the module and formats the descriptorThe marker's term, as when format_error/1 failssyntax_tools

erl_syntax_lib

DifferenceOTPClauseOwner
limit/2,3 with a depth that is not an integerCompares the depth with integers in term order (an atom depth keeps a leaf)badargsyntax_tools

prettypr

DifferenceOTPClauseOwner
A paper or ribbon width that is not an integer (prettypr:format(D, wide))Used only when compared or subtracted: a short document lays out, a longer one raises badarith or compares by term orderfunction_clausebuiltins
prettypr:sep([]) or par([]) laid outcase_clausefunction_clausebuiltins

erl_lint

DifferenceOTPClauseOwner
Behaviours named by -behaviourAny module on the code path answers behaviour_info/1Only modules linked into the program answer; another is undefined_behaviourerl_lint
Order of several errors found in one map fold (singleton type variables of one type, specs without a function, callback checks)The map's internal order (atoms by index)Term ordererl_lint
erlang:is_builtin/3 for -deprecated, -removed and -unsafe entries that are not exportedOTP's BIF tableThe runtime's builtins, which include native library functionserl_lint
is_guard_expr/1 of a record constructionRaises case_clauseAnswers whether the fields are guard expressionserl_lint

epp

DifferenceOTPClauseOwner
-include_lib("App/...") not on the include pathFound in code:lib_dir(App), which knows OTP's applicationsFound in code:lib_dir(App) of Clause's code path, which has no OTP applications unless they are added to itlibrary

erl_pp

DifferenceOTPClauseOwner
Shape of the characters erl_pp returnsDeep character listsOne flat character list; flattened output is equalbuiltins

qlc

DifferenceOTPClauseOwner
Stack trace of an exception raised in a cursor process, as next_answers/1,2 re-raises itThe cursor's stack trace followed by the owner's process_info(self(), current_stacktrace)Followed by the stack trace of an exception caught in the owner (Clause has no current_stacktrace item)qlc
qlc:q/1,2 in erl_eval, ets:table/1,2, dets:table/1,2 in a program that never names qlcqlc is always loadedundef for qlc: these reach it by a runtime name, so only programs naming qlc (any module including qlc.hrl does) link itlibrary
Annotation numbers in the code of compiled queries (info/2 with {format, abstract_code})OTP's transform numbers annotations around every integer of the module, the characters of qlc.hrl's path in its file attribute includedThe same transform, but Clause's qlc.hrl has another path, so numbers past the first query may differ; the code is otherwise equalqlc

qlc_pt

DifferenceOTPClauseOwner
Messages of qlc_pt:parse_transform/2 at run timeFrom compile:noenv_forms/2 (strong_validation): erl_lint plus the compiler's core passes, such as sys_core_fold warningsFrom erl_lint only, as OTP's qlc_pt does when the compiler is not availableqlc_pt

Interactive shell

DifferenceOTPClauseOwner
Line editing in a terminaledlin: cursor keys, line history, search, tab completion over edlin_expand, the ..> multiline promptThe terminal's own (cooked) line editing; lines are read as the terminal delivers them, with the same prompt for each further line of a command, as OTP does for piped inputlibrary
Job controlCtrl+G opens the JCL menu (new, connected, interrupted and killed shells)None; the banner and the slow-command hint still name Ctrl+G as OTP prints themlibrary
exit(). when the shell reads piped inputA new shell starts and reads nothing moreA new shell starts and reads the rest of the inputlibrary
Programs that start the shell without --shellEvery module of the code path is callableOnly the modules the program links; without --keep-exports dynamic calls reach only exports the program can reachlibrary
Records of compiled modules (rr(Module), shell_default and user_default at start)Read from the module's debug information or source{error, nofile}: linked code keeps no abstract code; rr/1,2,3 of source and .beam files read themlibrary
save_module/1Writes the module and compiles it with c:c/1Writes the module only (no compiler)library
edlin_expand:expand/1,2 inside a call or a record field valueFunction heads and argument types from the function's specification (lists:seq(From, To)), atoms and types the specification allowsMod:Fun/Arity heads of the exported arities, no type suggestions: linked code keeps no specificationslibrary
edlin_expand:expand/1,2 of functions and modulesFunctions grouped by the documentation's groups; modules of the code pathOne Functions group (no documentation); the program's moduleslibrary
c:i/0,1, c:ni/0, c:regs/0 columnsEach process's initial call and current functionproc_lib's initial call or undefined; the current function undefined (no current_function item)library

Random numbers

DifferenceOTPClauseOwner
Strip heights of rand's normal zigguratTabled constantsComputed to the nearest double from the ziggurat's constants; a height may differ in its last bit, which changes a slow-path accept only for a draw within that bit of the bound (odds near 2^-53 per slow-path draw). Strip widths and bounds are observed from OTP and equalbuiltins

crypto

DifferenceOTPClauseOwner
Order of crypto:supports(ciphers)The NIF's table sorted by atom index, which varies between VM runs, then the aliasesOTP's table order, then the aliasesbuiltins
{File, Line} of crypto's {badarg | notsup | error, {File, Line}, Description} errorsOTP's C source file and line ({"hash.c", 111})Clause's C++ source file and line ({"hash.cpp", 63}); the class and description are OTP'sbuiltins
link_type of crypto:info/0How OTP linked libcrypto (usually dynamic)Always static, also when an installed shared libcrypto is linkedOpenSSL
Long pbkdf2_hmac/5 computations (more than 100 iterations or 64 bytes)Run on a dirty CPU schedulerRun on the calling process's scheduler worker, which runs no other process meanwhilebuiltins
modules of the crypto application[crypto, crypto_ec_curves][crypto]library
Long crypto_one_time/4,5 and crypto_one_time_aead/4,6,7 texts (more than 20000 bytes)Run on a dirty CPU schedulerRun on the calling process's scheduler worker, which runs no other process meanwhilebuiltins
The fips_mode application variable of cryptoRead when the crypto module loads: true enables FIPS modeNot read (Clause has no on_load and programs have no sys.config): use crypto:enable_fips_mode/1, or clau --fipscrypto
crypto:info_fips/0 without a loadable FIPS providernot_enabled when OTP was built with FIPS support, not_supported otherwisenot_supportedcrypto
When the crypto application is loadedWhen the crypto module loads (its on_load)When a crypto_cache, crypto_aes or crypto_prng1 generator first reads rand_cache_sizelibrary
RSA key generation (crypto:generate_key(rsa, ...)) and SLH-DSA signaturesRun on a dirty CPU schedulerRun on the calling process's scheduler worker, which runs no other process meanwhilebuiltins
The rsa_sslv23_padding option of crypto:public_encrypt/4 and its siblingsAccepted when OTP is built against an OpenSSL that has SSLv23 padding (1.1, 3.x)"Bad padding type in option rsa_padding", as OTP built against OpenSSL 4builtins
crypto:ec_curve/1 of a curve the linked libcrypto lacks (an OpenSSL built without binary curves)The parameters from crypto_ec_curveserror:function_clause, as for an unknown curve: the parameters come from the libcrypto's built-in curvesbuiltins
beam_lib decryption of debug information in a program that does not call cryptocrypto is always presentkey_missing_or_invalid unless the program links crypto (--with-crypto), since beam_lib calls it dynamicallylibrary

ASN.1

DifferenceOTPClauseOwner
Stack in {error, {asn1, {Reason, Stack}}}Frames of the generated enc_*/dec_* functions and asn1rtt_*Frames of Module:encode/2 or decode/2 and the codec builtinasn1
Functions of a generated moduleAlso exports enc_Type/1,2, dec_Type/1,2 and the other per-type functions asn1ct generatesOnly encode/2, decode/2, info/0, the option functions and the value functionsasn1
A CHOICE whose body starts with ... (no root alternatives)asn1ct reports a syntax errorAcceptedasn1
Value macros and functions that name another value inside an open type (PKCS-1's mgf1SHA1, rSASSA-PSS-Default-Identifier)asn1ct leaves {'Externalvaluereference', Line, Module, Name} in place of the valueThe referenced valueasn1
A runtime error (not an ASN.1 one) while public_key decodes or encodes an extension valueRaised as it happens, mostly error class, from the generated dec_ext-*/enc_ext-* functionexit({error, {asn1, Reason}}): the value goes through the generated module's decode/2 or encode/2, which wraps every failurepublic_key
The default Diffie-Hellman groups of public_key:dh_gex_group/4The groups OTP generated (lib/public_key/priv/moduli), 60–81 per sizeEight per size from OpenSSH's moduli file; same sizes (2047 to 8191)public_key
Frames of a public_key exceptionpublic_key, pubkey_pem, pubkey_pbe, pubkey_cert_records, pubkey_cert, pubkey_crl, pubkey_policy_tree, pubkey_ocsp, pubkey_os_cacerts, pubkey_sshpublic_key, clause_public_key_codec, clause_public_key_keys, clause_public_key_cert, clause_public_key_path, clause_public_key_crl, clause_public_key_ocsp, clause_public_key_test_data and clause_public_key_cacertspublic_key

Unsupported features

DifferenceOTPClauseOwner
erl_ddll:loaded_drivers/0The linked-in drivers (tcp_inet, udp_inet, ram_file_drv, ...){ok, []}: Clause's ports are not driverslibrary
erl_ddll:load/2, load_driver/2, try_load/3Load a driver, or {error, {open_error, Code}} for a missing file{error, no_ddll_available}, OTP's answer without DDLL functionalitylibrary
erl_ddll:format_error({open_error, Code}) for an operating system code (Code =< -10)The system's message ("The specified module could not be found.")"Unspecified error"library
erl_epmd:names/1, port_please/2,3Ask a running epmd daemonAnswer as without one ({error, address}, noport or the configured listen port); start_link/0 is declinedlibrary
erl_boot_serverA working boot server for diskless nodesEvery function is declinedlibrary
peer:start/1, start_link/1 with an alternative connectionStart a peer node over standard I/O or TCPerror:notsup after OTP's option checks: Clause cannot run another nodelibrary
pool's expected loadsA statistic collector per node updates them every few secondsOnly get_node/0 and pspawn/3 raise themlibrary

ssl

DifferenceOTPClauseOwner
Atoms ssl:str_to_suite/1 takes as existingAny atom of the VM's atom tableThe program's atoms and the parts of the suite tablessl
ssl:str_to_suite/1 of chardata that is not a flat string (["TLS_AES_128_GCM_SHA256"])string functions may parse it{error, {not_recognized, Name}}ssl
The ssl application's start module and supervision treessl_app; ssl_sup with ssl_admin_sup, ssl_pem_cache, ssl_manager, tls_sup and dtls_supclause_ssl_app; ssl_sup with ssl_pem_cache, ssl_manager (the client session cache only), tls_connection_sup, whose children are the connection processes, and ssl_unknown_listener once an upgraded server socket needs it; listening sockets' session caches are not supervisedssl
Frames of an ssl exceptionssl, ssl_cipher, ssl_cipher_format, tls_v1, tls_record, dtls_recordssl and clause_ssl_algorithmsssl
Text of a {tls_alert, {Description, Text}} error and alert log entries`"TLS client: In state certify at ssl_handshake.erl:2304 generated CLIENT ALERT: Fatal - Unknown CA
"`: the state of OTP's state machine and a source location`"TLS client: In state certify generated CLIENT ALERT: Fatal - Unknown CA
": helloorcertifyduring the handshake,connection` after it, no locationssl
ssl connection processesA tls_dyn_connection_sup per connection with a receiver (gen_statem) and a sender process; the sslsocket record names both and an ETS tableOne clause_ssl_connection (gen_server) per connection; the record names it twice and no tablessl
ssl:connection_information/1The negotiated items and every ssl option of the connectionThe negotiated items (protocol, session_id, session_data, session_resumption, selected_cipher_suite, selected_group, sni_hostname) and the main options (verify, versions, ciphers, cacerts, depth, ...)ssl
session_data of ssl:connection_information/1,2term_to_binary/1 of OTP's internal #session{} recordlibssl's DER encoding of the session; each implementation reads only its ownssl
Ticket maps of {session_tickets, manual} ({ssl, session_ticket, Ticket})cipher_suite, sni, psk, timestamp and ticket (OTP's internal #new_session_ticket{} record)cipher_suite, sni, timestamp and ticket (libssl's DER session); each implementation reads only its ownssl
{use_ticket, Tickets} with several ticketsOffers all of themOffers the first whose suite the client offers (libssl resumes one session)ssl
A stateless server's anti_replayBloom filters (with false positives); a replayed ClientHello gets a full handshakeExact sets of PSK binders per window, no false positives; a replayed ClientHello resumes without its early datassl
Client early_data larger than the ticket's limitOTP 29.1.1 sends it and the server fails with unexpected_messageNot sent; the owner gets {early_data, rejected}ssl
A stateful server given a used ticket with early dataOTP 29.1.1 fails the handshake with unexpected_messageA full handshake; the early data is rejectedssl
ECDHE_PSK suites with AES-GCM or AES-CCM (RFC 8442)NegotiatedNever negotiated: libssl lacks themssl
SRP suites and srp_identityNegotiated over crypto's SRPNever negotiated: libssl's SRP interface is deprecatedssl
A PSK client whose key differs from the server'sThe server's bad_record_mac alert is not read; the client sees {error, closed}The client reads the alert: {error, {tls_alert, {bad_record_mac, _}}}ssl
ssl_crl_cache with {http, Timeout}Fetches missing CRLs from their http distribution points with httpcNever fetches: Clause has no inets; the hidden helpers is_internal_ip/1, validate_host/4 and is_allowed/3 raise not_implementedssl
log_level debug and info of ssl connectionsProtocol traces of records and handshake messagesNone; alerts are logged as OTP'sssl
key_update_at after a KeyUpdate the peer asked forThe answering KeyUpdate starts a new count of bytesThe count goes on until the connection's own KeyUpdatessl
How often sni_fun is called for a name it answers with undefinedTwice in a handshakeOncessl
Groups, signature algorithms and early data of sni_hosts and sni_fun optionsAppliedThe listening socket's stay (libssl keeps them per connection)ssl
Sessions given to ssl_session_cache_api modulesOTP's internal #session{} recordsMaps (session_id, data, cipher_suite, own_certificate, peer_certificate, sni, time_stamp, ...); both are opaque to the modulessl
Emulated options (active, mode, packet, header) set on a listening ssl socketKept by its option tracker for the next accepted connectionsIgnored: accepted connections take the options listen/2 was givenssl
A server linked with libssl older than 4.1 that verifies client certificatesRejects a chain during the handshake with the chosen alertVerifies after libssl's handshake; a rejection closes the connection without the alertssl
ssl:handshake/3 with options on an accepted socket whose handshake pauses at the hello{ok, Extensions}, the extensions still OTP's internal records and no socket{ok, SslSocket, Extensions}, as documented and as handshake/1,2 return itssl
The hello messages an ssl connection sendsOTP's: its extensions, groups and key shareslibssl's: for example a ClientHello has renegotiation_info and no signature_algs_cert, so a peer paused at the hello sees other extensionsssl
Calls other than handshake_continue and handshake_cancel on a connection paused at the helloWait until the handshake goes on{error, closed}ssl
ssl:close/1 and close/2 with a timeoutAfter close_notify, shut the transport down for writing and wait up to 5 s (not the given timeout) for the peer to closeClose the transport right after close_notifyssl
A TLS 1.2 renegotiation the peer refuses (no_renegotiation)ssl:renegotiate/1 gives {error, renegotiation_rejected} and the connection goes onThe same result, but libssl then ends the connection with a handshake_failure alertssl
ssl:update_keys/2 on a TLS 1.2 connectionThe connection's sender process crashes (function_clause) and the caller exits{error, not_supported}, the connection goes onssl
ssl:export_key_materials/4,5 with a length of 0 or lessThe connection hangsA negative length is {error, bad_input} (TLS 1.3) or {error, badarg} (TLS 1.2); 0 gives libssl's exporter resultssl
master_secret of ssl:connection_information/2 on TLS 1.3The key schedule's master secretLeft out: libssl does not expose itssl
Items of a {keylog_hs, Fun} when a TLS 1.3 client fails before the server's Finished (a rejected server certificate)Both handshake traffic secretsOnly SERVER_HANDSHAKE_TRAFFIC_SECRET: libssl derives the client's own handshake secret after the server's Finishedssl
Key log lines of keylog and the keep_secrets funsDeep character lists (io_lib:format/2 results)Flat strings with the same charactersssl

Parse transforms

DifferenceOTPClauseOwner
Name in the file attribute of an included file (--print-abstr, transform input)The include directory joined to the name, as found (inc.hrl, /abs/dir/inc.hrl, ../inc/x.hrl)The path relative to the working directory when the file is under it, else the absolute pathtransforms
Line 0 annotations of imported forms (generated code, as from the qlc transform)A valid line: the code has no source lineThe code takes the place of the node imported before ittransforms
generated annotations of imported forms (.abstr inputs, transform output)erl_lint and the compiler skip some warnings for generated codeIgnored: the code is checked like sourcetransforms
{error, {Location, Module, Descriptor}} forms in .abstr inputsFormatted with Module:format_error/1The descriptor's term text; transform output is formatted by the loadertransforms
Preprocessor and parse problems a parse transform gets as formsepp's and erl_parse's descriptors, each in place of the form that failed{error, {Location, clause_source, Text}} with Clause's message, all before eoftransforms
Compile options a transform receiveserlc's full option list{features, _}, report_warnings, report_errors, {cwd, _}, {outdir, _} (the working directory), {i, _}, {d, ...} and {parse_transform, _}transforms