Change:
let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| { ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id())) }); <ins> // N.b. principal, projections, auto traits // FIXME: This is actually wrong with multiple principals in regards to symbol mangling </ins> let mut v = regular_trait_predicates <del> .chain(auto_trait_predicates) </del> .chain( existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)), ) <ins> .chain(auto_trait_predicates) </ins> .collect::<SmallVec<[_; 8]>>(); v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder())); v.dedup();

Discussion:
For program below, mangled symbol doesn't match specification nor can it be demangled with rustfilt or c++filt (with rust v0 support): <details<summaryPartial derivation</summary</details<!-- TRIAGEBOTSTART --<!-- TRIAGEBOTASSIGNSTART --<!-- TRIAGEBOTASSIGNDATASTARTTRIAGEBOTASSIGNDATAEND --<!-- TRIAGEBOTASSIGNEND --<!-- TRIAGEBOTEND --
cc
The mangling was changed in cc
So, I'm not familiar at all with this (in fact, I didn't even realize we had a spec for symbol mangling until I saw this). But let's see. I'm just looking at It seems like where we expect the we instead next have which is a . didn't change that (essentially the mangling of at all). Did you actually bisect to or is that a guess?
Oh, I see what's happening, I think
I guess we're lowering to whereas it was before. This is a bit interesting, because the (slightly desugared) really is only one level of binder. But we could imagine something like (which is completely valid). This gets lowered into I have to think about this. The mangling is very much of the non-lowered version. There is an easy fix here: just don't print the binders of . This assumes that we always print the projections immediately after the relevant trait ref (but that assumption is already made). I am actually curious if the bound works out correctly. I'm assuming that when that gets lowered we just drop the . But I'm guessing that in mangling we now have an extra . So maybe we need to skip printing binders there too. I may or may not be able to get to this myself in the next couple days, but should be easy enough to fix for anyone interested; I can mentor as needed.
Which is the part of the code that prints the binder? I am potentially interested in implementing this :) claim
It's the call. So, it's not really clean, but you would have to only call that if the inner is a .
There's a single type with multiple bounds, so I would prefer keeping a single binder IMO (tho I can see us having to change the mangling if becomes a thing).

You can basically work around having a different implementation, by having the bound-lifetime anonymizing process work for you. Any 's substs would effectively be required to match the ones of , at least after anonymization, which I believe should be trivially true if replicating the binder happens as a desugaring. cc
So does that mean I need a different approach from I haven't interacted with the trait-solving-related code that much, so I would appreciate if you could give me more detail on how I would implement what you're suggesting :) Alternatively, I could open a PR using 's approach since it seems like it should be very quick to implement, and then you can comment on what part you would like to be different.
I think what is saying roughly lines up with my comment. I think just open a PR with my approach. I imagine this is a "single binder" in the mangling, not in the predicate list. I don't quite follow this. Maybe this referring to multiple bound traits? Lifetimes bound in should always be the same as those bound under , since it's just a desugaring.
Right, sorry for the ambiguity. Sure, but how confident are you some kind of strange interaction can't create something that seems to be out of sync? Anyway, if we check instead of assuming it, it should be fine. This doesn't work, it will keep s outside the binder, and e.g. turn this: into I think you should move the where it was before (i.e. around the loop), but only pass the element of the list, and use for the other ones. I was worried this would mess with the anonymization but that doesn't seem to happen here (instead, mangling just assumes anonymization happened and will ICE if it didn't).
was inside the loop, around a . I think I'll open a PR with jackh726's approach, and then we can talk about some concrete code.