1
1
use crate :: syntax:: atom:: Atom :: { self , * } ;
2
2
use crate :: syntax:: report:: Errors ;
3
3
use crate :: syntax:: set:: OrderedSet as Set ;
4
- use crate :: syntax:: { Api , Derive , Enum , ExternType , Struct , Type , TypeAlias } ;
4
+ use crate :: syntax:: { Api , Derive , Enum , ExternFn , ExternType , Struct , Type , TypeAlias } ;
5
5
use proc_macro2:: Ident ;
6
6
use quote:: ToTokens ;
7
7
use std:: collections:: { BTreeMap as Map , HashSet as UnorderedSet } ;
@@ -14,7 +14,7 @@ pub struct Types<'a> {
14
14
pub rust : Set < & ' a Ident > ,
15
15
pub aliases : Map < & ' a Ident , & ' a TypeAlias > ,
16
16
pub untrusted : Map < & ' a Ident , & ' a ExternType > ,
17
- pub required_trivial_aliases : UnorderedSet < & ' a Ident > ,
17
+ pub required_trivial_aliases : Map < & ' a Ident , TrivialReason < ' a > > ,
18
18
}
19
19
20
20
impl < ' a > Types < ' a > {
@@ -140,27 +140,30 @@ impl<'a> Types<'a> {
140
140
// we check that this is permissible. We do this _after_ scanning all
141
141
// the APIs above, in case some function or struct references a type
142
142
// which is declared subsequently.
143
- let mut required_trivial_aliases = UnorderedSet :: new ( ) ;
144
- let mut insist_alias_types_are_trivial = |ty : & ' a Type | {
143
+ let mut required_trivial_aliases = Map :: new ( ) ;
144
+ let mut insist_alias_types_are_trivial = |ty : & ' a Type , reason | {
145
145
if let Type :: Ident ( ident) = ty {
146
146
if aliases. contains_key ( ident) {
147
- required_trivial_aliases. insert ( ident) ;
147
+ required_trivial_aliases. entry ( ident) . or_insert ( reason ) ;
148
148
}
149
149
}
150
150
} ;
151
151
for api in apis {
152
152
match api {
153
153
Api :: Struct ( strct) => {
154
+ let reason = TrivialReason :: StructField ( strct) ;
154
155
for field in & strct. fields {
155
- insist_alias_types_are_trivial ( & field. ty ) ;
156
+ insist_alias_types_are_trivial ( & field. ty , reason ) ;
156
157
}
157
158
}
158
159
Api :: CxxFunction ( efn) | Api :: RustFunction ( efn) => {
160
+ let reason = TrivialReason :: FunctionArgument ( efn) ;
159
161
for arg in & efn. args {
160
- insist_alias_types_are_trivial ( & arg. ty ) ;
162
+ insist_alias_types_are_trivial ( & arg. ty , reason ) ;
161
163
}
162
164
if let Some ( ret) = & efn. ret {
163
- insist_alias_types_are_trivial ( & ret) ;
165
+ let reason = TrivialReason :: FunctionReturn ( efn) ;
166
+ insist_alias_types_are_trivial ( & ret, reason) ;
164
167
}
165
168
}
166
169
_ => { }
@@ -211,6 +214,13 @@ impl<'t, 'a> IntoIterator for &'t Types<'a> {
211
214
}
212
215
}
213
216
217
+ #[ derive( Copy , Clone ) ]
218
+ pub enum TrivialReason < ' a > {
219
+ StructField ( & ' a Struct ) ,
220
+ FunctionArgument ( & ' a ExternFn ) ,
221
+ FunctionReturn ( & ' a ExternFn ) ,
222
+ }
223
+
214
224
fn duplicate_name ( cx : & mut Errors , sp : impl ToTokens , ident : & Ident ) {
215
225
let msg = format ! ( "the name `{}` is defined multiple times" , ident) ;
216
226
cx. error ( sp, msg) ;
0 commit comments