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

Cherry-pick some downstream commits #13459

Closed
wants to merge 4 commits into from

Conversation

lnicola
Copy link
Member

@lnicola lnicola commented Oct 22, 2022

I couldn't use git merge for this, it seemed to give conflicts on files only modified on our side, like crates/project-model/Cargo.toml, so I cherry-picked a couple of commits from there.

bors and others added 4 commits October 22, 2022 08:32
proc_macro/bridge: send diagnostics over the bridge as a struct

This removes some RPC when creating and emitting diagnostics, and
simplifies the bridge slightly.

After this change, there are no remaining methods which take advantage
of the support for `&mut` references to objects in the store as
arguments, meaning that support for them could technically be removed if
we wanted. The only remaining uses of immutable references into the
store are `TokenStream` and `SourceFile`.

r? `@eddyb`
This fixes a typo first appearing in #94624
in which test-macro diagnostic uses "a" article twice.

Since I searched sources for " a a " sequences,
I also fixed the same issue in a few source files where I found it.

Signed-off-by: Petr Portnov <[email protected]>
@Veykril
Copy link
Member

Veykril commented Oct 24, 2022

I don't know subtrees too well but could this cause problems with syncs? (I have no idea how subtree syncs were tbh, is it just a merge commit?)

@bjorn3
Copy link
Member

bjorn3 commented Oct 25, 2022

I have no idea how subtree syncs were tbh, is it just a merge commit?

For rust-analyzer -> rust it is a merge commit created using the subtree merge strategy. For rust -> rust-analyzer it synthesizes new commits. Not sure if the commits in this PR will conflict.

@lnicola
Copy link
Member Author

lnicola commented Oct 25, 2022

Yeah, I think the sync back looks like this:

a99a48e78 (HEAD -> sync-from-rust, mine/sync-from-rust) :arrow_up: rust-analyzer
8536eb016 rename rustc_allocator_nounwind to rustc_nounwind
4f55ebbd4 :arrow_up: rust-analyzer
3a57388d1 update to syn-1.0.102
ed532e5a3 Fix duplicate usage of `a` article.
6f13f1230 rustc_typeck to rustc_hir_analysis
f5fde4df4 :arrow_up: rust-analyzer
459bbb422 :arrow_up: rust-analyzer
65e1dc4d9 :arrow_up: rust-analyzer
c1918fcb9 Auto merge of #100210 - mystor:proc_macro_diag_struct, r=eddyb
3e358a682 :arrow_up: rust-analyzer
31519bb39 :arrow_up: rust-analyzer
134701885 Rollup merge of #100643 - TaKO8Ki:point-at-type-parameter-shadowing-another-type, r=estebank
3a1aa376c avoid a `&str` to `String` conversion
8231fee46 :arrow_up: rust-analyzer
22c8c9c40 :arrow_up: rust-analyzer
2c7f2c105 proc_macro/bridge: send diagnostics over the bridge as a struct
9d2cb42a4 :arrow_up: rust-analyzer
a1f1b95d0 Merge commit 'e36a20c24f35a4cee82bbdc600289104c9237c22' into ra-sync-and-pms-component
dfe84494c Make macros test order-resistant
56c369db4 Sort when iterating through CrateGraph
d8c0d88e4 Sort in DefMap::dump, since HashMap iteration order isn't defined
ff317858c hir-def tests: sort results before comparing, since FxHashSet iteration order isn't guaranteed
74998e46e Fix .gitattributes for test_data
20eb2ddb2 Small fixups
[...]

@lnicola
Copy link
Member Author

lnicola commented Oct 27, 2022

r? @fasterthanlime, maybe?

@fasterthanlime
Copy link
Contributor

Just discovering this PR now — does the original PR description mean that following this guide didn't work? (I'm not sure what "merge" means in that context) https://doc.rust-lang.org/clippy/development/infrastructure/sync.html#performing-the-sync-from-rust-langrust-to-clippy

Cherry-picking seems like a bad idea and I'd rather ping some folks working on clippy/other subtrees before merging this.

@lnicola
Copy link
Member Author

lnicola commented Oct 27, 2022

I cherry picked some commits from the branch created by git subtree. But I can't merge the master branch into that one.

@fasterthanlime
Copy link
Contributor

it seemed to give conflicts on files only modified on our side, like crates/project-model/Cargo.toml

can't those merge conflicts be fixed? I feel like I should try to do the sync myself to see exactly what's going on.

@lnicola
Copy link
Member Author

lnicola commented Oct 27, 2022

I tried, but there were too many. It seemed to me that some of them were in files not touched by the downstream commits.

@bjorn3
Copy link
Member

bjorn3 commented Oct 27, 2022

Whenever syncing from rust-analyzer -> rust you have to immediately sync the merge commit from rust -> rust-analyzer to prevent merge conflicts in the future.

@fasterthanlime
Copy link
Contributor

I unfortunately won't have time to look more into this until next week, sorry - pinging @oli-obk for additional git-subtree expertise.

@oli-obk
Copy link
Contributor

oli-obk commented Oct 31, 2022

yea I think you need to either redo a rustc->here sync right after the last here->rustc sync or move to using https://github.com/josh-project/josh like miri did: https://github.com/rust-lang/miri/blob/master/CONTRIBUTING.md#advanced-topic-syncing-with-the-rustc-repo

@lnicola
Copy link
Member Author

lnicola commented Oct 31, 2022

Is there any way to fix this now that I've missed some syncs? I think I tried it right after a filing a sync PR, but before it being merged. Cherry-picking the commits doesn't sound too bad to me in the meanwhile.

On the other hand, we should probably give josh a try.

@oli-obk
Copy link
Contributor

oli-obk commented Oct 31, 2022

So is there any way to fix this now that I've missed some syncs

hmm... I'm not sure. You could try to do a sync in the other direction at each of the past syncs and basically rebuild what was "lost". But that could be a lot of work

@Veykril Veykril added the S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. label Nov 3, 2022
@lnicola
Copy link
Member Author

lnicola commented Nov 8, 2022

I'm still inclined to merge this. If we ever make it work in the future, they should "go away" and if not, the rust-lang/rust side isn't that hard to handle in the same way (with cherry-picks).

@fasterthanlime
Copy link
Contributor

I'm still inclined to merge this. If we ever make it work in the future, they should "go away" and if not, the rust-lang/rust side isn't that hard to handle in the same way (with cherry-picks).

Now that I'm full-time on open-source stuff (among other things), I actually do have time to work on this — do we have time for me to take a closer look, or should I do so after this is merged?

josh looks interesting, if it fixes most of our subtree woes, I would definitely invest effort into that.

@lnicola
Copy link
Member Author

lnicola commented Nov 8, 2022

No hurry there. The commits here are pretty old and I don't think we've missed them.

There's at least one more I didn't pick because it was a mass replace in a test fixture.

@fasterthanlime
Copy link
Contributor

fasterthanlime commented Nov 13, 2022

So I gave josh a quick try (using RalfJung's fork), with:

$ cd rust-analyzer/
$ JOSH_FILTER=":at_commit=a63222cd240d9b5405826783603f3b391c90885d[:prefix=src/tools/rust-analyzer]:/src/tools/rust-analyzer"
$ git fetch http://localhost:8000/rust-lang/rust.git$JOSH_FILTER.git master
From http://localhost:8000/rust-lang/rust.git:at_commit=a63222cd240d9b5405826783603f3b391c90885d[:prefix=src/tools/rust-analyzer]:/src/tools/rust-analyzer                                    * branch                master     -> FETCH_HEAD
$ git merge FETCH_HEAD --no-ff -m "Merge from rustc"
fatal: refusing to merge unrelated histories

(Where https://github.com/rust-lang/rust/commits/a63222cd240d9b5405826783603f3b391c90885d is the first commit in rust-lang/rust where the rust-analyzer subtree history begins — not 100% sure that's right)

Passing --allow-unrelated-histories made the merge succeed, although, with numerous conflicts, which I imagine looks like what you saw @lnicola:

https://gist.github.com/fasterthanlime/bb66f688764de5b4223b715e1704dbad

I think I could go through all these merge conflicts if we were convinced that was the way forward? Here's a sample one:

image

I think like often the "Current change" is the one we want to keep:

image

...there might even be a git option to do just that...

@fasterthanlime
Copy link
Contributor

Just checking in - do we think the way forward is switching to josh + resolving merge conflicts once? I have time to resolve the merge conflicts, it's time-consuming and annoying but if we do it once and "do it right" moving forward, it might be worth it, I just want to confirm that it's what we think is the right thing to do.

@lnicola
Copy link
Member Author

lnicola commented Nov 21, 2022

Some quick (but still late) thoughts:

  • I'm not sure we're getting the same conflicts, but it's likely
  • the conflicts don't really make sense to me
  • git isn't great IMHE at remembering how you resolved conflicts
  • cherry picking as I did here seems the right thing to do: we might not want every commit from the downstream, cherry picking worked and preserved authorship without causing any conflicts
  • I suspect I merged the two branches in the wrong direction, or something like that, which caused the conflicts

So josh might be nice to avoid patching git-subtree after every update, but I don't think it's worth spending time on those conflicts that don't even appear to make sense. Also, there's no guarantee we won't need to do it again on the next merge.

@fasterthanlime
Copy link
Contributor

So josh might be nice to avoid patching git-subtree after every update, but I don't think it's worth spending time on those conflicts that don't even appear to make sense. Also, there's no guarantee we won't need to do it again on the next merge.

That's actually my question: if we resolve the conflicts now and "do it right" moving forward, will it be the last time we have to deal with merge conflicts? (Unless there were actual conflicting changes, which I don't think is what happened there).

And also: if we do cherry pick those commits, will the next time we run a git-subtree or josh sync be conflict-free? Could we make sure that after cherry-picking, the file trees under rust-lang/rust-analyzer and rust-lang/rust/src/tools/rust-analyzer are the same? josh lets us specify a commit to start from, so if the contents are the same, maybe we would be able to have a conflict-free life going forward.

Maybe @RalfJung knows more? (since their fork of josh includes additional functionality)

@RalfJung
Copy link
Member

RalfJung commented Nov 22, 2022

Josh needs to be used with care. :) And you cannot mix josh with other sync strategies, it's use only-josh or no-josh. Using josh here means you should stop using git subtree entirely, and you sholuldn't do manual cherry-picking. Also no need to use my fork, josh master has all the patches (and my fork is probably outdated at this point).

The key thing to ensure with josh is that extracting the history from rustc must exactly produce the history in this repo.

When was the last time RA got pushed to rustc, and which RA commit was the one that got pushed? The first order of business is to ensure that extracting RA from rustc with josh yields a history that contains that commit. Since you used git subtree in the past, this will require a rev filter like in Miri, since josh and git subtree differ in how RA commits look like in rustc: with git subtree they contain just the subtree, but with josh they actually contain all of rustc.

In Miri we use the filter

:rev(75dd959a3a40eb5b4574f8d2e23aa6efbeb33573:prefix=src/tools/miri):/src/tools/miri

where 75dd959a3a40eb5b4574f8d2e23aa6efbeb33573 is the last (most recent) Miri commit in rustc that was created by git subtree. So this basically tells josh to move the git subtree part of the Miri history in rustc into a subfolder (where it would be if that history was created with josh), and then to project to that subfolder (the normal procedure with josh), which means we get a full Miri history that looks exactly like what we have in the Miri repo.

Once you have that first josh fetch figured out, you should produce a merge of that with RA master, resolving any conflicts that have occurred. Those should be real conflicts, if there are nonsense conflicts here then likely something went wrong. Prepare that commit but do not merge this in RA yet, you want to be sure this all went well before permanently merging something into RA! Merging the wrong thing can make it permanently impossible to use josh properly, fixable only with a force-push. Still it's a good idea to make a GitHub PR at this point, as that will show very nicely which new commits are being added, so it's a good sanity-check to look at the new commits and the diff.

To make sure it all went well, you want to test that pushing this new version of RA to rustc via josh (a) works, and (b) round-trips, i.e. fetching that indeed yields the new RA master you constructed. It's also worth opening a rustc PR for the push, again just to sanity-check things by looking at the new commits and the diff. If anything seems odd, stop and investigate.

The josh parts of the ./miri script contain the lessons we learned so far for how to best use josh. I would suggest you use a script for that as well. Note that we are using the fact that Miri already has a file that tracks the rustc git commit to use for CI; we now define that this file always contains the last rustc git ID we pulled via josh -- this helps a lot with josh pushes, because it means we can base them off of that, rather than off of rustc master, which makes josh's life a lot easier.

Also I think it is a bad idea to have pull and push syncs that race: at any point in time, there should either be an open PR in the RA repo, waiting to merge the latest rustc-pull, or an open PR in the rustc repo, waiting to merge the latest rustc-push. I have not tried what happens when these happen in parallel, but it seems like trouble worth avoiding. ;) In fact what I usually do is that I do a pull immediately before each push. IOW, when I push, the commit I am pushing is a just-merged rustc-pull. pushing is the much harder less well-defined task for josh, so this ensures that that has the highest chance of succeeding. I do not know if it is strictly required to be so careful, but it seems to help avoid josh-project/josh#998 and also we had 2 force-pushes in Miri recently and I'd rather avoid having more. ;) (So this is basically the opposite of what @bjorn3 said about subtree -- with josh, you want to pull immediately before you push, but I don't think you need to immediately pull after you pushed.)

(Where https://github.com/rust-lang/rust/commits/a63222cd240d9b5405826783603f3b391c90885d is the first commit in rust-lang/rust where the rust-analyzer subtree history begins — not 100% sure that's right)

Nope it's wrong, you want the last (most recent) subtree commit.

Passing --allow-unrelated-histories made the merge succeed

If you needed that flag it means the roundtrip failed, so something went wrong. (Not surprising given the wrong filter.)

@RalfJung
Copy link
Member

RalfJung commented Nov 22, 2022

Oh I should also say that I consider josh to still be on probation in Miri. We had some annoying trouble last week, after which we updated our scripts and a josh bug got fixed and hopefully that is dealt with now. But if this happens again we'll probably give up on trying to sync history, and do something home-brew that just tries to get the file contents back and forth.

If you wait a month I can tell you more, but at this point I cannot yet wholeheartedly recommend switching to josh. Once you merge any of the josh-produced history, I am not sure if switching back to git subtree is possible. In Miri, git subtree just doesn't work so we went with josh for lack of alternatives.

So it depends on how fed up you are with git subtree -- if switching to a home-brew hack in case josh turns out to not work well enough is okay for you, go ahead. If you'd rather stick to git subtree than risk having to stop syncing history then I suggest you wait a bit and see how things go in Miri.

@fasterthanlime
Copy link
Contributor

@RalfJung thanks for the thoughtful response: what I'm getting from this is "don't switch to josh yet because it can lock us out of git-subtree".

My only remaining question is: if we do these cherry-picks, can we still use git-subtree later or are we forever locked into doing these manual cherry-picks (unless we're willing to force-push rust-lang/rust-analyzer?)

If not, then apologies for wasting everyone's time and let's move forward with the cherry-picking.

@RalfJung
Copy link
Member

RalfJung commented Nov 23, 2022

I know nothing about git subtree so I can't help with that question.

If this was josh, then I think cherry-picks would lead to annoying conflicts on the next rustc-push and to these commits being duplicated, but the situation should stabilize afterwards.

@fasterthanlime
Copy link
Contributor

fasterthanlime commented Nov 25, 2022

Update: I'm trying something locally with some external help. Please don't merge this today (but if I don't report back before monday, feel free).

Edit: I'm cautiously optimistic, will open PR when done.

Edit 2: whoomp there it is: #13676

@Veykril
Copy link
Member

Veykril commented Nov 25, 2022

Closing in favor of #13676

@Veykril Veykril closed this Nov 25, 2022
bors added a commit that referenced this pull request Nov 25, 2022
Mega-sync from `rust-lang/rust`

This essentially implements `@oli-obk's` suggestion here #13459 (comment), with `@eddyb's` help.

This PR is equivalent to 14 syncs (back and forth) between `rust-lang/rust` and `rust-lang/rust-analyzer`.

Working from this list (from bottom to top):

```
(x) a2a1d99 ⬆️ rust-analyzer
(x) 79923c3 ⬆️ rust-analyzer
(x) c60b1f6 ⬆️ rust-analyzer
(x) 8807fc4 ⬆️ rust-analyzer
(x) a99a48e ⬆️ rust-analyzer
(x) 4f55ebb ⬆️ rust-analyzer
(x) f5fde4d ⬆️ rust-analyzer
(x) 459bbb4 ⬆️ rust-analyzer
(x) 65e1dc4 ⬆️ rust-analyzer
(x) 3e358a6 ⬆️ rust-analyzer
(x) 31519bb ⬆️ rust-analyzer
(x) 8231fee ⬆️ rust-analyzer
(x) 22c8c9c ⬆️ rust-analyzer
(x) 9d2cb42 ⬆️ rust-analyzer
```

(This listed was assembled by doing a `git subtree push`, which made a branch, and looking at the new commits in that branch, picking only those that were `⬆️ rust-analyzer` commits)

We used the following commands to simulate merges in both directions:

```shell
TO_MERGE=22c8c9c40 # taken from the list above, bottom to top
git merge --no-edit --no-ff $TO_MERGE
git merge --no-edit --no-ff $(git -C ../rust log --pretty=format:'%cN | %s | %ad => %P' | rg -m1 -F "$(git show --no-patch --pretty=format:%ad $TO_MERGE)" | tee /dev/stderr | rg '.* => \S+ (\S+)$' --replace '$1')
```

We encountered no merge conflicts that Git wasn't able to solve by doing it this way.

Here's what the commit graph looks like (as shown in the Git Lens VSCode extension):

<img width="1345" alt="image" src="https://user-images.githubusercontent.com/7998310/203984523-7c1a690a-8224-416c-8015-ed6e49667066.png">

This PR closes #13459

## Does this unbreak `rust->ra` syncs?

Yes, here's how we tried:

In `rust-analyzer`:

  * check out `subtree-fix` (this PR's branch)
  * make a new branch off of it: `git checkout -b subtree-fix-merge-test`
  * simulate this PR getting merged with `git merge master`

In `rust`:

  * pull latest master
  * make a new branch: `git checkout -b test-change`
  * mess with rust-analyzer (I added a comment to `src/tools/rust-analyzer/Cargo.toml`)
  * commit
  * run `git subtree push -P src/tools/rust-analyzer ra-local final-sync` (this follows the [Clippy sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html))

This created a `final-sync` branch in `rust-analyzer`.

In `rust-analyzer`:

  * `git merge --no-ff final-sync` (this follows the [Clippy sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html))

Now `git log` in `rust-analyzer` shows this:

```
commit 460128387e46ddfc2b95921b2d7f6e913a3d2b9f (HEAD -> subtree-fix-merge-test)
Merge: 0513fc02a 9ce6a734f
Author: Amos Wenger <[email protected]>
Date:   Fri Nov 25 13:28:24 2022 +0100

    Merge branch 'final-sync' into subtree-fix-merge-test

commit 0513fc02a08ea9de952983624bd0a00e98044b36
Merge: 38c98d1 6918009
Author: Amos Wenger <[email protected]>
Date:   Fri Nov 25 13:28:02 2022 +0100

    Merge branch 'master' into subtree-fix-merge-test

commit 9ce6a734f37ef8e53689f1c6f427a9efafe846bd (final-sync)
Author: Amos Wenger <[email protected]>
Date:   Fri Nov 25 13:26:26 2022 +0100

    Mess with rust-analyzer just for fun
```

And `git diff 0513fc02a08ea9de952983624bd0a00e98044b36` shows this:

```patch
diff --git a/Cargo.toml b/Cargo.toml
index 286ef1e7d..c9e24cd19 100644
--- a/Cargo.toml
+++ b/Cargo.toml
`@@` -32,3 +32,5 `@@` debug = 0
 # ungrammar = { path = "../ungrammar" }

 # salsa = { path = "../salsa" }
+
+# lol, hi
```

## Does this unbreak `ra->rust` syncs?

Yes, here's how we tried.

From `rust`:

  * `git checkout -b sync-from-ra`
  * `git subtree pull -P src/tools/rust-analyzer ra-local subtree-fix-merge-test` (this is adapted from the [Clippy sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html#performing-the-sync-from-clippy-to-rust-langrust), you would normally use `ra-upstream master` but we're simulating things here)

A commit editor pops up, there was no merge conflicts.

## How do we prevent this from happening again?

Like `@bjorn3` said in #13459 (comment)

> Whenever syncing from rust-analyzer -> rust you have to immediately sync the merge commit from rust -> rust-analyzer to prevent merge conflicts in the future.

But if we get it wrong again, at least now we have a not-so-painful way to fix it.
@lnicola lnicola deleted the sync-from-rust-2 branch February 11, 2023 15:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
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.

9 participants