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

v0 mangled symbol doesn't match specification nor can it be demangled with rustfilt or c++filt #83611

Closed
tmiasko opened this issue Mar 28, 2021 · 12 comments · Fixed by #83767
Closed
Assignees
Labels
C-bug Category: This is a bug. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. requires-nightly This issue requires a nightly compiler in some way.

Comments

@tmiasko
Copy link
Contributor

tmiasko commented Mar 28, 2021

For program below, mangled symbol doesn't match specification nor can it be demangled with rustfilt or c++filt (with rust v0 support):

pub fn f<T>() {}

pub fn g() {
    f::<&dyn FnMut(&u8)>();
}
$  rustc --crate-type=lib -Zsymbol-mangling-version=v0 a.rs && nm ./liba.rlib | c++filt 
a.a.3a1fbbbh-cgu.0.rcgu.o:
0000000000000000 T _RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEEG_p6OutputuEL_EB2_
0000000000000000 T a[cdfa367c26312547]::g
Partial derivation
"" <symbol-name>
"_R" [<decimal-number>] <path> [<instantiating-crate>]
"_R" <path> [<instantiating-crate>]
"_RI" <path> {<generic-arg>} "E" [<instantiating-crate>]
"_RIN" <namespace> <path> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINv" <path> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvC" <identifier> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvC" [<disambiguator>] <undisambiguated-identifier> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCs" <base-62-number> <undisambiguated-identifier> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_" <undisambiguated-identifier> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_" <decimal-number> ["_"] <bytes> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1" ["_"] <bytes> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1" <bytes> <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a" <identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a" [<disambiguator>] <undisambiguated-identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a" <undisambiguated-identifier> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a" <decimal-number> ["_"] <bytes> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1" ["_"] <bytes> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1" <bytes> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1f" {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1f" <type> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fR" [<lifetime>] <type> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fR" <type> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRD" <dyn-bounds> <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRD" <binder> {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG" <base-62-number> {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_" {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_" <path> {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_I" <path> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_IN" <namespace> <path> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INt" <path> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtN" <namespace> <path> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNt" <path> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtN" <namespace> <path> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNt" <path> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtC" <identifier> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtC" [<disambiguator>] <undisambiguated-identifier> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs" <base-62-number> <undisambiguated-identifier> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_" <undisambiguated-identifier> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_" <decimal-number> ["_"] <bytes> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4" ["_"] <bytes> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4" <bytes> <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core" <identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core" [<disambiguator>] <undisambiguated-identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core" <undisambiguated-identifier> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core" <decimal-number> ["_"] <bytes> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3" ["_"] <bytes> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3" <bytes> <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops" <identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops" [<disambiguator>] <undisambiguated-identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops" <undisambiguated-identifier> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops" <decimal-number> ["_"] <bytes> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8" ["_"] <bytes> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8" <bytes> <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function" <identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function" [<disambiguator>] <undisambiguated-identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function" <undisambiguated-identifier> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function" <decimal-number> ["_"] <bytes> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5" ["_"] <bytes> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5" <bytes> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMut" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMut" <type> {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutT" {<type>} "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTR" [<lifetime>] <type> {<type>} "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTR" <base-62-number> <type> {<type>} "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_" <type> {<type>} "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_" <basic-type> {<type>} "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_h" {<type>} "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_h" "E" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hE" {<generic-arg>} "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hE" "E" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEE" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEE" {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEE" <path> {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEEG_p6OutputuEL_EB2_" ?
@tmiasko tmiasko added the C-bug Category: This is a bug. label Mar 28, 2021
@tmiasko
Copy link
Contributor Author

tmiasko commented Mar 28, 2021

cc @michaelwoerister @eddyb

@tmiasko
Copy link
Contributor Author

tmiasko commented Mar 28, 2021

The mangling was changed in #79945 cc @jackh726

@jackh726
Copy link
Member

jackh726 commented Mar 28, 2021

🙄 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

"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEE" {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEE" {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEE" <path> {<dyn-trait-assoc-binding>} {<dyn-trait>} "E" <lifetime> {<generic-arg>} "E" [<instantiating-crate>]
"_RINvCshGpAVYOtgW1_1a1fRDG_INtNtNtCs4RZURTQcbNt_4core3ops8function5FnMutTRL0_hEEG_p6OutputuEL_EB2_" ?

It seems like where we expect the {<dyn-trait-assoc-binding>} we instead next have G_ which is a Binder. #79945 didn't change that (essentially the mangling of ExistentialPredicate::Projection at all).

Did you actually bisect to #79945 or is that a guess?

@jackh726
Copy link
Member

Oh, I see what's happening, I think

@jackh726
Copy link
Member

I guess we're lowering dyn FnMut(&u8) to

[
  for<> ExistentialProjection::Trait(Self: FnMut),
  for<> ExistentialProjection::Projection(<Self as FnMut>::Output = &u8),
]

whereas it was

for<> [
  ExistentialProjection::Trait(Self: FnMut),
  ExistentialProjection::Projection(<Self as FnMut>::Output = &u8)
]

before.

This is a bit interesting, because the (slightly desugared) FnMut<Output = &u8> really is only one level of binder. But we could imagine something like &(dyn for<'a> Foo<'a, As=()> + for<'b> Send) (which is completely valid). This gets lowered into

[
  for<'a> ExistentialProjection::Trait(Self: Foo<'a>),
  for<'a> ExistentialProjection::Projection(<Self as Foo<'a>>::As = (),
  for<'b> ExistentialProjection::Trait(Self: Send)
]

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 ExistentialPredicate::Projection here. 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 for<'a> Send bound works out correctly. I'm assuming that when that gets lowered we just drop the for<'a>. But I'm guessing that in mangling we now have an extra G.... 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.

@jackh726 jackh726 added E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. labels Mar 28, 2021
@camelid camelid added the requires-nightly This issue requires a nightly compiler in some way. label Mar 28, 2021
@camelid
Copy link
Member

camelid commented Mar 29, 2021

Which is the part of the code that prints the binder?

ty::ExistentialPredicate::Projection(projection) => {
let name = cx.tcx.associated_item(projection.item_def_id).ident;
cx.push("p");
cx.push_ident(&name.as_str());
cx = projection.ty.print(cx)?;
}

I am potentially interested in implementing this :)

@rustbot claim

@jackh726
Copy link
Member

It's the in_binder call. So, it's not really clean, but you would have to only call that if the inner ExistentialPredicate is a Trait.

@eddyb
Copy link
Member

eddyb commented Mar 29, 2021

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 dyn for<'a> Foo<'a, for<'b> Assoc<'b> = Bar<'a, 'b>> becomes a thing).

You can basically work around having a different implementation, by having the bound-lifetime anonymizing process work for you.

Any ExistentialProjection::Projection's substs would effectively be required to match the ones of ExistentialProjection::Trait, at least after anonymization, which I believe should be trivially true if replicating the binder happens as a desugaring.

cc @nikomatsakis

@camelid
Copy link
Member

camelid commented Mar 30, 2021

So does that mean I need a different approach from #83611 (comment)? 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 @jackh726'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.

@jackh726
Copy link
Member

I think what @eddyb is saying roughly lines up with my comment. @camelid I think just open a PR with my approach.

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 dyn for<'a> Foo<'a, for<'b> Assoc<'b> = Bar<'a, 'b>> becomes a thing).

I imagine this is a "single binder" in the mangling, not in the predicate list.

You can basically work around having a different implementation, by having the bound-lifetime anonymizing process work for you.

Any ExistentialProjection::Projection's substs would effectively be required to match the ones of ExistentialProjection::Trait, at least after anonymization, which I believe should be trivially true if replicating the binder happens as a desugaring.

I don't quite follow this. Maybe this referring to multiple bound traits? Lifetimes bound in Projection should always be the same as those bound under Trait, since it's just a desugaring.

@eddyb
Copy link
Member

eddyb commented Apr 1, 2021

I imagine this is a "single binder" in the mangling, not in the predicate list.

Right, sorry for the ambiguity.

I don't quite follow this. Maybe this referring to multiple bound traits? Lifetimes bound in Projection should always be the same as those bound under Trait, since it's just a desugaring.

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.

It's the in_binder call. So, it's not really clean, but you would have to only call that if the inner ExistentialPredicate is a Trait.

This doesn't work, it will keep Projections outside the binder, and e.g. turn this:
for<'a> fn(&'a dyn for<'b> FnOnce(&'b T) -> &'b U) -> &'a V
into
for<'a> fn(&'a dyn for<'b> FnOnce(&'b T) -> &'a U) -> &'a V

I think you should move the in_binder where it was before (i.e. around the loop), but only pass the Trait element of the list, and use skip_binder 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).

@camelid
Copy link
Member

camelid commented Apr 2, 2021

I think you should move the in_binder where it was before (i.e. around the loop), but only pass the Trait element of the list, and use skip_binder for the other ones.

in_binder was inside the loop, around a match. I think I'll open a PR with jackh726's approach, and then we can talk about some concrete code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. E-easy Call for participation: Easy difficulty. Experience needed to fix: Not much. Good first issue. E-mentor Call for participation: This issue has a mentor. Use #t-compiler/help on Zulip for discussion. requires-nightly This issue requires a nightly compiler in some way.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants