diff --git a/documentation/source/library-reference/language-extensions/inlining.rst b/documentation/source/library-reference/language-extensions/inlining.rst index 3e1ad4e7c3..a3c8c26caa 100644 --- a/documentation/source/library-reference/language-extensions/inlining.rst +++ b/documentation/source/library-reference/language-extensions/inlining.rst @@ -22,8 +22,10 @@ and have included those same adjectives in our language extension - ``inline`` Inline this item wherever the compiler can do so. In addition, ``define constant`` and ``define function`` permit the -adjective ``inline-only``, which forces every reference to the constant -or function to be inlined. +adjective ``inline-only``, which forces every reference to the +constant or function to be inlined. If a call can not be inlined +(because, for example, the argument types are not known with enough +specificity at compile time), then the compiler will issue a warning. .. note:: If you export from a library any variables created with ``may-inline``, ``inline``, or ``inline-only``, and then change the diff --git a/documentation/source/release-notes/2025.2.rst b/documentation/source/release-notes/2025.2.rst index 2c8dca172f..5beebdd99d 100644 --- a/documentation/source/release-notes/2025.2.rst +++ b/documentation/source/release-notes/2025.2.rst @@ -20,6 +20,11 @@ this release. Compiler ======== +* The compiler will now issue a warning when it is unable to inline a + call to a function or method marked as ``inline-only``, and signal + an error if it does not inline a function with raw argumennt or + return values. + Tools ===== diff --git a/sources/corba/orb/protocols/corba/typecode.dylan b/sources/corba/orb/protocols/corba/typecode.dylan index 18b5431e82..064e0d8399 100644 --- a/sources/corba/orb/protocols/corba/typecode.dylan +++ b/sources/corba/orb/protocols/corba/typecode.dylan @@ -53,13 +53,13 @@ define method object-typecode (object :: CORBA/) corba/$TypeCode-typecode; end method; -define inline-only function CORBA/TCKind/as-symbol (integer :: ) +define inline function CORBA/TCKind/as-symbol (integer :: ) => (s :: ) let typecode = class-typecode(CORBA/); typecode-members(typecode)[integer]; end function; -define inline-only function CORBA/TCKind/as-integer (symbol :: ) +define inline function CORBA/TCKind/as-integer (symbol :: ) => (i :: ) let typecode = class-typecode(CORBA/); typecode-symbol-index(typecode)[symbol]; diff --git a/sources/corba/scepter/console/parse-arguments.dylan b/sources/corba/scepter/console/parse-arguments.dylan index 55a64023dd..e8de58729d 100644 --- a/sources/corba/scepter/console/parse-arguments.dylan +++ b/sources/corba/scepter/console/parse-arguments.dylan @@ -53,7 +53,7 @@ define method canonicalize-arguments (arguments :: ) => (canonicalized-arguments :: ) let canonicalized-arguments = make(); let skip? = #f; - for (argument in arguments) + for (argument :: in arguments) if (skip? & keyword-argument?(argument)) skip? := #f; end if; diff --git a/sources/dfmc/modeling/machine-word-primitives-support.dylan b/sources/dfmc/modeling/machine-word-primitives-support.dylan index 2ab19e7d5a..93d8fea09b 100644 --- a/sources/dfmc/modeling/machine-word-primitives-support.dylan +++ b/sources/dfmc/modeling/machine-word-primitives-support.dylan @@ -108,7 +108,7 @@ end function extract-mw-operand-signed; /// Identical to make-raw-literal but checks that the value will actually /// fit into a on the target system for use by folders for /// primitives which are supposed to signal overflow. -define inline-only function make-raw-literal-with-overflow (object :: ) +define inline function make-raw-literal-with-overflow (object :: ) => (literal :: <&raw-machine-word>) if (instance?(object, )) make-raw-literal(object) diff --git a/sources/dfmc/modeling/primitive-macros.dylan b/sources/dfmc/modeling/primitive-macros.dylan index b14027e450..a191119d0d 100644 --- a/sources/dfmc/modeling/primitive-macros.dylan +++ b/sources/dfmc/modeling/primitive-macros.dylan @@ -153,6 +153,8 @@ override-parameters: { \#rest ?:name } => { #rest ?name } { ?variable-name, ... } => { ?variable-name, ... } variable-name: + { ?:name :: } + => { ?name :: <&raw-machine-word> } { ?:name :: ?:expression ?ignore:* } => { ?name } end macro; diff --git a/sources/dfmc/optimization/check.dylan b/sources/dfmc/optimization/check.dylan index 1280bd03ab..b5c66fd3fe 100644 --- a/sources/dfmc/optimization/check.dylan +++ b/sources/dfmc/optimization/check.dylan @@ -10,11 +10,20 @@ define program-warning slot condition-inline-only-function, required-init-keyword: inline-only-function:; format-string - "Failed to inline call to the inline-only function %s - making a " + "Failed to inline call to inline-only %s - making a " "local copy to call out of line"; format-arguments inline-only-function; end program-warning; +define program-error + slot condition-raw-value-function, + required-init-keyword: raw-value-function:; + format-string + "Calls to %s with raw argument or return values must be inlined, " + "but could not be"; + format-arguments raw-value-function; +end program-error; + define method check-optimized-computations (o :: <&lambda>) let checker = if (lambda-initializer?(o)) rcurry(check-optimized-reference, #t); @@ -58,7 +67,16 @@ end method; define method check-optimized-reference (c :: , ref :: , f :: <&function>, check-forward-refs? :: ) => () - if (model-compile-stage-only?(f) | inlined-inline-only-function?(f)) + if (raw-value-function?(f)) + note(, + source-location: dfm-source-location(c), + context-id: dfm-context-id(c), + raw-value-function: f); + elseif (model-compile-stage-only?(f) | inlined-inline-only-function?(f)) + note(, + source-location: dfm-source-location(c), + context-id: dfm-context-id(c), + inline-only-function: f); let copy = find-inline-copy(current-compilation-record(), f); reference-value(ref) := copy end; @@ -74,9 +92,17 @@ end method; define method check-optimized-reference (c :: , ref :: , e :: <&cache-header-engine-node>, check-forward-refs? :: ) => () - // format-out(">>> check-optimized-reference CHEN (%=) %= %= %=\n", object-class(c), c, ref, e); let f :: <&generic-function> = ^cache-header-engine-node-parent(e); - if (model-compile-stage-only?(f) | inlined-inline-only-function?(f)) + if (raw-value-function?(f)) + note(, + source-location: dfm-source-location(c), + context-id: dfm-context-id(c), + raw-value-function: f); + elseif (model-compile-stage-only?(f) | inlined-inline-only-function?(f)) + note(, + source-location: dfm-source-location(c), + context-id: dfm-context-id(c), + inline-only-function: f); let copy = find-inline-copy(current-compilation-record(), f); ^cache-header-engine-node-parent(e) := copy; end; @@ -124,6 +150,13 @@ define method generators-through-merges end method; */ +define function raw-value-function? + (f :: <&function>) => (well? :: ) + let sig = ^function-signature(f); + any?(raw-type?, sig.^signature-required) + | any?(raw-type?, sig.^signature-values) +end function; + // An inlined inline-only function is one that's called from some function // that is itself declared inline and so is a copy that has ended up // inlined elsewhere. In that case, we have to copy again. diff --git a/sources/duim/win32/wgadgets.dylan b/sources/duim/win32/wgadgets.dylan index 207935c1c7..42b688be2d 100644 --- a/sources/duim/win32/wgadgets.dylan +++ b/sources/duim/win32/wgadgets.dylan @@ -1793,7 +1793,7 @@ end method handle-scrolling; /// General collection gadget handling define class - () + (, ) end class ; define sealed domain gadget-selection-mode (); diff --git a/sources/dylan/float.dylan b/sources/dylan/float.dylan index 616f1162ea..60934525cd 100644 --- a/sources/dylan/float.dylan +++ b/sources/dylan/float.dylan @@ -152,13 +152,13 @@ define sealed inline method as (class == , x :: ) (primitive-double-float-as-single(primitive-double-float-as-raw(x))) end method as; -define inline-only function decode-single-float (x :: ) +define inline function decode-single-float (x :: ) => (decoded :: ) primitive-wrap-machine-word (primitive-cast-single-float-as-machine-word(primitive-single-float-as-raw(x))) end function decode-single-float; -define inline-only function encode-single-float (x :: ) +define inline function encode-single-float (x :: ) => (encoded :: ) primitive-raw-as-single-float (primitive-cast-machine-word-as-single-float(primitive-unwrap-machine-word(x))) @@ -277,14 +277,14 @@ define sealed inline method as (class == , x :: ) (primitive-single-float-as-double(primitive-single-float-as-raw(x))) end method as; -define inline-only function decode-double-float (x :: ) +define inline function decode-double-float (x :: ) => (low :: , high :: ) let (low :: , high :: ) = primitive-cast-double-float-as-machine-words(primitive-double-float-as-raw(x)); values(primitive-wrap-machine-word(low), primitive-wrap-machine-word(high)) end function decode-double-float; -define inline-only function encode-double-float +define inline function encode-double-float (low :: , high :: ) => (encoded :: ) primitive-raw-as-double-float (primitive-cast-machine-words-as-double-float(primitive-unwrap-machine-word(low), diff --git a/sources/io/streams/typed-stream.dylan b/sources/io/streams/typed-stream.dylan index 7a6131a251..07ae28ead9 100644 --- a/sources/io/streams/typed-stream.dylan +++ b/sources/io/streams/typed-stream.dylan @@ -22,16 +22,25 @@ define function byte-to-byte (byte :: ) => (byte :: ) byte end function byte-to-byte; +define function typed-tsm + (s :: , ss :: , d :: , ds :: , n :: ) + => () + copy-bytes(d, ds, s, ss, n); +end; + +define function typed-fsm + (s :: , ss :: , d :: , ds :: , n :: ) + => () + copy-bytes(d, ds, s, ss, n) +end; define open abstract class () // Assume that slot sequence-type /* ---*** :: subclass() */ = ; slot to-element-mapper :: = byte-to-byte-char; slot from-element-mapper :: = byte-char-to-byte; - constant slot to-sequence-mapper :: = - method (s, ss, d, ds, n) => () copy-bytes(d, ds, s, ss, n) end; - constant slot from-sequence-mapper :: = - method (s, ss, d, ds, n) => () copy-bytes(d, ds, s, ss, n) end; + constant slot to-sequence-mapper :: = typed-tsm; + constant slot from-sequence-mapper :: = typed-fsm; end class ; define open abstract class () diff --git a/sources/network/unix-sockets/bsd-address-data.dylan b/sources/network/unix-sockets/bsd-address-data.dylan index 019bb4cb28..f0e539da5a 100644 --- a/sources/network/unix-sockets/bsd-address-data.dylan +++ b/sources/network/unix-sockets/bsd-address-data.dylan @@ -63,25 +63,25 @@ define constant $INADDR-NONE = as(, #xffffffff); define constant = ; define constant = ; -define inline-only C-function ntohl +define inline C-function ntohl parameter netlong :: ; result val :: ; c-name: "ntohl"; end C-function; -define inline-only C-function ntohs +define inline C-function ntohs parameter netshort :: ; result val :: ; c-name: "ntohs"; end C-function; -define inline-only C-function htonl +define inline C-function htonl parameter hostlong :: ; result val :: ; c-name: "htonl"; end C-function; -define inline-only C-function htons +define inline C-function htons parameter hostshort :: ; result val :: ; c-name: "htons"; diff --git a/sources/network/unix-sockets/linux-address-data.dylan b/sources/network/unix-sockets/linux-address-data.dylan index 15880bb02f..55bd9365ea 100644 --- a/sources/network/unix-sockets/linux-address-data.dylan +++ b/sources/network/unix-sockets/linux-address-data.dylan @@ -74,25 +74,25 @@ define constant $INADDR-NONE = as(, #xffffffff); define constant = ; define constant = ; -define inline-only C-function ntohl +define inline C-function ntohl parameter netlong :: ; result val :: ; c-name: "ntohl"; end C-function; -define inline-only C-function ntohs +define inline C-function ntohs parameter netshort :: ; result val :: ; c-name: "ntohs"; end C-function; -define inline-only C-function htonl +define inline C-function htonl parameter hostlong :: ; result val :: ; c-name: "htonl"; end C-function; -define inline-only C-function htons +define inline C-function htons parameter hostshort :: ; result val :: ; c-name: "htons"; diff --git a/sources/network/unix-sockets/sockets-extras.dylan b/sources/network/unix-sockets/sockets-extras.dylan index d9d449fe1f..0f7d30b4db 100644 --- a/sources/network/unix-sockets/sockets-extras.dylan +++ b/sources/network/unix-sockets/sockets-extras.dylan @@ -15,7 +15,7 @@ define C-struct c-name: "timeval"; end; -define inline-only C-function unix-recv-buffer +define inline C-function unix-recv-buffer parameter socket :: ; parameter buffer :: ; parameter length :: ; @@ -24,7 +24,7 @@ define inline-only C-function unix-recv-buffer c-name: "recv"; end C-function; -define inline-only C-function unix-send-buffer +define inline C-function unix-send-buffer parameter socket :: ; parameter buffer :: ; parameter length :: ; @@ -33,7 +33,7 @@ define inline-only C-function unix-send-buffer c-name: "send"; end C-function; -define inline-only C-function unix-recv-buffer-from +define inline C-function unix-recv-buffer-from parameter socket :: ; parameter buffer :: ; parameter length :: ; @@ -44,7 +44,7 @@ define inline-only C-function unix-recv-buffer-from c-name: "recvfrom"; end C-function; -define inline-only C-function unix-send-buffer-to +define inline C-function unix-send-buffer-to parameter socket :: ; parameter message :: ; parameter length :: ; diff --git a/sources/network/unix-sockets/sockets-interfaces.dylan b/sources/network/unix-sockets/sockets-interfaces.dylan index 60fb8ee3b5..6a9276224a 100644 --- a/sources/network/unix-sockets/sockets-interfaces.dylan +++ b/sources/network/unix-sockets/sockets-interfaces.dylan @@ -15,7 +15,7 @@ define inline-only C-function ioctl c-name: "ioctl"; end C-function; -define inline-only C-function accept +define inline C-function accept parameter socket :: ; parameter address :: ; parameter address-len :: ; @@ -23,7 +23,7 @@ define inline-only C-function accept c-name: "accept"; end C-function; -define inline-only C-function bind +define inline C-function bind parameter socket :: ; parameter address :: ; parameter address-len :: ; @@ -32,13 +32,13 @@ define inline-only C-function bind end C-function; // TODO: Shared: close -define inline-only C-function close +define inline C-function close parameter socket :: ; result val :: ; c-name: "close"; end C-function; -define inline-only C-function connect +define inline C-function connect parameter socket :: ; parameter address :: ; parameter address-len :: ; @@ -51,7 +51,7 @@ end C-function; // Shared: fsetpos // Shared: ftell -define inline-only C-function getpeername +define inline C-function getpeername parameter socket :: ; parameter address :: ; parameter address-len :: ; @@ -59,7 +59,7 @@ define inline-only C-function getpeername c-name: "getpeername"; end C-function; -define inline-only C-function getsockname +define inline C-function getsockname parameter socket :: ; parameter address :: ; parameter address-len :: ; @@ -77,7 +77,7 @@ define inline-only C-function getsockopt c-name: "getsockopt"; end C-function; -define inline-only C-function listen +define inline C-function listen parameter socket :: ; parameter backlog :: ; result val :: ; @@ -146,7 +146,7 @@ define inline-only C-function sendto c-name: "sendto"; end C-function; -define inline-only C-function setsockopt +define inline C-function setsockopt parameter socket :: ; parameter level :: ; parameter option-name :: ; @@ -156,14 +156,14 @@ define inline-only C-function setsockopt c-name: "setsockopt"; end C-function; -define inline-only C-function shutdown +define inline C-function shutdown parameter socket :: ; parameter how :: ; result val :: ; c-name: "shutdown"; end C-function; -define inline-only C-function socket +define inline C-function socket parameter domain :: ; parameter type :: ; parameter protocol :: ; diff --git a/sources/network/winsock2/first.dylan b/sources/network/winsock2/first.dylan index c5f5c7665a..4b1ef4c036 100644 --- a/sources/network/winsock2/first.dylan +++ b/sources/network/winsock2/first.dylan @@ -24,11 +24,11 @@ define inline-only constant = ; define inline-only constant = ; -define inline-only function import-wchar +define inline function import-wchar (value :: ) => (char :: ) as(, value) end; -define inline-only function export-wchar +define inline function export-wchar (value :: ) => (i :: ) as(, value) end; diff --git a/sources/network/winsock2/hand.dylan b/sources/network/winsock2/hand.dylan index 727488d345..6dac6a30d5 100644 --- a/sources/network/winsock2/hand.dylan +++ b/sources/network/winsock2/hand.dylan @@ -99,7 +99,7 @@ define inline-only C-function win32-send-buffer c-name: "send", c-modifiers: "__stdcall"; end; -define inline-only C-function win32-recv-buffer-from +define inline C-function win32-recv-buffer-from parameter s :: ; parameter buf :: ; parameter len :: ; @@ -110,7 +110,7 @@ define inline-only C-function win32-recv-buffer-from c-name: "recvfrom", c-modifiers: "__stdcall"; end; -define inline-only C-function win32-send-buffer-to +define inline C-function win32-send-buffer-to parameter s :: ; parameter buf :: ; parameter len :: ; diff --git a/sources/network/winsock2/winsock2.dylan b/sources/network/winsock2/winsock2.dylan index 2d76497344..6f8c82274b 100644 --- a/sources/network/winsock2/winsock2.dylan +++ b/sources/network/winsock2/winsock2.dylan @@ -34,7 +34,7 @@ define C-struct c-name: "struct fd_set"; end C-struct ; -define inline-only C-function %-WSAFDIsSet +define inline C-function %-WSAFDIsSet parameter socket1 :: ; parameter lpfdset2 :: ; result value :: ; @@ -46,8 +46,8 @@ define inline-only function FD-ISSET (fd, set); end; define C-struct - sealed inline-only slot tv-sec-value :: ; - sealed inline-only slot tv-usec-value :: ; + sealed inline slot tv-sec-value :: ; + sealed inline slot tv-usec-value :: ; pointer-type-name: ; end C-struct; @@ -204,9 +204,9 @@ define inline-only constant $INADDR-BROADCAST = $FFFFFFFF; define inline-only constant $INADDR-NONE = $FFFFFFFF; define C-struct - sealed inline-only slot sin-family-value :: ; - sealed inline-only slot sin-port-value :: ; - sealed inline-only slot sin-addr-value :: ; + sealed inline slot sin-family-value :: ; + sealed inline slot sin-port-value :: ; + sealed inline slot sin-addr-value :: ; sealed inline-only array slot sin-zero-array :: , length: 8, address-getter: sin-zero-value; pointer-type-name: ; @@ -969,7 +969,7 @@ define inline constant = ; define inline constant = ; define inline constant = ; -define inline-only C-function accept +define inline C-function accept parameter s :: ; parameter addr :: ; parameter addrlen :: ; @@ -977,7 +977,7 @@ define inline-only C-function accept c-name: "accept", c-modifiers: "__stdcall"; end; -define inline-only C-function bind +define inline C-function bind parameter s :: ; parameter name :: /* const */ ; parameter namelen :: ; @@ -985,13 +985,13 @@ define inline-only C-function bind c-name: "bind", c-modifiers: "__stdcall"; end; -define inline-only C-function closesocket +define inline C-function closesocket parameter s :: ; result value :: ; c-name: "closesocket", c-modifiers: "__stdcall"; end; -define inline-only C-function connect +define inline C-function connect parameter s :: ; parameter name :: /* const */ ; parameter namelen :: ; @@ -1033,13 +1033,13 @@ define inline-only C-function getsockopt c-name: "getsockopt", c-modifiers: "__stdcall"; end; -define inline-only C-function htonl +define inline C-function htonl parameter hostlong :: ; result value :: ; c-name: "htonl", c-modifiers: "__stdcall"; end; -define inline-only C-function htons +define inline C-function htons parameter hostshort :: ; result value :: ; c-name: "htons", c-modifiers: "__stdcall"; @@ -1057,20 +1057,20 @@ define inline-only C-function inet-ntoa c-name: "inet_ntoa", c-modifiers: "__stdcall"; end; -define inline-only C-function listen +define inline C-function listen parameter s :: ; parameter backlog :: ; result value :: ; c-name: "listen", c-modifiers: "__stdcall"; end; -define inline-only C-function ntohl +define inline C-function ntohl parameter netlong :: ; result value :: ; c-name: "ntohl", c-modifiers: "__stdcall"; end; -define inline-only C-function ntohs +define inline C-function ntohs parameter netshort :: ; result value :: ; c-name: "ntohs", c-modifiers: "__stdcall"; @@ -1126,7 +1126,7 @@ define inline-only C-function sendto c-name: "sendto", c-modifiers: "__stdcall"; end; -define inline-only C-function setsockopt +define inline C-function setsockopt parameter s :: ; parameter level :: ; parameter optname :: ; @@ -1143,7 +1143,7 @@ define inline-only C-function shutdown c-name: "shutdown", c-modifiers: "__stdcall"; end; -define inline-only C-function socket +define inline C-function socket parameter af :: ; parameter type :: ; parameter protocol :: ; diff --git a/sources/ole/ole-automation/dispatch.dylan b/sources/ole/ole-automation/dispatch.dylan index d30520d8ab..65852e284d 100644 --- a/sources/ole/ole-automation/dispatch.dylan +++ b/sources/ole/ole-automation/dispatch.dylan @@ -154,11 +154,11 @@ define method apply-to-dispparams // (usually , but doesn't matter here.) parms :: // the function arguments. ); // (returns whatever the function returns) - let numparms = parms.cArgs-value; // total number of arguments + let numparms :: = parms.cArgs-value; // total number of arguments if ( zero?(numparms) ) // short cut when no parameters function(instance); else - let numnamed = parms.cNamedArgs-value; // number of named arguments + let numnamed :: = parms.cNamedArgs-value; // number of named arguments let numpos = numparms - numnamed; // number of positional arguments let argptr :: = parms.rgvarg-value; if ( numpos = 1 & numnamed = 0 ) diff --git a/sources/system/settings/win32-settings.dylan b/sources/system/settings/win32-settings.dylan index 8fb5dc91e8..71ddd49619 100644 --- a/sources/system/settings/win32-settings.dylan +++ b/sources/system/settings/win32-settings.dylan @@ -469,17 +469,18 @@ define inline-only constant $WRITING-SAM = as(, logior($KEY-QUERY-VALUE, $KEY-SET-VALUE, $KEY-CREATE-SUB-KEY, $KEY-ENUMERATE-SUB-KEYS)); -define variable *settings-default-class* = "Open Dylan"; +define variable *settings-default-class* :: = "Open Dylan"; define sealed method initialize-settings (settings :: , for-writing? :: ) => () local method open () - let parent = element($settings-table, settings-parent(settings)); + let parent :: + = element($settings-table, settings-parent(settings)); initialize-settings(parent, for-writing?); let hKey = settings-key-handle(parent); if (hKey) - let key = settings-key-name(settings); - let class = *settings-default-class*; + let key :: = settings-key-name(settings); + let class :: = *settings-default-class*; let (phkResult, result) = if (for-writing?) RegCreateKeyEx(hKey, key, class, $REG-OPTION-NON-VOLATILE, $WRITING-SAM)