@@ -28,10 +28,50 @@ fn read_crates(sess: session::session, crate: ast::crate) {
28
28
visit_item: bind visit_item ( e, _)
29
29
with * visit:: default_simple_visitor ( ) } ) ;
30
30
visit:: visit_crate ( crate , ( ) , v) ;
31
+ warn_if_multiple_versions ( sess, copy e. crate_cache ) ;
32
+ }
33
+
34
+ type cache_entry = {
35
+ cnum: int,
36
+ span: span,
37
+ metas: @[ @ast:: meta_item]
38
+ } ;
39
+
40
+ fn warn_if_multiple_versions ( sess : session:: session ,
41
+ crate_cache : [ cache_entry ] ) {
42
+ import either:: * ;
43
+
44
+ if crate_cache. is_not_empty ( ) {
45
+ let name = crate_name_from_metas ( * crate_cache. last ( ) . metas ) ;
46
+ let { lefts: matches , rights: non_matches } =
47
+ partition ( crate_cache. map { |entry|
48
+ let othername = crate_name_from_metas ( * entry. metas ) ;
49
+ if name == othername {
50
+ left ( entry)
51
+ } else {
52
+ right ( entry)
53
+ }
54
+ } ) ;
55
+
56
+ assert matches. is_not_empty ( ) ;
57
+
58
+ if matches. len ( ) != 1 u {
59
+ sess. warn ( #fmt ( "using multiple versions of crate `%s`" , name) ) ;
60
+ for matches. each { |match|
61
+ sess. span_note( match. span, "used here" ) ;
62
+ let attrs = [
63
+ attr:: mk_attr ( attr:: mk_list_item ( "link" , * match . metas ) )
64
+ ] ;
65
+ note_linkage_attrs ( sess, attrs) ;
66
+ }
67
+ }
68
+
69
+ warn_if_multiple_versions ( sess, non_matches) ;
70
+ }
31
71
}
32
72
33
73
type env = @{ sess : session:: session ,
34
- mut crate_cache: [ ( int , @ [ @ast :: meta_item ] ) ] ,
74
+ mut crate_cache : [ cache_entry ] ,
35
75
mut next_crate_num : ast:: crate_num } ;
36
76
37
77
fn visit_view_item ( e : env , i : @ast:: view_item ) {
@@ -138,28 +178,28 @@ fn default_native_lib_naming(sess: session::session, static: bool) ->
138
178
}
139
179
}
140
180
181
+ fn crate_name_from_metas ( metas : [ @ast:: meta_item ] ) -> str {
182
+ let name_items = attr:: find_meta_items_by_name ( metas, "name" ) ;
183
+ alt vec:: last_opt ( name_items) {
184
+ some ( i) {
185
+ alt attr:: get_meta_item_value_str ( i) {
186
+ some ( n) { n }
187
+ // FIXME: Probably want a warning here since the user
188
+ // is using the wrong type of meta item
189
+ _ { fail }
190
+ }
191
+ }
192
+ none { fail "expected to find the crate name" }
193
+ }
194
+ }
195
+
141
196
fn find_library_crate ( sess : session:: session , span : span ,
142
197
metas : [ @ast:: meta_item ] )
143
198
-> option < { ident: str , data : @[ u8 ] } > {
144
199
145
200
attr:: require_unique_names ( sess. diagnostic ( ) , metas) ;
146
201
let metas = metas;
147
-
148
- let crate_name =
149
- {
150
- let name_items = attr:: find_meta_items_by_name ( metas, "name" ) ;
151
- alt vec:: last_opt ( name_items) {
152
- some ( i) {
153
- alt attr:: get_meta_item_value_str ( i) {
154
- some ( n) { n }
155
- // FIXME: Probably want a warning here since the user
156
- // is using the wrong type of meta item
157
- _ { fail }
158
- }
159
- }
160
- none { fail }
161
- }
162
- } ;
202
+ let crate_name = crate_name_from_metas ( metas) ;
163
203
164
204
let nn = default_native_lib_naming ( sess, sess. opts . static ) ;
165
205
let x =
@@ -221,15 +261,19 @@ fn find_library_crate_aux(sess: session::session,
221
261
for matches. each { |match|
222
262
sess. note( #fmt( "path: %s" , match. ident) ) ;
223
263
let attrs = decoder:: get_crate_attributes( match . data) ;
224
- for attr:: find_linkage_attrs( attrs) . each { |attr|
225
- sess. note ( #fmt ( "meta: %s" , pprust:: attr_to_str ( attr) ) ) ;
226
- }
264
+ note_linkage_attrs ( sess, attrs) ;
227
265
}
228
266
sess. abort_if_errors ( ) ;
229
267
none
230
268
}
231
269
}
232
270
271
+ fn note_linkage_attrs ( sess : session:: session , attrs : [ ast:: attribute ] ) {
272
+ for attr:: find_linkage_attrs( attrs) . each { |attr|
273
+ sess. note( #fmt( "meta: %s" , pprust:: attr_to_str( attr) ) ) ;
274
+ }
275
+ }
276
+
233
277
fn get_metadata_section ( sess : session:: session ,
234
278
filename : str ) -> option < @[ u8 ] > unsafe {
235
279
let mb = str:: as_c_str ( filename, { |buf|
@@ -282,10 +326,10 @@ fn metas_with_ident(ident: ast::ident,
282
326
283
327
fn existing_match ( e : env , metas : [ @ast:: meta_item ] ) -> option < int > {
284
328
let maybe_entry = e. crate_cache . find { |c|
285
- metadata_matches ( * tuple :: second ( c ) , metas)
329
+ metadata_matches ( * c . metas , metas)
286
330
} ;
287
331
288
- maybe_entry. map { |c| tuple :: first ( c ) }
332
+ maybe_entry. map { |c| c . cnum }
289
333
}
290
334
291
335
fn resolve_crate ( e : env , ident : ast:: ident , metas : [ @ast:: meta_item ] ,
@@ -305,7 +349,7 @@ fn resolve_crate(e: env, ident: ast::ident, metas: [@ast::meta_item],
305
349
306
350
// Claim this crate number and cache it
307
351
let cnum = e. next_crate_num ;
308
- e. crate_cache += [ ( cnum, @linkage_metas) ] ;
352
+ e. crate_cache += [ { cnum: cnum , span : span , metas : @linkage_metas} ] ;
309
353
e. next_crate_num += 1 ;
310
354
311
355
// Now resolve the crates referenced by this crate
0 commit comments