@@ -91,8 +91,9 @@ use rustc::middle::codegen_fn_attrs::CodegenFnAttrFlags;
91
91
use rustc:: mir:: mono:: { InstantiationMode , MonoItem } ;
92
92
use rustc:: session:: config:: SymbolManglingVersion ;
93
93
use rustc:: ty:: query:: Providers ;
94
+ use rustc:: ty:: subst:: SubstsRef ;
94
95
use rustc:: ty:: { self , Instance , TyCtxt } ;
95
- use rustc_hir:: def_id:: LOCAL_CRATE ;
96
+ use rustc_hir:: def_id:: { CrateNum , LOCAL_CRATE } ;
96
97
use rustc_hir:: Node ;
97
98
98
99
use rustc_span:: symbol:: Symbol ;
@@ -102,15 +103,70 @@ use log::debug;
102
103
mod legacy;
103
104
mod v0;
104
105
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
+
105
117
pub 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
+ }
108
120
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) }
111
160
}
112
161
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 {
114
170
let def_id = instance. def_id ( ) ;
115
171
let substs = instance. substs ;
116
172
@@ -121,11 +177,11 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
121
177
if def_id. is_local ( ) {
122
178
if tcx. plugin_registrar_fn ( LOCAL_CRATE ) == Some ( def_id) {
123
179
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) ;
125
181
}
126
182
if tcx. proc_macro_decls_static ( LOCAL_CRATE ) == Some ( def_id) {
127
183
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) ;
129
185
}
130
186
}
131
187
@@ -162,29 +218,28 @@ fn symbol_name(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) -> Symbol {
162
218
|| !tcx. wasm_import_module_map ( def_id. krate ) . contains_key ( & def_id)
163
219
{
164
220
if let Some ( name) = attrs. link_name {
165
- return name;
221
+ return name. to_string ( ) ;
166
222
}
167
- return tcx. item_name ( def_id) ;
223
+ return tcx. item_name ( def_id) . to_string ( ) ;
168
224
}
169
225
}
170
226
171
227
if let Some ( name) = attrs. export_name {
172
228
// Use provided name
173
- return name;
229
+ return name. to_string ( ) ;
174
230
}
175
231
176
232
if attrs. flags . contains ( CodegenFnAttrFlags :: NO_MANGLE ) {
177
233
// Don't mangle
178
- return tcx. item_name ( def_id) ;
234
+ return tcx. item_name ( def_id) . to_string ( ) ;
179
235
}
180
236
181
- let is_generic = substs. non_erasable_generics ( ) . next ( ) . is_some ( ) ;
182
237
let avoid_cross_crate_conflicts =
183
238
// If this is an instance of a generic function, we also hash in
184
239
// the ID of the instantiating crate. This avoids symbol conflicts
185
240
// in case the same instances is emitted in two crates of the same
186
241
// project.
187
- is_generic ||
242
+ is_generic ( substs ) ||
188
243
189
244
// If we're dealing with an instance of a function that's inlined from
190
245
// 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 {
197
252
_ => false ,
198
253
} ;
199
254
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 } ;
219
257
220
258
// Pick the crate responsible for the symbol mangling version, which has to:
221
259
// 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 {
232
270
tcx. symbol_mangling_version ( mangling_version_crate)
233
271
} ;
234
272
235
- let mangled = match mangling_version {
273
+ match mangling_version {
236
274
SymbolManglingVersion :: Legacy => legacy:: mangle ( tcx, instance, instantiating_crate) ,
237
275
SymbolManglingVersion :: V0 => v0:: mangle ( tcx, instance, instantiating_crate) ,
238
- } ;
276
+ }
277
+ }
239
278
240
- Symbol :: intern ( & mangled)
279
+ fn is_generic ( substs : SubstsRef < ' _ > ) -> bool {
280
+ substs. non_erasable_generics ( ) . next ( ) . is_some ( )
241
281
}
0 commit comments