Skip to content

Commit

Permalink
Rollup merge of #83767 - camelid:mangle-v0-fix, r=nikomatsakis
Browse files Browse the repository at this point in the history
Fix v0 symbol mangling bug

Fixes #83611.

r? ``@jackh726``
  • Loading branch information
jackh726 committed May 19, 2021
2 parents 3c99dcd + 8345908 commit 809e975
Show file tree
Hide file tree
Showing 4 changed files with 144 additions and 7 deletions.
43 changes: 37 additions & 6 deletions compiler/rustc_symbol_mangling/src/v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -485,9 +485,39 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
mut self,
predicates: &'tcx ty::List<ty::Binder<'tcx, ty::ExistentialPredicate<'tcx>>>,
) -> Result<Self::DynExistential, Self::Error> {
for predicate in predicates {
self = self.in_binder(&predicate, |mut cx, predicate| {
match predicate {
// Okay, so this is a bit tricky. Imagine we have a trait object like
// `dyn for<'a> Foo<'a, Bar = &'a ()>`. When we mangle this, the
// output looks really close to the syntax, where the `Bar = &'a ()` bit
// is under the same binders (`['a]`) as the `Foo<'a>` bit. However, we
// actually desugar these into two separate `ExistentialPredicate`s. We
// can't enter/exit the "binder scope" twice though, because then we
// would mangle the binders twice. (Also, side note, we merging these
// two is kind of difficult, because of potential HRTBs in the Projection
// predicate.)
//
// Also worth mentioning: imagine that we instead had
// `dyn for<'a> Foo<'a, Bar = &'a ()> + Send`. In this case, `Send` is
// under the same binders as `Foo`. Currently, this doesn't matter,
// because only *auto traits* are allowed other than the principal trait
// and all auto traits don't have any generics. Two things could
// make this not an "okay" mangling:
// 1) Instead of mangling only *used*
// bound vars, we want to mangle *all* bound vars (`for<'b> Send` is a
// valid trait predicate);
// 2) We allow multiple "principal" traits in the future, or at least
// allow in any form another trait predicate that can take generics.
//
// Here we assume that predicates have the following structure:
// [<Trait> [{<Projection>}]] [{<Auto>}]
// Since any predicates after the first one shouldn't change the binders,
// just put them all in the binders of the first.
self = self.in_binder(&predicates[0], |mut cx, _| {
for predicate in predicates.iter() {
// It would be nice to be able to validate bound vars here, but
// projections can actually include bound vars from super traits
// because of HRTBs (only in the `Self` type). Also, auto traits
// could have different bound vars *anyways*.
match predicate.as_ref().skip_binder() {
ty::ExistentialPredicate::Trait(trait_ref) => {
// Use a type that can't appear in defaults of type parameters.
let dummy_self = cx.tcx.mk_ty_infer(ty::FreshTy(0));
Expand All @@ -504,9 +534,10 @@ impl Printer<'tcx> for SymbolMangler<'tcx> {
cx = cx.print_def_path(*def_id, &[])?;
}
}
Ok(cx)
})?;
}
}
Ok(cx)
})?;

self.push("E");
Ok(self)
}
Expand Down
4 changes: 3 additions & 1 deletion compiler/rustc_typeck/src/astconv/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1394,11 +1394,13 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
let auto_trait_predicates = auto_traits.into_iter().map(|trait_ref| {
ty::Binder::dummy(ty::ExistentialPredicate::AutoTrait(trait_ref.trait_ref().def_id()))
});
// N.b. principal, projections, auto traits
// FIXME: This is actually wrong with multiple principals in regards to symbol mangling
let mut v = regular_trait_predicates
.chain(auto_trait_predicates)
.chain(
existential_projections.map(|x| x.map_bound(ty::ExistentialPredicate::Projection)),
)
.chain(auto_trait_predicates)
.collect::<SmallVec<[_; 8]>>();
v.sort_by(|a, b| a.skip_binder().stable_cmp(tcx, &b.skip_binder()));
v.dedup();
Expand Down
48 changes: 48 additions & 0 deletions src/test/ui/symbol-names/trait-objects.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// Ensure that trait objects don't include more than one binder. See #83611

// build-fail
// revisions: v0
//[v0]compile-flags: -Z symbol-mangling-version=v0
//[v0]normalize-stderr-test: "Cs.*?_" -> "CRATE_HASH"
//[v0]normalize-stderr-test: "core\[.*?\]" -> "core[HASH]"

#![feature(rustc_attrs)]

trait Bar {
fn method(&self) {}
}

impl Bar for &dyn FnMut(&u8) {
#[rustc_symbol_name]
//[v0]~^ ERROR symbol-name
//[v0]~| ERROR demangling
//[v0]~| ERROR demangling-alt
fn method(&self) {}
}

trait Foo {
fn method(&self) {}
}

impl Foo for &(dyn FnMut(&u8) + for<'b> Send) {
#[rustc_symbol_name]
//[v0]~^ ERROR symbol-name
//[v0]~| ERROR demangling
//[v0]~| ERROR demangling-alt
fn method(&self) {}
}

trait Baz {
fn method(&self) {}
}

impl Baz for &(dyn for<'b> Send + FnMut(&u8)) {
#[rustc_symbol_name]
//[v0]~^ ERROR symbol-name
//[v0]~| ERROR demangling
//[v0]~| ERROR demangling-alt
fn method(&self) {}
}

fn main() {
}
56 changes: 56 additions & 0 deletions src/test/ui/symbol-names/trait-objects.v0.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
error: symbol-name(_RNvXCRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB2_3Bar6method)
--> $DIR/trait-objects.rs:16:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[17891616a171812d]::Bar>::method)
--> $DIR/trait-objects.rs:16:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method)
--> $DIR/trait-objects.rs:16:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: symbol-name(_RNvXs_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBI_6marker4SendEL_NtB4_3Foo6method)
--> $DIR/trait-objects.rs:28:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Foo>::method)
--> $DIR/trait-objects.rs:28:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method)
--> $DIR/trait-objects.rs:28:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: symbol-name(_RNvXs0_CRATE_HASH13trait_objectsRDG_INtNtNtCRATE_HASH4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtBJ_6marker4SendEL_NtB5_3Baz6method)
--> $DIR/trait-objects.rs:40:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[17891616a171812d]::Baz>::method)
--> $DIR/trait-objects.rs:40:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method)
--> $DIR/trait-objects.rs:40:5
|
LL | #[rustc_symbol_name]
| ^^^^^^^^^^^^^^^^^^^^

error: aborting due to 9 previous errors

0 comments on commit 809e975

Please sign in to comment.