@@ -61,56 +61,75 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
61
61
Some ( item) => item,
62
62
None => continue ,
63
63
} ;
64
- let kind = items. iter ( ) . find ( |k| {
65
- k. check_name ( "kind" )
66
- } ) . and_then ( |a| a. value_str ( ) ) . map ( Symbol :: as_str) ;
67
- let kind = match kind. as_ref ( ) . map ( |s| & s[ ..] ) {
68
- Some ( "static" ) => cstore:: NativeStatic ,
69
- Some ( "static-nobundle" ) => cstore:: NativeStaticNobundle ,
70
- Some ( "dylib" ) => cstore:: NativeUnknown ,
71
- Some ( "framework" ) => cstore:: NativeFramework ,
72
- Some ( k) => {
73
- struct_span_err ! ( self . tcx. sess, m. span, E0458 ,
74
- "unknown kind: `{}`" , k)
75
- . span_label ( m. span , "unknown kind" ) . emit ( ) ;
76
- cstore:: NativeUnknown
77
- }
78
- None => cstore:: NativeUnknown
79
- } ;
80
- let n = items. iter ( ) . find ( |n| {
81
- n. check_name ( "name" )
82
- } ) . and_then ( |a| a. value_str ( ) ) ;
83
- let n = match n {
84
- Some ( n) => n,
85
- None => {
86
- struct_span_err ! ( self . tcx. sess, m. span, E0459 ,
87
- "#[link(...)] specified without `name = \" foo\" `" )
88
- . span_label ( m. span , "missing `name` argument" ) . emit ( ) ;
89
- Symbol :: intern ( "foo" )
90
- }
64
+ let mut lib = NativeLibrary {
65
+ name : None ,
66
+ kind : cstore:: NativeUnknown ,
67
+ cfg : None ,
68
+ foreign_module : Some ( self . tcx . hir . local_def_id ( it. id ) ) ,
69
+ wasm_import_module : None ,
91
70
} ;
92
- let cfg = items. iter ( ) . find ( |k| {
93
- k. check_name ( "cfg" )
94
- } ) . and_then ( |a| a. meta_item_list ( ) ) ;
95
- let cfg = if let Some ( list) = cfg {
96
- if list. is_empty ( ) {
97
- self . tcx . sess . span_err ( m. span ( ) , "`cfg()` must have an argument" ) ;
98
- return ;
99
- } else if let cfg @ Some ( ..) = list[ 0 ] . meta_item ( ) {
100
- cfg. cloned ( )
71
+ let mut kind_specified = false ;
72
+
73
+ for item in items. iter ( ) {
74
+ if item. check_name ( "kind" ) {
75
+ kind_specified = true ;
76
+ let kind = match item. value_str ( ) {
77
+ Some ( name) => name,
78
+ None => continue , // skip like historical compilers
79
+ } ;
80
+ lib. kind = match & kind. as_str ( ) [ ..] {
81
+ "static" => cstore:: NativeStatic ,
82
+ "static-nobundle" => cstore:: NativeStaticNobundle ,
83
+ "dylib" => cstore:: NativeUnknown ,
84
+ "framework" => cstore:: NativeFramework ,
85
+ k => {
86
+ struct_span_err ! ( self . tcx. sess, m. span, E0458 ,
87
+ "unknown kind: `{}`" , k)
88
+ . span_label ( item. span , "unknown kind" ) . emit ( ) ;
89
+ cstore:: NativeUnknown
90
+ }
91
+ } ;
92
+ } else if item. check_name ( "name" ) {
93
+ lib. name = item. value_str ( ) ;
94
+ } else if item. check_name ( "cfg" ) {
95
+ let cfg = match item. meta_item_list ( ) {
96
+ Some ( list) => list,
97
+ None => continue , // skip like historical compilers
98
+ } ;
99
+ if cfg. is_empty ( ) {
100
+ self . tcx . sess . span_err (
101
+ item. span ( ) ,
102
+ "`cfg()` must have an argument" ,
103
+ ) ;
104
+ } else if let cfg @ Some ( ..) = cfg[ 0 ] . meta_item ( ) {
105
+ lib. cfg = cfg. cloned ( ) ;
106
+ } else {
107
+ self . tcx . sess . span_err ( cfg[ 0 ] . span ( ) , "invalid argument for `cfg(..)`" ) ;
108
+ }
109
+ } else if item. check_name ( "wasm_import_module" ) {
110
+ match item. value_str ( ) {
111
+ Some ( s) => lib. wasm_import_module = Some ( s) ,
112
+ None => {
113
+ let msg = "must be of the form #[link(wasm_import_module = \" ...\" )]" ;
114
+ self . tcx . sess . span_err ( item. span ( ) , msg) ;
115
+ }
116
+ }
101
117
} else {
102
- self . tcx . sess . span_err ( list [ 0 ] . span ( ) , "invalid argument for `cfg(..)`" ) ;
103
- return ;
118
+ // currently, like past compilers, ignore unknown
119
+ // directives here.
104
120
}
105
- } else {
106
- None
107
- } ;
108
- let lib = NativeLibrary {
109
- name : n,
110
- kind,
111
- cfg,
112
- foreign_module : Some ( self . tcx . hir . local_def_id ( it. id ) ) ,
113
- } ;
121
+ }
122
+
123
+ // In general we require #[link(name = "...")] but we allow
124
+ // #[link(wasm_import_module = "...")] without the `name`.
125
+ let requires_name = kind_specified || lib. wasm_import_module . is_none ( ) ;
126
+ if lib. name . is_none ( ) && requires_name {
127
+ struct_span_err ! ( self . tcx. sess, m. span, E0459 ,
128
+ "#[link(...)] specified without \
129
+ `name = \" foo\" `")
130
+ . span_label ( m. span , "missing `name` argument" )
131
+ . emit ( ) ;
132
+ }
114
133
self . register_native_lib ( Some ( m. span ) , lib) ;
115
134
}
116
135
}
@@ -121,7 +140,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
121
140
122
141
impl < ' a , ' tcx > Collector < ' a , ' tcx > {
123
142
fn register_native_lib ( & mut self , span : Option < Span > , lib : NativeLibrary ) {
124
- if lib. name . as_str ( ) . is_empty ( ) {
143
+ if lib. name . as_ref ( ) . map ( |s| s . as_str ( ) . is_empty ( ) ) . unwrap_or ( false ) {
125
144
match span {
126
145
Some ( span) => {
127
146
struct_span_err ! ( self . tcx. sess, span, E0454 ,
@@ -167,10 +186,14 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
167
186
let mut renames = FxHashSet ( ) ;
168
187
for & ( ref name, ref new_name, _) in & self . tcx . sess . opts . libs {
169
188
if let & Some ( ref new_name) = new_name {
189
+ let any_duplicate = self . libs
190
+ . iter ( )
191
+ . filter_map ( |lib| lib. name . as_ref ( ) )
192
+ . any ( |n| n == name) ;
170
193
if new_name. is_empty ( ) {
171
194
self . tcx . sess . err (
172
195
& format ! ( "an empty renaming target was specified for library `{}`" , name) ) ;
173
- } else if !self . libs . iter ( ) . any ( |lib| lib . name == name as & str ) {
196
+ } else if !any_duplicate {
174
197
self . tcx . sess . err ( & format ! ( "renaming of the library `{}` was specified, \
175
198
however this crate contains no #[link(...)] \
176
199
attributes referencing this library.", name) ) ;
@@ -189,14 +212,18 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
189
212
for & ( ref name, ref new_name, kind) in & self . tcx . sess . opts . libs {
190
213
let mut found = false ;
191
214
for lib in self . libs . iter_mut ( ) {
192
- if lib. name == name as & str {
215
+ let lib_name = match lib. name {
216
+ Some ( n) => n,
217
+ None => continue ,
218
+ } ;
219
+ if lib_name == name as & str {
193
220
let mut changed = false ;
194
221
if let Some ( k) = kind {
195
222
lib. kind = k;
196
223
changed = true ;
197
224
}
198
225
if let & Some ( ref new_name) = new_name {
199
- lib. name = Symbol :: intern ( new_name) ;
226
+ lib. name = Some ( Symbol :: intern ( new_name) ) ;
200
227
changed = true ;
201
228
}
202
229
if !changed {
@@ -212,10 +239,11 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
212
239
// Add if not found
213
240
let new_name = new_name. as_ref ( ) . map ( |s| & * * s) ; // &Option<String> -> Option<&str>
214
241
let lib = NativeLibrary {
215
- name : Symbol :: intern ( new_name. unwrap_or ( name) ) ,
242
+ name : Some ( Symbol :: intern ( new_name. unwrap_or ( name) ) ) ,
216
243
kind : if let Some ( k) = kind { k } else { cstore:: NativeUnknown } ,
217
244
cfg : None ,
218
245
foreign_module : None ,
246
+ wasm_import_module : None ,
219
247
} ;
220
248
self . register_native_lib ( None , lib) ;
221
249
}
0 commit comments