Skip to content

[no-implicit-copy] Update SILGen/move checker to work with new patterns from copyable_to_moveonly and friends. #59611

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jun 28, 2022

Conversation

gottesmm
Copy link
Contributor

This involved doing the following:

  1. Update the move only checker to look for new patterns.

  2. Teach emitSemanticStore to use a moveonlywrapper_to_copyable to store moveonly
    values into memory. The various checkers will validate that this code is
    correct.

  3. When emitting an apply, always unwrap move only variables. In the
    future, I am going to avoid this if a parameter is explicitly marked as also
    being moveonly (e.x.: @moveOnly parameter or @NoEscape argument).

  4. Convert from moveOnly -> copyable on return inst automatically in SILGen.

  5. Fix SILGenLValue emission so we emit an error diagnostic later rather than
    crash. This is needed to keep SILGen emitting move only addresses (that is no
    implicit copy address only lets) in a form that the move only checker then
    will error upon. Without this change, SILGen crashes instead of emitting an
    error diagnostic in the following test:
    .//test/SILOptimizer/move_only_checker_addressonly_fail.swift

Replace this paragraph with a description of your changes and rationale. Provide links to external references/discussions if appropriate.

Resolves SR-NNNN.

@gottesmm gottesmm requested a review from jckarter June 21, 2022 18:02
@gottesmm
Copy link
Contributor Author

@swift-ci test

…ns from copyable_to_moveonly and friends.

This involved doing the following:

1. Update the move only checker to look for new patterns.

2. Teach emitSemanticStore to use a moveonlywrapper_to_copyable to store moveonly
   values into memory. The various checkers will validate that this code is
   correct.

3. When emitting an apply, always unwrap move only variables. In the
   future, I am going to avoid this if a parameter is explicitly marked as also
   being moveonly (e.x.: @moveOnly parameter or @NoEscape argument).

4. Convert from moveOnly -> copyable on return inst automatically in SILGen.

5. Fix SILGenLValue emission so we emit an error diagnostic later rather than
   crash. This is needed to keep SILGen emitting move only addresses (that is no
   implicit copy address only lets) in a form that the move only checker then
   will error upon. Without this change, SILGen crashes instead of emitting an
   error diagnostic in the following test:
   .//test/SILOptimizer/move_only_checker_addressonly_fail.swift
@gottesmm
Copy link
Contributor Author

@jckarter I forgot to upload the trivial type eliminator. I added that in the 2nd commit I added here and also added a small fix that I discovered when writing some Interpreter tests for this.

@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test

gottesmm added 2 commits June 22, 2022 15:31
…ter move only checking.

This pass lowers moveonly-ness from the IR after we have finished move only
checking. The transform can be configured in two ways: such that it only handles
trivial types and such that it does trivial and non-trivial types. For ease of
use, I created two top level transforms (TrivialMoveOnlyTypeEliminator and
MoveOnlyTypeElimintor) that invoke the two behaviors by configuring the
underlying transform slightly differently.

For now, I am running first the trivial-only and then the all of the above
lowering. The trivial only pass will remain at this part of the pipeline
forever, but with time we are going to move the lower everything pass later into
the pipeline once I have audited the optimizer pipeline to just not perform any
work on move only types. That being said, currently we do not have this
guarantee and this patch at least improves the world and lets us codegen no
implicit copy code again.
…es before materializing for a function argument.

I discovered this as I began to write some Interpreter tests for move only. This
was triggered by SILGen attempting to pass a non-trivial type to StringBuilder
which is generic, so we needed to materialize.

I also discovered a small bug where we were not properly ignoring class_method
in the move only type eliminator. I just folded the small fix + a test for that
into this commit.
@gottesmm
Copy link
Contributor Author

@swift-ci test

@gottesmm
Copy link
Contributor Author

@swift-ci test macOS platform

1 similar comment
@gottesmm
Copy link
Contributor Author

@swift-ci test macOS platform


public func aggGenericStructAccessField<T>(_ x: AggGenericStruct<T>) {
@_noImplicitCopy let x2 = x // expected-error {{'x2' consumed more than once}}
print(x2.lhs) // expected-note {{consuming use}}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Projecting a stored property, or more generally, calling a get or read accessor with a guaranteed base, should not be a consuming use.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason this is a consuming use is b/c of print. Print consumes values unfortunately due to the way we construct the array.

/////////////////////////////////

public func klassNoImplicitCopyArgument(@_noImplicitCopy _ x: Trivial) -> Trivial {
return x
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For a nontrivial x, returning it here would be considered a copy, unless the argument were __owned. Should this also be flagged as a consuming use?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually have @_noImplicitCopy arguments being +1 currently. I am looking at changing that (I can do it in this PR)

@gottesmm
Copy link
Contributor Author

@jckarter Hows this sound: can we get in this PR and then in follow on PRs I will do the following:

  1. Remove the typelowering bit for move only (leaving in typelowering itself though)
  2. I am going to rename MoveOnlyType to MoveOnlyWrappedType
  3. I am going to change the owned no implicit copy ABI change to not be there and add a test that shows the behavior is as expected for non-trivial types as well.
  4. I am going to make it so that no-implicit-copy does not apply to fields of the underlying struct since it is a getter and the type will be copyable.

@jckarter
Copy link
Contributor

That works for me.

@gottesmm gottesmm merged commit 6a24087 into swiftlang:main Jun 28, 2022
@gottesmm gottesmm deleted the moveonly-rebase branch June 28, 2022 20:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants