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

Fix v0 symbol mangling bug #83767

Merged
merged 3 commits into from
May 19, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -1386,11 +1386,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