diff options
| author | bors <bors@rust-lang.org> | 2018-10-27 19:29:35 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2018-10-27 19:29:35 +0000 |
| commit | cae6efc37d70ab7d353e6ab9ce229d59a65ed643 (patch) | |
| tree | 755deb56e86b2436a04ccbab70b3506608e36075 /src/librustc_codegen_utils | |
| parent | b3b87609713887a27ebd07557af14e4aa57771f3 (diff) | |
| parent | 2f7ea4a8725d433db4f34fca87eb7f61afb7ef9a (diff) | |
| download | rust-cae6efc37d70ab7d353e6ab9ce229d59a65ed643.tar.gz rust-cae6efc37d70ab7d353e6ab9ce229d59a65ed643.zip | |
Auto merge of #54183 - qnighy:by-value-object-safety, r=oli-obk
Implement by-value object safety
This PR implements **by-value object safety**, which is part of unsized rvalues #48055. That means, with `#![feature(unsized_locals)]`, you can call a method `fn foo(self, ...)` on trait objects. One aim of this is to enable `Box<FnOnce>` in the near future.
The difficulty here is this: when constructing a vtable for a trait `Foo`, we can't just put the function `<T as Foo>::foo` into the table. If `T` is no larger than `usize`, `self` is usually passed directly. However, as the caller of the vtable doesn't know the concrete `Self` type, we want a variant of `<T as Foo>::foo` where `self` is always passed by reference.
Therefore, when the compiler encounters such a method to be generated as a vtable entry, it produces a newly introduced instance called `InstanceDef::VtableShim(def_id)` (that wraps the original instance). the shim just derefs the receiver and calls the original method. We give different symbol names for the shims by appending `::{{vtable-shim}}` to the symbol path (and also adding vtable-shimness as an ingredient to the symbol hash).
r? @eddyb
Diffstat (limited to 'src/librustc_codegen_utils')
| -rw-r--r-- | src/librustc_codegen_utils/symbol_names.rs | 13 |
1 files changed, 12 insertions, 1 deletions
diff --git a/src/librustc_codegen_utils/symbol_names.rs b/src/librustc_codegen_utils/symbol_names.rs index c1e80234a77..0d95b0c7bbc 100644 --- a/src/librustc_codegen_utils/symbol_names.rs +++ b/src/librustc_codegen_utils/symbol_names.rs @@ -114,6 +114,7 @@ use rustc_mir::monomorphize::Instance; use syntax_pos::symbol::Symbol; use std::fmt::Write; +use std::mem::discriminant; pub fn provide(providers: &mut Providers) { *providers = Providers { @@ -219,6 +220,10 @@ fn get_symbol_hash<'a, 'tcx>( .hash_stable(&mut hcx, &mut hasher); (&tcx.crate_disambiguator(instantiating_crate)).hash_stable(&mut hcx, &mut hasher); } + + // We want to avoid accidental collision between different types of instances. + // Especially, VtableShim may overlap with its original instance without this. + discriminant(&instance.def).hash_stable(&mut hcx, &mut hasher); }); // 64 bits should be enough to avoid collisions. @@ -322,7 +327,13 @@ fn compute_symbol_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, instance: Instance let hash = get_symbol_hash(tcx, def_id, instance, instance_ty, substs); - SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)).finish(hash) + let mut buf = SymbolPathBuffer::from_interned(tcx.def_symbol_name(def_id)); + + if instance.is_vtable_shim() { + buf.push("{{vtable-shim}}"); + } + + buf.finish(hash) } // Follow C++ namespace-mangling style, see |
