内联如何与外部库一起使用? (Swift)
How does inlining work with external libraries? (Swift)
属性@inline(__always)
强制编译器内联特定函数。外部库提供的代码如何内联到一个项目中?编译器是否真的从库的可执行文件中复制代码段?
据我所知,@inline(__always)
意味着函数(或类似函数)始终是内联的,无论如何。这意味着它的符号在编译模块中公开,因此它们可以被使用该模块的项目内联。因此 "always".
这主要是一个未记录的属性,我能找到的唯一官方参考是在一些 stdlib 开发者的 internal documentation, not even describing its behavior directly. The best unofficial documentation I can find is Vandad Nahavandipoor's disassembly-confirmed investigation into its behavior 中,它没有试图确认您关注的跨模块用例。
在Swift4.2,@inlinable
and @usableFromInline
were introduced完成这个故事。
我的理解:
@inline(__always)
强制函数(等)每次内联,无论它们在哪里声明或使用
@inlinable
允许将模块中的函数(等)内联到该模块中的调用代码中,或调用使用该模块的代码,如果编译器认为有必要的话
如果编译器认为有必要,@usableFromInline
允许将模块内部的函数(等)内联到 @inlinable
调用也在该模块中的代码中。不像@inlinable
,这些必须是internal
;他们不能是public
根据Swift.org:
inlinable
Apply this attribute to a function, method, computed property, subscript, convenience initializer, or deinitializer declaration to expose that declaration’s implementation as part of the module’s public interface. The compiler is allowed to replace calls to an inlinable symbol with a copy of the symbol’s implementation at the call site.
Inlinable code can interact with public
symbols declared in any module, and it can interact with internal symbols declared in the same module that are marked with the usableFromInline
attribute. Inlinable code can’t interact with private
or fileprivate
symbols.
This attribute can’t be applied to declarations that are nested inside functions or to fileprivate
or private
declarations. Functions and closures that are defined inside an inlinable function are implicitly inlinable, even though they can’t be marked with this attribute.
usableFromInline
Apply this attribute to a function, method, computed property, subscript, initializer, or deinitializer declaration to allow that symbol to be used in inlinable code that’s defined in the same module as the declaration. The declaration must have the internal access level modifier. A structure or class marked usableFromInline
can use only types that are public or usableFromInline
for its properties. An enumeration marked usableFromInline
can use only types that are public or usableFromInline
for the raw values and associated values of its cases.
Like the public
access level modifier, this attribute exposes the declaration as part of the module’s public interface. Unlike public
, the compiler doesn’t allow declarations marked with usableFromInline
to be referenced by name in code outside the module, even though the declaration’s symbol is exported. However, code outside the module might still be able to interact with the declaration’s symbol by using runtime behavior.
Declarations marked with the inlinable
attribute are implicitly usable from inlinable
code. Although either inlinable
or usableFromInline
can be applied to internal
declarations, applying both attributes is an error.
属性@inline(__always)
强制编译器内联特定函数。外部库提供的代码如何内联到一个项目中?编译器是否真的从库的可执行文件中复制代码段?
据我所知,@inline(__always)
意味着函数(或类似函数)始终是内联的,无论如何。这意味着它的符号在编译模块中公开,因此它们可以被使用该模块的项目内联。因此 "always".
这主要是一个未记录的属性,我能找到的唯一官方参考是在一些 stdlib 开发者的 internal documentation, not even describing its behavior directly. The best unofficial documentation I can find is Vandad Nahavandipoor's disassembly-confirmed investigation into its behavior 中,它没有试图确认您关注的跨模块用例。
在Swift4.2,@inlinable
and @usableFromInline
were introduced完成这个故事。
我的理解:
@inline(__always)
强制函数(等)每次内联,无论它们在哪里声明或使用@inlinable
允许将模块中的函数(等)内联到该模块中的调用代码中,或调用使用该模块的代码,如果编译器认为有必要的话
如果编译器认为有必要,@usableFromInline
允许将模块内部的函数(等)内联到@inlinable
调用也在该模块中的代码中。不像@inlinable
,这些必须是internal
;他们不能是public
根据Swift.org:
inlinable
Apply this attribute to a function, method, computed property, subscript, convenience initializer, or deinitializer declaration to expose that declaration’s implementation as part of the module’s public interface. The compiler is allowed to replace calls to an inlinable symbol with a copy of the symbol’s implementation at the call site.
Inlinable code can interact with
public
symbols declared in any module, and it can interact with internal symbols declared in the same module that are marked with theusableFromInline
attribute. Inlinable code can’t interact withprivate
orfileprivate
symbols.This attribute can’t be applied to declarations that are nested inside functions or to
fileprivate
orprivate
declarations. Functions and closures that are defined inside an inlinable function are implicitly inlinable, even though they can’t be marked with this attribute.
usableFromInline
Apply this attribute to a function, method, computed property, subscript, initializer, or deinitializer declaration to allow that symbol to be used in inlinable code that’s defined in the same module as the declaration. The declaration must have the internal access level modifier. A structure or class marked
usableFromInline
can use only types that are public orusableFromInline
for its properties. An enumeration markedusableFromInline
can use only types that are public orusableFromInline
for the raw values and associated values of its cases.Like the
public
access level modifier, this attribute exposes the declaration as part of the module’s public interface. Unlikepublic
, the compiler doesn’t allow declarations marked withusableFromInline
to be referenced by name in code outside the module, even though the declaration’s symbol is exported. However, code outside the module might still be able to interact with the declaration’s symbol by using runtime behavior.Declarations marked with the
inlinable
attribute are implicitly usable frominlinable
code. Although eitherinlinable
orusableFromInline
can be applied tointernal
declarations, applying both attributes is an error.