@@ -20,7 +20,7 @@ export list_file_metadata;
20
20
// libraries necessary for later resolving, typechecking, linking, etc.
21
21
fn read_crates( sess : session:: session , crate : ast:: crate ) {
22
22
let e = @{ sess: sess,
23
- crate_cache: std :: map :: str_hash :: < int > ( ) ,
23
+ mut crate_cache: [ ] ,
24
24
mut next_crate_num: 1 } ;
25
25
let v =
26
26
visit:: mk_simple_visitor ( @{ visit_view_item:
@@ -31,7 +31,7 @@ fn read_crates(sess: session::session, crate: ast::crate) {
31
31
}
32
32
33
33
type env = @{ sess: session:: session,
34
- crate_cache : hashmap < str , int > ,
34
+ mut crate_cache: [ ( int , @ [ @ast :: meta_item ] ) ] ,
35
35
mut next_crate_num: ast:: crate_num} ;
36
36
37
37
fn visit_view_item ( e : env , i : @ast:: view_item ) {
@@ -100,21 +100,26 @@ fn list_file_metadata(sess: session::session, path: str, out: io::writer) {
100
100
}
101
101
}
102
102
103
- fn metadata_matches ( crate_data : @[ u8 ] , metas : [ @ast:: meta_item ] ) -> bool {
103
+ fn crate_matches ( crate_data : @[ u8 ] , metas : [ @ast:: meta_item ] ) -> bool {
104
104
let attrs = decoder:: get_crate_attributes ( crate_data) ;
105
105
let linkage_metas = attr:: find_linkage_metas ( attrs) ;
106
+ metadata_matches ( linkage_metas, metas)
107
+ }
108
+
109
+ fn metadata_matches ( extern_metas : [ @ast:: meta_item ] ,
110
+ local_metas : [ @ast:: meta_item ] ) -> bool {
106
111
107
112
#debug ( "matching %u metadata requirements against %u items" ,
108
- vec:: len ( metas ) , vec:: len ( linkage_metas ) ) ;
113
+ vec:: len ( local_metas ) , vec:: len ( extern_metas ) ) ;
109
114
110
115
#debug ( "crate metadata:" ) ;
111
- for have: @ast:: meta_item in linkage_metas {
116
+ for have: @ast:: meta_item in extern_metas {
112
117
#debug ( " %s" , pprust:: meta_item_to_str ( * have) ) ;
113
118
}
114
119
115
- for needed: @ast:: meta_item in metas {
120
+ for needed: @ast:: meta_item in local_metas {
116
121
#debug ( "looking for %s" , pprust:: meta_item_to_str ( * needed) ) ;
117
- if !attr:: contains ( linkage_metas , needed) {
122
+ if !attr:: contains ( extern_metas , needed) {
118
123
#debug ( "missing %s" , pprust:: meta_item_to_str ( * needed) ) ;
119
124
ret false ;
120
125
}
@@ -133,7 +138,7 @@ fn default_native_lib_naming(sess: session::session, static: bool) ->
133
138
}
134
139
}
135
140
136
- fn find_library_crate ( sess : session:: session , ident : ast :: ident ,
141
+ fn find_library_crate( sess: session:: session,
137
142
metas: [ @ast:: meta_item] )
138
143
-> option<{ ident: str , data: @[ u8] } > {
139
144
@@ -149,10 +154,10 @@ fn find_library_crate(sess: session::session, ident: ast::ident,
149
154
some ( n) { n }
150
155
// FIXME: Probably want a warning here since the user
151
156
// is using the wrong type of meta item
152
- _ { ident }
157
+ _ { fail }
153
158
}
154
159
}
155
- none { ident }
160
+ none { fail }
156
161
}
157
162
} ;
158
163
@@ -186,7 +191,7 @@ fn find_library_crate_aux(sess: session::session,
186
191
#debug ( "%s is a candidate" , path) ;
187
192
alt get_metadata_section ( sess, path) {
188
193
option:: some ( cvec) {
189
- if !metadata_matches ( cvec, metas) {
194
+ if !crate_matches ( cvec, metas) {
190
195
#debug ( "skipping %s, metadata doesn't match" , path) ;
191
196
option:: none
192
197
} else {
@@ -230,31 +235,55 @@ fn get_metadata_section(sess: session::session,
230
235
ret option:: none :: < @[ u8 ] > ;
231
236
}
232
237
233
- fn load_library_crate ( sess : session:: session , span : span , ident : ast:: ident ,
238
+ fn load_library_crate ( sess : session:: session , ident : ast:: ident , span : span ,
234
239
metas : [ @ast:: meta_item ] )
235
240
-> { ident: str , data: @[ u8] } {
236
241
237
242
238
- alt find_library_crate ( sess, ident , metas) {
243
+ alt find_library_crate ( sess, metas) {
239
244
some ( t) { ret t; }
240
245
none {
241
246
sess. span_fatal ( span, #fmt[ "can't find crate for '%s'" , ident] ) ;
242
247
}
243
248
}
244
249
}
245
250
251
+ fn metas_with_ident ( ident : ast:: ident ,
252
+ metas : [ @ast:: meta_item ] ) -> [ @ast:: meta_item ] {
253
+ let name_items = attr:: find_meta_items_by_name ( metas, "name" ) ;
254
+ if name_items. is_empty ( ) {
255
+ metas + [ attr:: mk_name_value_item_str ( "name" , ident) ]
256
+ } else {
257
+ metas
258
+ }
259
+ }
260
+
261
+ fn existing_match ( e : env , metas : [ @ast:: meta_item ] ) -> option < int > {
262
+ let maybe_entry = e. crate_cache . find { |c|
263
+ metadata_matches ( * tuple:: second ( c) , metas)
264
+ } ;
265
+
266
+ maybe_entry. map { |c| tuple:: first ( c) }
267
+ }
268
+
246
269
fn resolve_crate ( e : env , ident : ast:: ident , metas : [ @ast:: meta_item ] ,
247
270
span : span ) -> ast:: crate_num {
248
- if !e. crate_cache . contains_key ( ident) {
271
+ let metas = metas_with_ident ( ident, metas) ;
272
+
273
+ alt existing_match ( e, metas) {
274
+ none {
249
275
let cinfo =
250
- load_library_crate ( e. sess , span , ident , metas) ;
276
+ load_library_crate ( e. sess , ident , span , metas) ;
251
277
252
278
let cfilename = cinfo. ident ;
253
279
let cdata = cinfo. data ;
254
280
281
+ let attrs = decoder:: get_crate_attributes ( cdata) ;
282
+ let linkage_metas = attr:: find_linkage_metas ( attrs) ;
283
+
255
284
// Claim this crate number and cache it
256
285
let cnum = e. next_crate_num ;
257
- e. crate_cache . insert ( ident , cnum ) ;
286
+ e. crate_cache += [ ( cnum , @linkage_metas ) ] ;
258
287
e. next_crate_num += 1 ;
259
288
260
289
// Now resolve the crates referenced by this crate
@@ -267,7 +296,11 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
267
296
cstore:: set_crate_data ( cstore, cnum, cmeta) ;
268
297
cstore:: add_used_crate_file ( cstore, cfilename) ;
269
298
ret cnum;
270
- } else { ret e. crate_cache . get ( ident) ; }
299
+ }
300
+ some ( cnum) {
301
+ ret cnum;
302
+ }
303
+ }
271
304
}
272
305
273
306
// Go through the crate metadata and load any crates that it references
@@ -279,19 +312,24 @@ fn resolve_crate_deps(e: env, cdata: @[u8]) -> cstore::cnum_map {
279
312
for dep: decoder:: crate_dep in decoder:: get_crate_deps ( cdata) {
280
313
let extrn_cnum = dep. cnum ;
281
314
let cname = dep. ident ;
315
+ // FIXME: We really need to know the linkage metas of our transitive
316
+ // dependencies in order to resolve them correctly.
317
+ let cmetas = [ ] ;
282
318
#debug ( "resolving dep %s" , cname) ;
283
- if e. crate_cache . contains_key ( cname) {
319
+ alt existing_match ( e, metas_with_ident ( cname, cmetas) ) {
320
+ some ( local_cnum) {
284
321
#debug ( "already have it" ) ;
285
322
// We've already seen this crate
286
- let local_cnum = e. crate_cache . get ( cname) ;
287
323
cnum_map. insert ( extrn_cnum, local_cnum) ;
288
- } else {
324
+ }
325
+ none {
289
326
#debug( "need to load it" ) ;
290
327
// This is a new one so we've got to load it
291
328
// FIXME: Need better error reporting than just a bogus span
292
329
let fake_span = ast_util:: dummy_sp ( ) ;
293
- let local_cnum = resolve_crate ( e, cname, [ ] , fake_span) ;
330
+ let local_cnum = resolve_crate ( e, cname, cmetas , fake_span) ;
294
331
cnum_map. insert ( extrn_cnum, local_cnum) ;
332
+ }
295
333
}
296
334
}
297
335
ret cnum_map;
0 commit comments