The Protocol field isn't really necessary, because the conformance
stores the protocol. But we do need the substituted subject type
of the requirement, just temporarily, until an abstract conformance
stores its own subject type too.
Casts always work with formal rather than lowered types.
This fixes a potential bug when lowered types are different than formal types, like function types.
* let `SIL.Type` conform to `TypeProperties` to share the implementation of common type properties between the AST types and `SIL.Type`
* call references to an `AST.Type` `rawType` (instead of just `type`)
* remove unneeded stuff
* add comments
InteriorLiveness has a new "visitInnerUses" mode used by DestroyHoisting. That
mode may visit dependent values, which was not valid for noescape
closures. ClosureLifetimeFixup inserts destroys of noescape closures after the
destroys of the captures. So following such dependent value could result in an
apparent use-after-destroy. This causes DestroyHoisting to insert redundant
destroys.
Fix: InteriorUses will conservatively only follow dependent values if they are
escapable. Non-escapable values, like noescape closures are now considered
escapes of the original value that the non-escapable value depends on. This can
be improved in the future, but we may want to rewrite ClosureLifetimeFixup first.
Fixes the root cause of: rdar://146142041
When creating a specialized witness table, we need to get the right specialized conformance.
In IRGen don't emit associated conformance witness table entries if the protocol is not a class protocol.
In this case the associated type can never be used to create an existential. Therefore such a witness table entry is never used at runtime in embedded swift.
Fixes a compiler crash
rdar://146448091
* factor out common methods of AST Type/CanonicalType into a `TypeProperties` protocol.
* add more APIs to AST Type/CanoncialType.
* move `MetatypeRepresentation` from SIL.Type to AST.Type and implement it with a swift enum.
* let `Builder.createMetatype` get a CanonicalType as instance type, because the instance type must not be a lowered type.
DestroyHoisting is using this utility. This requires complete liveness. But we
can't rely on complete liveness because complete lifetimes is not
enabled. Instead, we use a visitInnerUses flag to try to ignore borrow
scopes. That flag was never properly implemented. Make an attempt here.
Always visit the use even if it is the beginning of an inner borrow. This
provides a "better" liveness result in the case of dead borrows and gives the
client a chance to see/intercept all uses.
The extra complexity for traversing phis is not needed now that it handles
borrowed-from instructions. Remove the redundant logic because it complicates
the liveness algorithm and generates confusing results.
Inner scopes must all be reported because the walker assumes they are
complete. It is up to the client to either complete them or recursively follow
them.
Check if the forwarded value is trivial, not the base value. Presumably, we
won't call this visitor at all if the base is trivial.
Record a dependent non-Escapable values as a pointer-escape. InteriorUseWalker
does not handle lifetime dependencies. That requires
LifetimeDependenceDefUseWalker.
Only return false if the visitor returns false. Clients were ignoring the
result.
If the BorrowingOperand does not create a borrow scope, call visitUnknownUse
instead.
Until we have complete lifetimes, to avoid breaking code that cannot handle dead
defs, consider a dead borrow scope to be an unknown use.
Functional changes:
Improved modeling of dependence on local variable scopes.
For nested modify->read accesses, only extend the read accesses.
Avoid making a read access dependent on an inout argument.
The following needs to be an error to prevent span storage from being modified:
@lifetime(owner)
foo(owner: inout Owner) -> Span {
owner.span
}
Improve usability of borrowing trivial values (UnsafePointer). Allow:
let span = Span(buffer.baseAddress)
Ignore access scopes for trivial values.
Structural changes:
Delete the LifetimeDependenceUseDefWalker.
Encapsulate all logic for variable introducers within the LifetimeDependenceInsertion pass. Once mark_dependence instructions are inserted, no subsequent pass needs to think about the "root" of a dependence.
Fixes: rdar://142451725 (Escape analysis fails with mutations)
This is necessary to fix a recent OSSA bug that breaks common occurrences on
mark_dependence [nonescaping]. Rather than reverting that change above, we make
forward progress toward implicit borrows scopes, as was the original intention.
In the near future, all InteriorPointer instructions will create an implicit
borrow scope. This means we have the option of not emitting extraneous
begin/end_borrow instructions around intructions like ref_element_addr,
open_existential, and project_box. After that, we can also migrate
GuaranteedForwarding instructions like tuple_extract and struct_extract.
The problem with `is_escaping_closure` was that it didn't consume its operand and therefore reference count checks were unreliable.
For example, copy-propagation could break it.
As this instruction was always used together with an immediately following `destroy_value` of the closure, it makes sense to combine both into a `destroy_not_escaped_closure`.
It
1. checks the reference count and returns true if it is 1
2. consumes and destroys the operand