Skip to content

Commit 0daabbe

Browse files
committed
Change to just use first binders and add test
1 parent c34e7c6 commit 0daabbe

File tree

5 files changed

+218
-27
lines changed

5 files changed

+218
-27
lines changed

compiler/rustc_symbol_mangling/src/v0.rs

Lines changed: 47 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -485,38 +485,59 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
485485
mut self,
486486
predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
487487
) -> Result<Self::DynExistential, Self::Error> {
488-
let mut predicate_iter = predicates.iter().peekable();
489-
while let Some(predicate) = predicate_iter.next() {
490-
match predicate.as_ref().skip_binder() {
491-
ty::ExistentialPredicate::Trait(trait_ref) => {
492-
self = self.in_binder(&predicate, |mut cx, _predicate| {
488+
// Okay, so this is a bit tricky. Imagine we have a trait object like
489+
// `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the
490+
// output looks really close to the syntax, where the `Bar = &'a ()` bit
491+
// is under the same binders (`['a]`) as the `Foo<'a>` bit. However, we
492+
// actually desugar these into two separate `ExistentialPredicate`s. We
493+
// can't enter/exit the "binder scope" twice though, because then we
494+
// would mangle the binders twice. (Also, side note, we merging these
495+
// two is kind of difficult, because of potential HRTBs in the Projection
496+
// predicate.)
497+
//
498+
// Also worth mentioning: imagine that we instead had
499+
// `dyn for<'a> Foo<'a, Bar = &'a ()> + Send`. In this case, `Send` is
500+
// under the same binders as `Foo`. Currently, this doesn't matter,
501+
// because only *auto traits* are allowed other than the principal trait
502+
// and all auto traits don't have any generics. Two things could
503+
// make this not an "okay" mangling:
504+
// 1) Instead of mangling only *used*
505+
// bound vars, we want to mangle *all* bound vars (`for<'b> Send` is a
506+
// valid trait predicate);
507+
// 2) We allow multiple "principal" traits in the future, or at least
508+
// allow in any form another trait predicate that can take generics.
509+
//
510+
// Here we assume that predicates have the following structure:
511+
// [<Trait> [{<Projection>}]] [{<Auto>}]
512+
// Since any predicates after the first one shouldn't change the binders,
513+
// just put them all in the binders of the first.
514+
self = self.in_binder(&predicates[0], |mut cx, _| {
515+
for predicate in predicates.iter() {
516+
// It would be nice to be able to validate bound vars here, but
517+
// projections can actually include bound vars from super traits
518+
// because of HRTBs (only in the `Self` type). Also, auto traits
519+
// could have different bound vars *anyways*.
520+
match predicate.as_ref().skip_binder() {
521+
ty::ExistentialPredicate::Trait(trait_ref) => {
493522
// Use a type that can't appear in defaults of type parameters.
494523
let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0));
495524
let trait_ref = trait_ref.with_self_ty(cx.tcx, dummy_self);
496525
cx = cx.print_def_path(trait_ref.def_id, trait_ref.substs)?;
497-
while let Some(projection_pred) = predicate_iter.next_if(|p| {
498-
matches!(p.skip_binder(), ty::ExistentialPredicate::Projection(_))
499-
}) {
500-
let projection = match projection_pred.skip_binder() {
501-
ty::ExistentialPredicate::Projection(projection) => projection,
502-
_ => unreachable!(),
503-
};
504-
let name = cx.tcx.associated_item(projection.item_def_id).ident;
505-
cx.push("p");
506-
cx.push_ident(&name.as_str());
507-
cx = projection.ty.print(cx)?;
508-
}
509-
Ok(cx)
510-
})?;
511-
}
512-
ty::ExistentialPredicate::Projection(_) => {
513-
unreachable!("handled in trait predicate arm")
514-
}
515-
ty::ExistentialPredicate::AutoTrait(def_id) => {
516-
self = self.print_def_path(*def_id, &[])?;
526+
}
527+
ty::ExistentialPredicate::Projection(projection) => {
528+
let name = cx.tcx.associated_item(projection.item_def_id).ident;
529+
cx.push("p");
530+
cx.push_ident(&name.as_str());
531+
cx = projection.ty.print(cx)?;
532+
}
533+
ty::ExistentialPredicate::AutoTrait(def_id) => {
534+
cx = cx.print_def_path(*def_id, &[])?;
535+
}
517536
}
518537
}
519-
}
538+
Ok(cx)
539+
})?;
540+
520541
self.push("E");
521542
Ok(self)
522543
}

compiler/rustc_typeck/src/astconv/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1386,11 +1386,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
13861386
let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
13871387
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
13881388
});
1389+
// N.b. principal, projections, auto traits
1390+
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
13891391
let mut v = regular_trait_predicates
1390-
.chain(auto_trait_predicates)
13911392
.chain(
13921393
existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
13931394
)
1395+
.chain(auto_trait_predicates)
13941396
.collect::<SmallVec<[_; 8]>>();
13951397
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
13961398
v.dedup();
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error: symbol-name(_ZN136_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u20$as$u20$trait_objects..Bar$GT$6method17h1e14a5f2d365272fE)
2+
--> $DIR/trait-objects.rs:15:5
3+
|
4+
LL | #[rustc_symbol_name]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
7+
error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = () as trait_objects::Bar>::method::h1e14a5f2d365272f)
8+
--> $DIR/trait-objects.rs:15:5
9+
|
10+
LL | #[rustc_symbol_name]
11+
| ^^^^^^^^^^^^^^^^^^^^
12+
13+
error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = () as trait_objects::Bar>::method)
14+
--> $DIR/trait-objects.rs:15:5
15+
|
16+
LL | #[rustc_symbol_name]
17+
| ^^^^^^^^^^^^^^^^^^^^
18+
19+
error: symbol-name(_ZN159_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u2b$core..marker..Send$u20$as$u20$trait_objects..Foo$GT$6method17he7a07961c9aaa367E)
20+
--> $DIR/trait-objects.rs:30:5
21+
|
22+
LL | #[rustc_symbol_name]
23+
| ^^^^^^^^^^^^^^^^^^^^
24+
25+
error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Foo>::method::he7a07961c9aaa367)
26+
--> $DIR/trait-objects.rs:30:5
27+
|
28+
LL | #[rustc_symbol_name]
29+
| ^^^^^^^^^^^^^^^^^^^^
30+
31+
error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Foo>::method)
32+
--> $DIR/trait-objects.rs:30:5
33+
|
34+
LL | #[rustc_symbol_name]
35+
| ^^^^^^^^^^^^^^^^^^^^
36+
37+
error: symbol-name(_ZN159_$LT$$RF$dyn$u20$core..ops..function..FnMut$LT$$LP$$RF$u8$C$$RP$$GT$$u2b$Output$u20$$u3d$$u20$$LP$$RP$$u2b$core..marker..Send$u20$as$u20$trait_objects..Baz$GT$6method17ha53e6f99bf033f0bE)
38+
--> $DIR/trait-objects.rs:45:5
39+
|
40+
LL | #[rustc_symbol_name]
41+
| ^^^^^^^^^^^^^^^^^^^^
42+
43+
error: demangling(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Baz>::method::ha53e6f99bf033f0b)
44+
--> $DIR/trait-objects.rs:45:5
45+
|
46+
LL | #[rustc_symbol_name]
47+
| ^^^^^^^^^^^^^^^^^^^^
48+
49+
error: demangling-alt(<&dyn core::ops::function::FnMut<(&u8,)>+Output = ()+core::marker::Send as trait_objects::Baz>::method)
50+
--> $DIR/trait-objects.rs:45:5
51+
|
52+
LL | #[rustc_symbol_name]
53+
| ^^^^^^^^^^^^^^^^^^^^
54+
55+
error: aborting due to 9 previous errors
56+
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
// Ensure that trait objects don't include more than one binder. See #83611
2+
3+
// build-fail
4+
// revisions: legacy v0
5+
//[legacy]compile-flags: -Z symbol-mangling-version=legacy
6+
//[v0]compile-flags: -Z symbol-mangling-version=v0
7+
8+
#![feature(rustc_attrs)]
9+
10+
trait Bar {
11+
fn method(&self) {}
12+
}
13+
14+
impl Bar for &dyn FnMut(&u8) {
15+
#[rustc_symbol_name]
16+
//[legacy]~^ ERROR symbol-name
17+
//[legacy]~| ERROR demangling
18+
//[legacy]~| ERROR demangling-alt
19+
//[v0]~^^^^ ERROR symbol-name
20+
//[v0]~| ERROR demangling
21+
//[v0]~| ERROR demangling-alt
22+
fn method(&self) {}
23+
}
24+
25+
trait Foo {
26+
fn method(&self) {}
27+
}
28+
29+
impl Foo for &(dyn FnMut(&u8) + for<'b> Send) {
30+
#[rustc_symbol_name]
31+
//[legacy]~^ ERROR symbol-name
32+
//[legacy]~| ERROR demangling
33+
//[legacy]~| ERROR demangling-alt
34+
//[v0]~^^^^ ERROR symbol-name
35+
//[v0]~| ERROR demangling
36+
//[v0]~| ERROR demangling-alt
37+
fn method(&self) {}
38+
}
39+
40+
trait Baz {
41+
fn method(&self) {}
42+
}
43+
44+
impl Baz for &(dyn for<'b> Send + FnMut(&u8)) {
45+
#[rustc_symbol_name]
46+
//[legacy]~^ ERROR symbol-name
47+
//[legacy]~| ERROR demangling
48+
//[legacy]~| ERROR demangling-alt
49+
//[v0]~^^^^ ERROR symbol-name
50+
//[v0]~| ERROR demangling
51+
//[v0]~| ERROR demangling-alt
52+
fn method(&self) {}
53+
}
54+
55+
fn main() {
56+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
error: symbol-name(_RNvXCs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB2_3Bar6method)
2+
--> $DIR/trait-objects.rs:15:5
3+
|
4+
LL | #[rustc_symbol_name]
5+
| ^^^^^^^^^^^^^^^^^^^^
6+
7+
error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
8+
--> $DIR/trait-objects.rs:15:5
9+
|
10+
LL | #[rustc_symbol_name]
11+
| ^^^^^^^^^^^^^^^^^^^^
12+
13+
error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method)
14+
--> $DIR/trait-objects.rs:15:5
15+
|
16+
LL | #[rustc_symbol_name]
17+
| ^^^^^^^^^^^^^^^^^^^^
18+
19+
error: symbol-name(_RNvXs_Cs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBI_6marker4SendEL_NtB4_3Foo6method)
20+
--> $DIR/trait-objects.rs:30:5
21+
|
22+
LL | #[rustc_symbol_name]
23+
| ^^^^^^^^^^^^^^^^^^^^
24+
25+
error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> + core[3b0e14d6e1ad42d0]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
26+
--> $DIR/trait-objects.rs:30:5
27+
|
28+
LL | #[rustc_symbol_name]
29+
| ^^^^^^^^^^^^^^^^^^^^
30+
31+
error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method)
32+
--> $DIR/trait-objects.rs:30:5
33+
|
34+
LL | #[rustc_symbol_name]
35+
| ^^^^^^^^^^^^^^^^^^^^
36+
37+
error: symbol-name(_RNvXs0_Cs21hi0yVfW1J_13trait_objectsRDG_INtNtNtCs54lBhuwykzk_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBJ_6marker4SendEL_NtB5_3Baz6method)
38+
--> $DIR/trait-objects.rs:45:5
39+
|
40+
LL | #[rustc_symbol_name]
41+
| ^^^^^^^^^^^^^^^^^^^^
42+
43+
error: demangling(<&dyn for<'a> core[3b0e14d6e1ad42d0]::ops::function::FnMut<(&'a u8,), Output = ()> + core[3b0e14d6e1ad42d0]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
44+
--> $DIR/trait-objects.rs:45:5
45+
|
46+
LL | #[rustc_symbol_name]
47+
| ^^^^^^^^^^^^^^^^^^^^
48+
49+
error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method)
50+
--> $DIR/trait-objects.rs:45:5
51+
|
52+
LL | #[rustc_symbol_name]
53+
| ^^^^^^^^^^^^^^^^^^^^
54+
55+
error: aborting due to 9 previous errors
56+

0 commit comments

Comments
 (0)