@@ -61,56 +61,75 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
6161 Some ( item) => item,
6262 None => continue ,
6363 } ;
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 ,
9170 } ;
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+ }
101117 } 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.
104120 }
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+ }
114133 self . register_native_lib ( Some ( m. span ) , lib) ;
115134 }
116135 }
@@ -121,7 +140,7 @@ impl<'a, 'tcx> ItemLikeVisitor<'tcx> for Collector<'a, 'tcx> {
121140
122141impl < ' a , ' tcx > Collector < ' a , ' tcx > {
123142 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 ) {
125144 match span {
126145 Some ( span) => {
127146 struct_span_err ! ( self . tcx. sess, span, E0454 ,
@@ -167,10 +186,14 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
167186 let mut renames = FxHashSet ( ) ;
168187 for & ( ref name, ref new_name, _) in & self . tcx . sess . opts . libs {
169188 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) ;
170193 if new_name. is_empty ( ) {
171194 self . tcx . sess . err (
172195 & 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 {
174197 self . tcx . sess . err ( & format ! ( "renaming of the library `{}` was specified, \
175198 however this crate contains no #[link(...)] \
176199 attributes referencing this library.", name) ) ;
@@ -189,14 +212,18 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
189212 for & ( ref name, ref new_name, kind) in & self . tcx . sess . opts . libs {
190213 let mut found = false ;
191214 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 {
193220 let mut changed = false ;
194221 if let Some ( k) = kind {
195222 lib. kind = k;
196223 changed = true ;
197224 }
198225 if let & Some ( ref new_name) = new_name {
199- lib. name = Symbol :: intern ( new_name) ;
226+ lib. name = Some ( Symbol :: intern ( new_name) ) ;
200227 changed = true ;
201228 }
202229 if !changed {
@@ -212,10 +239,11 @@ impl<'a, 'tcx> Collector<'a, 'tcx> {
212239 // Add if not found
213240 let new_name = new_name. as_ref ( ) . map ( |s| & * * s) ; // &Option<String> -> Option<&str>
214241 let lib = NativeLibrary {
215- name : Symbol :: intern ( new_name. unwrap_or ( name) ) ,
242+ name : Some ( Symbol :: intern ( new_name. unwrap_or ( name) ) ) ,
216243 kind : if let Some ( k) = kind { k } else { cstore:: NativeUnknown } ,
217244 cfg : None ,
218245 foreign_module : None ,
246+ wasm_import_module : None ,
219247 } ;
220248 self . register_native_lib ( None , lib) ;
221249 }
0 commit comments