@@ -91,8 +91,9 @@ use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
9191use rustc:: mir:: mono:: { InstantiationMode , MonoItem } ;
9292use rustc:: session:: config:: SymbolManglingVersion ;
9393use rustc:: ty:: query:: Providers ;
94+ use rustc:: ty:: subst:: SubstsRef ;
9495use rustc:: ty:: { self , Instance , TyCtxt } ;
95- use rustc_hir:: def_id:: LOCAL_CRATE ;
96+ use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
9697use rustc_hir:: Node ;
9798
9899use rustc_span:: symbol:: Symbol ;
@@ -102,15 +103,70 @@ use log::debug;
102103mod legacy;
103104mod v0;
104105
106+ /// This function computes the symbol name for the given `instance` and the
107+ /// given instantiating crate. That is, if you know that instance X is
108+ /// instantiated in crate Y, this is the symbol name this instance would have.
109+ pub fn symbol_name_for_instance_in_crate (
110+ tcx : TyCtxt < ' tcx > ,
111+ instance : Instance < ' tcx > ,
112+ instantiating_crate : CrateNum ,
113+ ) -> String {
114+ compute_symbol_name ( tcx, instance, || instantiating_crate)
115+ }
116+
105117pub fn provide ( providers : & mut Providers < ' _ > ) {
106- * providers = Providers {
107- symbol_name : |tcx , instance| ty :: SymbolName { name : symbol_name ( tcx , instance ) } ,
118+ * providers = Providers { symbol_name : symbol_name_provider , .. * providers } ;
119+ }
108120
109- ..* providers
110- } ;
121+ // The `symbol_name` query provides the symbol name for calling a given
122+ // instance from the local crate. In particular, it will also look up the
123+ // correct symbol name of instances from upstream crates.
124+ fn symbol_name_provider ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> ty:: SymbolName {
125+ let symbol_name = compute_symbol_name ( tcx, instance, || {
126+ // This closure determines the instantiating crate for instances that
127+ // need an instantiating-crate-suffix for their symbol name, in order
128+ // to differentiate between local copies.
129+ //
130+ // For generics we might find re-usable upstream instances. For anything
131+ // else we rely on their being a local copy available.
132+
133+ if is_generic ( instance. substs ) {
134+ let def_id = instance. def_id ( ) ;
135+
136+ if !def_id. is_local ( ) && tcx. sess . opts . share_generics ( ) {
137+ // If we are re-using a monomorphization from another crate,
138+ // we have to compute the symbol hash accordingly.
139+ let upstream_monomorphizations = tcx. upstream_monomorphizations_for ( def_id) ;
140+
141+ upstream_monomorphizations
142+ . and_then ( |monos| monos. get ( & instance. substs ) . cloned ( ) )
143+ // If there is no instance available upstream, there'll be
144+ // one in the current crate.
145+ . unwrap_or ( LOCAL_CRATE )
146+ } else {
147+ // For generic functions defined in the current crate, there
148+ // can be no upstream instances. Also, if we don't share
149+ // generics, we'll instantiate a local copy too.
150+ LOCAL_CRATE
151+ }
152+ } else {
153+ // For non-generic things that need to avoid naming conflicts, we
154+ // always instantiate a copy in the local crate.
155+ LOCAL_CRATE
156+ }
157+ } ) ;
158+
159+ ty:: SymbolName { name : Symbol :: intern ( & symbol_name) }
111160}
112161
113- fn symbol_name ( tcx : TyCtxt < ' tcx > , instance : Instance < ' tcx > ) -> Symbol {
162+ /// Computes the symbol name for the given instance. This function will call
163+ /// `compute_instantiating_crate` if it needs to factor the instantiating crate
164+ /// into the symbol name.
165+ fn compute_symbol_name (
166+ tcx : TyCtxt < ' tcx > ,
167+ instance : Instance < ' tcx > ,
168+ compute_instantiating_crate : impl FnOnce ( ) -> CrateNum ,
169+ ) -> String {
114170 let def_id = instance. def_id ( ) ;
115171 let substs = instance. substs ;
116172
@@ -121,11 +177,11 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
121177 if def_id. is_local ( ) {
122178 if tcx. plugin_registrar_fn ( LOCAL_CRATE ) == Some ( def_id) {
123179 let disambiguator = tcx. sess . local_crate_disambiguator ( ) ;
124- return Symbol :: intern ( & tcx. sess . generate_plugin_registrar_symbol ( disambiguator) ) ;
180+ return tcx. sess . generate_plugin_registrar_symbol ( disambiguator) ;
125181 }
126182 if tcx. proc_macro_decls_static ( LOCAL_CRATE ) == Some ( def_id) {
127183 let disambiguator = tcx. sess . local_crate_disambiguator ( ) ;
128- return Symbol :: intern ( & tcx. sess . generate_proc_macro_decls_symbol ( disambiguator) ) ;
184+ return tcx. sess . generate_proc_macro_decls_symbol ( disambiguator) ;
129185 }
130186 }
131187
@@ -162,29 +218,28 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
162218 || !tcx. wasm_import_module_map ( def_id. krate ) . contains_key ( & def_id)
163219 {
164220 if let Some ( name) = attrs. link_name {
165- return name;
221+ return name. to_string ( ) ;
166222 }
167- return tcx. item_name ( def_id) ;
223+ return tcx. item_name ( def_id) . to_string ( ) ;
168224 }
169225 }
170226
171227 if let Some ( name) = attrs. export_name {
172228 // Use provided name
173- return name;
229+ return name. to_string ( ) ;
174230 }
175231
176232 if attrs. flags . contains ( CodegenFnAttrFlags :: NO_MANGLE ) {
177233 // Don't mangle
178- return tcx. item_name ( def_id) ;
234+ return tcx. item_name ( def_id) . to_string ( ) ;
179235 }
180236
181- let is_generic = substs. non_erasable_generics ( ) . next ( ) . is_some ( ) ;
182237 let avoid_cross_crate_conflicts =
183238 // If this is an instance of a generic function, we also hash in
184239 // the ID of the instantiating crate. This avoids symbol conflicts
185240 // in case the same instances is emitted in two crates of the same
186241 // project.
187- is_generic ||
242+ is_generic ( substs ) ||
188243
189244 // If we're dealing with an instance of a function that's inlined from
190245 // another crate but we're marking it as globally shared to our
@@ -197,25 +252,8 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
197252 _ => false ,
198253 } ;
199254
200- let instantiating_crate = if avoid_cross_crate_conflicts {
201- Some ( if is_generic {
202- if !def_id. is_local ( ) && tcx. sess . opts . share_generics ( ) {
203- // If we are re-using a monomorphization from another crate,
204- // we have to compute the symbol hash accordingly.
205- let upstream_monomorphizations = tcx. upstream_monomorphizations_for ( def_id) ;
206-
207- upstream_monomorphizations
208- . and_then ( |monos| monos. get ( & substs) . cloned ( ) )
209- . unwrap_or ( LOCAL_CRATE )
210- } else {
211- LOCAL_CRATE
212- }
213- } else {
214- LOCAL_CRATE
215- } )
216- } else {
217- None
218- } ;
255+ let instantiating_crate =
256+ if avoid_cross_crate_conflicts { Some ( compute_instantiating_crate ( ) ) } else { None } ;
219257
220258 // Pick the crate responsible for the symbol mangling version, which has to:
221259 // 1. be stable for each instance, whether it's being defined or imported
@@ -232,10 +270,12 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
232270 tcx. symbol_mangling_version ( mangling_version_crate)
233271 } ;
234272
235- let mangled = match mangling_version {
273+ match mangling_version {
236274 SymbolManglingVersion :: Legacy => legacy:: mangle ( tcx, instance, instantiating_crate) ,
237275 SymbolManglingVersion :: V0 => v0:: mangle ( tcx, instance, instantiating_crate) ,
238- } ;
276+ }
277+ }
239278
240- Symbol :: intern ( & mangled)
279+ fn is_generic ( substs : SubstsRef < ' _ > ) -> bool {
280+ substs. non_erasable_generics ( ) . next ( ) . is_some ( )
241281}
0 commit comments