/src/test/incremental/hashes/struct_defs.rs

https://gitlab.com/jianglu/rust · Rust · 469 lines · 340 code · 80 blank · 49 comment · 0 complexity · a8486a585c51158f56a7a1d13928ff7f MD5 · raw file

  1. // Copyright 2016 The Rust Project Developers. See the COPYRIGHT
  2. // file at the top-level directory of this distribution and at
  3. // http://rust-lang.org/COPYRIGHT.
  4. //
  5. // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
  6. // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
  7. // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
  8. // option. This file may not be copied, modified, or distributed
  9. // except according to those terms.
  10. // This test case tests the incremental compilation hash (ICH) implementation
  11. // for struct definitions.
  12. // The general pattern followed here is: Change one thing between rev1 and rev2
  13. // and make sure that the hash has changed, then change nothing between rev2 and
  14. // rev3 and make sure that the hash has not changed.
  15. // We also test the ICH for struct definitions exported in metadata. Same as
  16. // above, we want to make sure that the change between rev1 and rev2 also
  17. // results in a change of the ICH for the struct's metadata, and that it stays
  18. // the same between rev2 and rev3.
  19. // compile-pass
  20. // revisions: cfail1 cfail2 cfail3
  21. // compile-flags: -Z query-dep-graph -Zincremental-ignore-spans
  22. #![allow(warnings)]
  23. #![feature(rustc_attrs)]
  24. #![crate_type="rlib"]
  25. // Layout ----------------------------------------------------------------------
  26. #[cfg(cfail1)]
  27. pub struct LayoutPacked;
  28. #[cfg(not(cfail1))]
  29. #[rustc_dirty(label="Hir", cfg="cfail2")]
  30. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  31. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  32. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  33. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  34. #[rustc_clean(label="Hir", cfg="cfail3")]
  35. #[rustc_clean(label="HirBody", cfg="cfail3")]
  36. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  37. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  38. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  39. #[repr(packed)]
  40. pub struct LayoutPacked;
  41. #[cfg(cfail1)]
  42. struct LayoutC;
  43. #[cfg(not(cfail1))]
  44. #[rustc_dirty(label="Hir", cfg="cfail2")]
  45. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  46. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  47. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  48. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  49. #[rustc_clean(label="Hir", cfg="cfail3")]
  50. #[rustc_clean(label="HirBody", cfg="cfail3")]
  51. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  52. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  53. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  54. #[repr(C)]
  55. struct LayoutC;
  56. // Tuple Struct Change Field Type ----------------------------------------------
  57. #[cfg(cfail1)]
  58. struct TupleStructFieldType(i32);
  59. #[cfg(not(cfail1))]
  60. #[rustc_dirty(label="Hir", cfg="cfail2")]
  61. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  62. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  63. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  64. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  65. #[rustc_clean(label="Hir", cfg="cfail3")]
  66. #[rustc_clean(label="HirBody", cfg="cfail3")]
  67. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  68. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  69. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  70. // Note that changing the type of a field does not change the type of the struct or enum, but
  71. // adding/removing fields or changing a fields name or visibility does.
  72. struct TupleStructFieldType(
  73. u32
  74. );
  75. // Tuple Struct Add Field ------------------------------------------------------
  76. #[cfg(cfail1)]
  77. struct TupleStructAddField(i32);
  78. #[cfg(not(cfail1))]
  79. #[rustc_dirty(label="Hir", cfg="cfail2")]
  80. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  81. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  82. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  83. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  84. #[rustc_clean(label="Hir", cfg="cfail3")]
  85. #[rustc_clean(label="HirBody", cfg="cfail3")]
  86. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  87. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  88. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  89. struct TupleStructAddField(
  90. i32,
  91. u32
  92. );
  93. // Tuple Struct Field Visibility -----------------------------------------------
  94. #[cfg(cfail1)]
  95. struct TupleStructFieldVisibility(char);
  96. #[cfg(not(cfail1))]
  97. #[rustc_dirty(label="Hir", cfg="cfail2")]
  98. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  99. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  100. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  101. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  102. #[rustc_clean(label="Hir", cfg="cfail3")]
  103. #[rustc_clean(label="HirBody", cfg="cfail3")]
  104. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  105. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  106. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  107. struct TupleStructFieldVisibility(pub char);
  108. // Record Struct Field Type ----------------------------------------------------
  109. #[cfg(cfail1)]
  110. struct RecordStructFieldType { x: f32 }
  111. #[cfg(not(cfail1))]
  112. #[rustc_dirty(label="Hir", cfg="cfail2")]
  113. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  114. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  115. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  116. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  117. #[rustc_clean(label="Hir", cfg="cfail3")]
  118. #[rustc_clean(label="HirBody", cfg="cfail3")]
  119. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  120. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  121. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  122. // Note that changing the type of a field does not change the type of the struct or enum, but
  123. // adding/removing fields or changing a fields name or visibility does.
  124. struct RecordStructFieldType {
  125. x: u64
  126. }
  127. // Record Struct Field Name ----------------------------------------------------
  128. #[cfg(cfail1)]
  129. struct RecordStructFieldName { x: f32 }
  130. #[cfg(not(cfail1))]
  131. #[rustc_dirty(label="Hir", cfg="cfail2")]
  132. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  133. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  134. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  135. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  136. #[rustc_clean(label="Hir", cfg="cfail3")]
  137. #[rustc_clean(label="HirBody", cfg="cfail3")]
  138. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  139. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  140. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  141. struct RecordStructFieldName { y: f32 }
  142. // Record Struct Add Field -----------------------------------------------------
  143. #[cfg(cfail1)]
  144. struct RecordStructAddField { x: f32 }
  145. #[cfg(not(cfail1))]
  146. #[rustc_dirty(label="Hir", cfg="cfail2")]
  147. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  148. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  149. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  150. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  151. #[rustc_clean(label="Hir", cfg="cfail3")]
  152. #[rustc_clean(label="HirBody", cfg="cfail3")]
  153. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  154. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  155. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  156. struct RecordStructAddField {
  157. x: f32,
  158. y: () }
  159. // Record Struct Field Visibility ----------------------------------------------
  160. #[cfg(cfail1)]
  161. struct RecordStructFieldVisibility { x: f32 }
  162. #[cfg(not(cfail1))]
  163. #[rustc_dirty(label="Hir", cfg="cfail2")]
  164. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  165. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  166. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  167. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  168. #[rustc_clean(label="Hir", cfg="cfail3")]
  169. #[rustc_clean(label="HirBody", cfg="cfail3")]
  170. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  171. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  172. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  173. struct RecordStructFieldVisibility {
  174. pub x: f32
  175. }
  176. // Add Lifetime Parameter ------------------------------------------------------
  177. #[cfg(cfail1)]
  178. struct AddLifetimeParameter<'a>(&'a f32, &'a f64);
  179. #[cfg(not(cfail1))]
  180. #[rustc_dirty(label="Hir", cfg="cfail2")]
  181. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  182. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  183. #[rustc_dirty(label="GenericsOfItem", cfg="cfail2")]
  184. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  185. #[rustc_clean(label="Hir", cfg="cfail3")]
  186. #[rustc_clean(label="HirBody", cfg="cfail3")]
  187. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  188. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  189. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  190. struct AddLifetimeParameter<'a, 'b>(&'a f32, &'b f64);
  191. // Add Lifetime Parameter Bound ------------------------------------------------
  192. #[cfg(cfail1)]
  193. struct AddLifetimeParameterBound<'a, 'b>(&'a f32, &'b f64);
  194. #[cfg(not(cfail1))]
  195. #[rustc_dirty(label="Hir", cfg="cfail2")]
  196. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  197. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  198. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  199. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  200. #[rustc_clean(label="Hir", cfg="cfail3")]
  201. #[rustc_clean(label="HirBody", cfg="cfail3")]
  202. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  203. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  204. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  205. struct AddLifetimeParameterBound<'a, 'b: 'a>(
  206. &'a f32,
  207. &'b f64
  208. );
  209. #[cfg(cfail1)]
  210. struct AddLifetimeParameterBoundWhereClause<'a, 'b>(&'a f32, &'b f64);
  211. #[cfg(not(cfail1))]
  212. #[rustc_dirty(label="Hir", cfg="cfail2")]
  213. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  214. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  215. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  216. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  217. #[rustc_clean(label="Hir", cfg="cfail3")]
  218. #[rustc_clean(label="HirBody", cfg="cfail3")]
  219. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  220. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  221. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  222. struct AddLifetimeParameterBoundWhereClause<'a, 'b>(
  223. &'a f32,
  224. &'b f64)
  225. where 'b: 'a;
  226. // Add Type Parameter ----------------------------------------------------------
  227. #[cfg(cfail1)]
  228. struct AddTypeParameter<T1>(T1, T1);
  229. #[cfg(not(cfail1))]
  230. #[rustc_dirty(label="Hir", cfg="cfail2")]
  231. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  232. #[rustc_dirty(label="TypeOfItem", cfg="cfail2")]
  233. #[rustc_dirty(label="GenericsOfItem", cfg="cfail2")]
  234. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  235. #[rustc_clean(label="Hir", cfg="cfail3")]
  236. #[rustc_clean(label="HirBody", cfg="cfail3")]
  237. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  238. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  239. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  240. struct AddTypeParameter<T1, T2>(
  241. // The field contains the parent's Generics, so it's dirty even though its
  242. // type hasn't changed.
  243. T1,
  244. T2
  245. );
  246. // Add Type Parameter Bound ----------------------------------------------------
  247. #[cfg(cfail1)]
  248. struct AddTypeParameterBound<T>(T);
  249. #[cfg(not(cfail1))]
  250. #[rustc_dirty(label="Hir", cfg="cfail2")]
  251. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  252. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  253. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  254. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  255. #[rustc_clean(label="Hir", cfg="cfail3")]
  256. #[rustc_clean(label="HirBody", cfg="cfail3")]
  257. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  258. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  259. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  260. struct AddTypeParameterBound<T: Send>(
  261. T
  262. );
  263. #[cfg(cfail1)]
  264. struct AddTypeParameterBoundWhereClause<T>(T);
  265. #[cfg(not(cfail1))]
  266. #[rustc_dirty(label="Hir", cfg="cfail2")]
  267. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  268. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  269. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  270. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  271. #[rustc_clean(label="Hir", cfg="cfail3")]
  272. #[rustc_clean(label="HirBody", cfg="cfail3")]
  273. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  274. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  275. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  276. struct AddTypeParameterBoundWhereClause<T>(
  277. T
  278. ) where T: Sync;
  279. // Empty struct ----------------------------------------------------------------
  280. // Since we cannot change anything in this case, we just make sure that the
  281. // fingerprint is stable (i.e. that there are no random influences like memory
  282. // addresses taken into account by the hashing algorithm).
  283. // Note: there is no #[cfg(...)], so this is ALWAYS compiled
  284. #[rustc_clean(label="Hir", cfg="cfail2")]
  285. #[rustc_clean(label="HirBody", cfg="cfail2")]
  286. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  287. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  288. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  289. #[rustc_clean(label="Hir", cfg="cfail3")]
  290. #[rustc_clean(label="HirBody", cfg="cfail3")]
  291. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  292. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  293. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  294. pub struct EmptyStruct;
  295. // Visibility ------------------------------------------------------------------
  296. #[cfg(cfail1)]
  297. struct Visibility;
  298. #[cfg(not(cfail1))]
  299. #[rustc_dirty(label="Hir", cfg="cfail2")]
  300. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  301. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  302. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  303. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  304. #[rustc_clean(label="Hir", cfg="cfail3")]
  305. #[rustc_clean(label="HirBody", cfg="cfail3")]
  306. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  307. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  308. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  309. pub struct Visibility;
  310. struct ReferencedType1;
  311. struct ReferencedType2;
  312. // Tuple Struct Change Field Type Indirectly -----------------------------------
  313. mod tuple_struct_change_field_type_indirectly {
  314. #[cfg(cfail1)]
  315. use super::ReferencedType1 as FieldType;
  316. #[cfg(not(cfail1))]
  317. use super::ReferencedType2 as FieldType;
  318. #[rustc_dirty(label="Hir", cfg="cfail2")]
  319. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  320. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  321. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  322. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  323. #[rustc_clean(label="Hir", cfg="cfail3")]
  324. #[rustc_clean(label="HirBody", cfg="cfail3")]
  325. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  326. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  327. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  328. struct TupleStruct(
  329. FieldType
  330. );
  331. }
  332. // Record Struct Change Field Type Indirectly -----------------------------------
  333. mod record_struct_change_field_type_indirectly {
  334. #[cfg(cfail1)]
  335. use super::ReferencedType1 as FieldType;
  336. #[cfg(not(cfail1))]
  337. use super::ReferencedType2 as FieldType;
  338. #[rustc_dirty(label="Hir", cfg="cfail2")]
  339. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  340. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  341. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  342. #[rustc_clean(label="PredicatesOfItem", cfg="cfail2")]
  343. #[rustc_clean(label="Hir", cfg="cfail3")]
  344. #[rustc_clean(label="HirBody", cfg="cfail3")]
  345. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  346. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  347. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  348. struct RecordStruct {
  349. _x: FieldType
  350. }
  351. }
  352. trait ReferencedTrait1 {}
  353. trait ReferencedTrait2 {}
  354. // Change Trait Bound Indirectly -----------------------------------------------
  355. mod change_trait_bound_indirectly {
  356. #[cfg(cfail1)]
  357. use super::ReferencedTrait1 as Trait;
  358. #[cfg(not(cfail1))]
  359. use super::ReferencedTrait2 as Trait;
  360. #[rustc_dirty(label="Hir", cfg="cfail2")]
  361. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  362. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  363. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  364. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  365. #[rustc_clean(label="Hir", cfg="cfail3")]
  366. #[rustc_clean(label="HirBody", cfg="cfail3")]
  367. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  368. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  369. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  370. struct Struct<T: Trait>(T);
  371. }
  372. // Change Trait Bound Indirectly In Where Clause -------------------------------
  373. mod change_trait_bound_indirectly_in_where_clause {
  374. #[cfg(cfail1)]
  375. use super::ReferencedTrait1 as Trait;
  376. #[cfg(not(cfail1))]
  377. use super::ReferencedTrait2 as Trait;
  378. #[rustc_dirty(label="Hir", cfg="cfail2")]
  379. #[rustc_dirty(label="HirBody", cfg="cfail2")]
  380. #[rustc_clean(label="TypeOfItem", cfg="cfail2")]
  381. #[rustc_clean(label="GenericsOfItem", cfg="cfail2")]
  382. #[rustc_dirty(label="PredicatesOfItem", cfg="cfail2")]
  383. #[rustc_clean(label="Hir", cfg="cfail3")]
  384. #[rustc_clean(label="HirBody", cfg="cfail3")]
  385. #[rustc_clean(label="TypeOfItem", cfg="cfail3")]
  386. #[rustc_clean(label="GenericsOfItem", cfg="cfail3")]
  387. #[rustc_clean(label="PredicatesOfItem", cfg="cfail3")]
  388. struct Struct<T>(T) where T : Trait;
  389. }