Skip to content
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

Dedup auto traits in trait objects. #51276

Merged
merged 3 commits into from
Jun 9, 2018
Merged

Conversation

Havvy
Copy link
Contributor

@Havvy Havvy commented Jun 1, 2018

Fixes #47010

Note that the test file run-pass/trait-object-auto-dedup.rs passes before and after this change. It's the ui test that changed from compiling to not compiling. Which does make this a breaking change, but I cannot imagine anybody actually being broken by it.

@rust-highfive
Copy link
Collaborator

r? @michaelwoerister

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jun 1, 2018
let mut auto_traits =
auto_traits.into_iter().map(ty::ExistentialPredicate::AutoTrait).collect::<Vec<_>>();
auto_traits.sort_by(|a, b| a.cmp(tcx, b));
auto_traits.dedup_by(|a, b| (&*a).cmp(tcx, b) == Ordering::Equal);
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 (&*a) is necessary here because std::cmp::Ord::cmp shadows ty::ExistentialPredicate::cmp for an &mut ty::ExistentialPredicate, but not necessary in the sort_by on the previous line because the shadowing is reversed for &ty::ExistentialPreciate (and the unborrowed version).

Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder if it's possible for you to just collect into an FxHashSet here?

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 cmp used by a HashSet doesn't compare using the TyCtx, so would fail if the DefIds for the auto trait are different, which I think can happen through type or use aliases. Also, in the vast majority of cases, there's going to be less than three auto traits (and many times zero), so I don't think it would be much of an optimization.

Copy link
Contributor

Choose a reason for hiding this comment

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

First off, I would recommend invoking ty::ExistentialPredicate::cmp — but maybe we should rename that method, if it is indeed not equivalent to Ord::cmp?

Copy link
Contributor

Choose a reason for hiding this comment

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

Put another way, why can't we invoke .dedup() here?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hmm, I thought that the DefIds might be different based on which use clause you use, but switching to just .dedup() works here. But then, why is there both ty::ExistentialPredicate::cmp and Ord::cmp if they give the same results? Are there actually cases where two DefIds could point to the same trait?

Copy link
Contributor

Choose a reason for hiding this comment

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

So, that function (a) has a bad name and (b) needs a comment. I think the distinction is this:

  • ExistentialPredicate::cmp sorts via a stable ordering that will not change if modules are ordered or other changes are made to the tree. In particular, this ordering is preserved across incremental compilations.
  • Ord::Cmp sorts in an order that is not stable across compilations.

For purposes of equality, they are equivalent.

It should really be called ExistentialPredicate::stable_cmp -- would you be game to try and rename it? (And add a comment.)

That could be either part of this PR or outside of it...

...given the unfortunate shadowing, the way I would go about it would be to add stable_cmp and mark the existing method as deprecated (and maybe make it panic! for good measure). Then a ./x.py test should shake out all the callers. =)

Copy link
Contributor

Choose a reason for hiding this comment

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

In any case, I think we can also (in this PR) just call dedup. We probably don't need a stable ordering, either.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In that case, we don't need to put the auto traits into the ExistentialPredicate before sorting and deduping, so can just sort and dedup the returned auto traits. Which makes this change ultimately more readable than the whole wrapping and then comparing.

--

I'll tackle the refactor in a separate PR, since it has nothing to do with this one. Due to the argument count difference, anybody calling the inherent method will get an argument count error at compile time, so I don't think the old name needs to be deprecated.

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

[00:04:52] travis_fold:start:tidy
travis_time:start:tidy
tidy check
[00:04:52] tidy error: /checkout/src/test/run-pass/trait-object-auto-dedup.rs: missing trailing newline
[00:04:52] tidy error: /checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs: incorrect license
[00:04:52] tidy error: /checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs: missing trailing newline
[00:04:54] some tidy checks failed
[00:04:54] 
[00:04:54] 
[00:04:54] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/tidy" "/checkout/src" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "--no-vendor" "--quiet"
[00:04:54] 
[00:04:54] 
[00:04:54] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test src/tools/tidy
[00:04:54] Build completed unsuccessfully in 0:01:51
[00:04:54] Build completed unsuccessfully in 0:01:51
[00:04:54] make: *** [tidy] Error 1
[00:04:54] Makefile:79: recipe for target 'tidy' failed

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:0e23e9d6
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

[00:08:26] travis_fold:start:tidy
travis_time:start:tidy
tidy check
[00:08:27] tidy error: /checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs: incorrect license
[00:08:28] some tidy checks failed
[00:08:28] 
[00:08:28] 
[00:08:28] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/tidy" "/checkout/src" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0/bin/cargo" "--no-vendor" "--quiet"
[00:08:28] 
[00:08:28] 
[00:08:28] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test src/tools/tidy
[00:08:28] Build completed unsuccessfully in 0:02:24
[00:08:28] Build completed unsuccessfully in 0:02:24
[00:08:28] Makefile:79: recipe for target 'tidy' failed
[00:08:28] make: *** [tidy] Error 1

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:036f2bc8
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:46:56] ..........................................................................i.........................
[00:47:01] ....................................................................................................
[00:47:06] ....................................................................................................
[00:47:12] ....................................................................................................
[00:47:16] ......i.............F....iiiiiiiii...................................................
[00:47:16] 
[00:47:16] ---- [ui] ui/trait-object-auto-dedup-in-impl.rs stdout ----
[00:47:16] diff of stderr:
[00:47:16] 
[00:47:16] 
[00:47:16] 1 error[E0592]: duplicate definitions with name `test`
[00:47:16] -   --> $DIR/trait-object-auto-dedup-in-impl.rs:21:5
[00:47:16] +   --> $DIR/trait-object-auto-dedup-in-impl.rs:24:5
[00:47:16] 3    |
[00:47:16] 4 LL |     fn test(&self) { println!("one"); } //~ ERROR duplicate definitions with name `test`
[00:47:16] 5    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `test`
[00:47:16] 
[00:47:16] The actual stderr differed from the expected stderr.
[00:47:16] The actual stderr differed from the expected stderr.
[00:47:16] Actual stderr saved to /checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/trait-object-auto-dedup-in-impl/trait-object-auto-dedup-in-impl.stderr
[00:47:16] To update references, rerun the tests and pass the `--bless` flag
[00:47:16] To only update this specific test, also pass `--test-args trait-object-auto-dedup-in-impl.rs`
[00:47:16] error: 1 errors occurred comparing output.
[00:47:16] status: exit code: 101
[00:47:16] status: exit code: 101
[00:47:16] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/trait-object-auto-dedup-in-impl/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/trait-object-auto-dedup-in-impl/auxiliary" "-A" "unused"
[00:47:16] ------------------------------------------
[00:47:16] 
[00:47:16] ------------------------------------------
[00:47:16] stderr:
[00:47:16] stderr:
[00:47:16] ------------------------------------------
[00:47:16] {"message":"duplicate definitions with name `test`","code":{"code":"E0592","explanation":null},"level":"error","spans":[{"file_name":"/checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs","byte_start":738,"byte_end":773,"line_start":24,"line_end":24,"column_start":5,"column_end":40,"is_primary":true,"text":[{"text":"    fn test(&self) { println!(\"one\"); } //~ ERROR duplicate definitions with name `test`","highlight_start":5,"highlight_end":40}],"label":"duplicate definitions for `test`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null},{"file_name":"/checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs","byte_start":857,"byte_end":892,"line_start":28,"line_end":28,"column_start":5,"column_end":40,"is_primary":false,"text":[{"text":"    fn test(&self) { println!(\"two\"); }","highlight_start":5,"highlight_end":40}],"label":"other definition for `test`","suggested_replacement":null,"suggestion_applicability":null,"expansion":null}],"children":[],"rendered":"error[E0592]: duplicate definitions with name `test`\n  --> /checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs:24:5\n   |\nLL |     fn test(&self) { println!(\"one\"); } //~ ERROR duplicate definitions with name `test`\n   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definitions for `test`\n...\nLL |     fn test(&self) { println!(\"two\"); }\n   |     ----------------------------------- other definition for `test`\n\n"}
[00:47:16] {"message":"aborting due to previous error","code":null,"level":"error","spans":[],"children":[],"rendered":"error: aborting due to previous error\n\n"}
[00:47:16] {"message":"For more information about this error, try `rustc --explain E0592`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0592`.\n"}
[00:47:16] ------------------------------------------
[00:47:16] 
[00:47:16] thread '[ui] ui/trait-object-auto-dedup-in-impl.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:3096:9
[00:47:16] note: Run with `RUST_BACKTRACE=1` for a backtrace.
---
[00:47:16] 
[00:47:16] thread 'main' panicked at 'Some tests failed', tools/compiletest/src/main.rs:498:22
[00:47:16] 
[00:47:16] 
[00:47:16] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-3.9/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Zunstable-options " "--target-rustcflags" "-Crpath -O -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "3.9.1\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[00:47:16] 
[00:47:16] 
[00:47:16] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[00:47:16] Build completed unsuccessfully in 0:02:33
[00:47:16] Build completed unsuccessfully in 0:02:33
[00:47:16] Makefile:58: recipe for target 'check' failed
[00:47:16] make: *** [check] Error 1

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:2af75ab8
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@Havvy
Copy link
Contributor Author

Havvy commented Jun 1, 2018

But why did that pass on my end?

@Havvy Havvy force-pushed the dyn-trait-send-send branch 2 times, most recently from d0e4f82 to 1990b45 Compare June 1, 2018 17:56
@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.
[00:56:21] ..........................................................................i.........................
[00:56:28] ....................................................................................................
[00:56:35] ....................................................................................................
[00:56:42] ....................................................................................................
[00:56:48] ......i...........F......iiiiiiiii...................................................
[00:56:48] 
[00:56:48] ---- [ui] ui/trait-object-auto-dedup-in-impl.rs stdout ----
[00:56:48] 
[00:56:48] 
[00:56:48] error: /checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs:24: unexpected error: '24:5: 24:40: duplicate definitions with name `test` [E0592]'
[00:56:48] 
[00:56:48] error: /checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs:24: expected error not found: duplicate definitions for `test`
[00:56:48] 
[00:56:48] error: 1 unexpected errors found, 1 expected errors not found
[00:56:48] status: exit code: 101
[00:56:48] command: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/src/test/ui/trait-object-auto-dedup-in-impl.rs" "--target=x86_64-unknown-linux-gnu" "--error-format" "json" "-Zui-testing" "-C" "prefer-dynamic" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/trait-object-auto-dedup-in-impl/a" "-Crpath" "-O" "-Zunstable-options" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/trait-object-auto-dedup-in-impl/auxiliary" "-A" "unused"
[00:56:48] unexpected errors (from JSON output): [
[00:56:48]     Error {
[00:56:48]         line_num: 24,
[00:56:48]         kind: Some(
[00:56:48]         ),
[00:56:48]         ),
[00:56:48]         msg: "24:5: 24:40: duplicate definitions with name `test` [E0592]"
[00:56:48] ]
[00:56:48] 
[00:56:48] not found errors (from test file): [
[00:56:48]     Error {
[00:56:48]     Error {
[00:56:48]         line_num: 24,
[00:56:48]         kind: Some(
[00:56:48]             Error
[00:56:48]         ),
[00:56:48]         msg: "duplicate definitions for `test`"
[00:56:48] ]
[00:56:48] 
[00:56:48] thread '[ui] ui/trait-object-auto-dedup-in-impl.rs' panicked at 'explicit panic', tools/compiletest/src/runtest.rs:1284:13
[00:56:48] note: Run with `RUST_BACKTRACE=1` for a backtrace.
---
[00:56:48] 
[00:56:48] thread 'main' panicked at 'Some tests failed', tools/compiletest/src/main.rs:498:22
[00:56:48] 
[00:56:48] 
[00:56:48] command did not execute successfully: "/checkout/obj/build/x86_64-unknown-linux-gnu/stage0-tools-bin/compiletest" "--compile-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib" "--run-lib-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/lib/rustlib/x86_64-unknown-linux-gnu/lib" "--rustc-path" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "--src-base" "/checkout/src/test/ui" "--build-base" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui" "--stage-id" "stage2-x86_64-unknown-linux-gnu" "--mode" "ui" "--target" "x86_64-unknown-linux-gnu" "--host" "x86_64-unknown-linux-gnu" "--llvm-filecheck" "/usr/lib/llvm-3.9/bin/FileCheck" "--host-rustcflags" "-Crpath -O -Zunstable-options " "--target-rustcflags" "-Crpath -O -Zunstable-options  -Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "--docck-python" "/usr/bin/python2.7" "--lldb-python" "/usr/bin/python2.7" "--gdb" "/usr/bin/gdb" "--quiet" "--llvm-version" "3.9.1\n" "--system-llvm" "--cc" "" "--cxx" "" "--cflags" "" "--llvm-components" "" "--llvm-cxxflags" "" "--adb-path" "adb" "--adb-test-dir" "/data/tmp/work" "--android-cross-path" "" "--color" "always"
[00:56:48] 
[00:56:48] 
[00:56:48] failed to run: /checkout/obj/build/bootstrap/debug/bootstrap test
[00:56:48] Build completed unsuccessfully in 0:03:23
[00:56:48] Build completed unsuccessfully in 0:03:23
[00:56:48] Makefile:58: recipe for target 'check' failed
[00:56:48] make: *** [check] Error 1

The command "stamp sh -x -c "$RUN_SCRIPT"" exited with 2.
travis_time:start:08951c50
$ date && (curl -fs --head https://google.com | grep ^Date: | sed 's/Date: //g' || true)

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@rust-highfive
Copy link
Collaborator

The job x86_64-gnu-llvm-3.9 of your PR failed on Travis (raw log). Through arcane magic we have determined that the following fragments from the build log may contain information about the problem.

Click to expand the log.

I'm a bot! I can only do what humans tell me to, so if this was not helpful or you have suggestions for improvements, please ping or otherwise contact @TimNN. (Feature Requests)

@michaelwoerister
Copy link
Member

r? @nikomatsakis for re-assignment

@nikomatsakis
Copy link
Contributor

@bors r+

@bors
Copy link
Contributor

bors commented Jun 8, 2018

📌 Commit eccd2ed has been approved by nikomatsakis

@bors
Copy link
Contributor

bors commented Jun 8, 2018

🌲 The tree is currently closed for pull requests below priority 1, this pull request will be tested once the tree is reopened

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jun 8, 2018
Mark-Simulacrum added a commit to Mark-Simulacrum/rust that referenced this pull request Jun 8, 2018
…tsakis

Dedup auto traits in trait objects.

Fixes rust-lang#47010

Note that the test file `run-pass/trait-object-auto-dedup.rs` passes before and after this change. It's the `ui` test that changed from compiling to not compiling. Which does make this a breaking change, but I cannot imagine anybody actually being broken by it.
@bors
Copy link
Contributor

bors commented Jun 8, 2018

🔒 Merge conflict

@bors bors added S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. and removed S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. labels Jun 8, 2018
bors added a commit that referenced this pull request Jun 8, 2018
Rollup of 13 pull requests

Successful merges:

 - #50143 (Add deprecation lint for duplicated `macro_export`s)
 - #51099 (Fix Issue 38777)
 - #51276 (Dedup auto traits in trait objects.)
 - #51298 (Stabilize unit tests with non-`()` return type)
 - #51360 (Suggest parentheses when a struct literal needs them)
 - #51391 (Use spans pointing at the inside of a rustdoc attribute)
 - #51394 (Use scope tree depths to speed up `nearest_common_ancestor`.)
 - #51396 (Make the size of Option<NonZero*> a documented guarantee.)
 - #51401 (Warn on `repr` without hints)
 - #51412 (Avoid useless Vec clones in pending_obligations().)
 - #51427 (compiletest: autoremove duplicate .nll.* files (#51204))
 - #51436 (Do not require stage 2 compiler for rustdoc)
 - #51437 (rustbuild: generate full list of dependencies for metadata)

Failed merges:
@bors bors merged commit eccd2ed into rust-lang:master Jun 9, 2018
@Havvy Havvy deleted the dyn-trait-send-send branch June 9, 2018 03:19
@SimonSapin SimonSapin added the relnotes Marks issues that should be documented in the release notes of the next release. label Jun 9, 2018
Havvy added a commit to Havvy/rust that referenced this pull request Jun 9, 2018
bors added a commit that referenced this pull request Jun 15, 2018
Refactor: Rename ExistentialPredicate::cmp to ExistentialPredicate::stable_cmp

See #51276 (comment) for
rationale.

Because stable_cmp takes three arguments and Ord::cmp takes two, I am confident that there is no shadowing happening here.

r? @nikomatsakis
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
relnotes Marks issues that should be documented in the release notes of the next release. S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants