]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/tydecode.rs
Fix stability
[rust.git] / src / librustc / metadata / tydecode.rs
1 // Copyright 2012-2014 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
11
12 // Type decoding
13
14 // tjc note: Would be great to have a `match check` macro equivalent
15 // for some of these
16
17 #![allow(non_camel_case_types)]
18
19 use rustc_front::hir;
20
21 use middle::def_id::{DefId, DefIndex};
22 use middle::region;
23 use middle::subst;
24 use middle::subst::VecPerParamSpace;
25 use middle::ty::{self, ToPredicate, Ty, HasTypeFlags};
26
27 use rbml;
28 use std::str;
29 use syntax::abi;
30 use syntax::ast;
31 use syntax::parse::token;
32
33 // Compact string representation for Ty values. API TyStr &
34 // parse_from_str. Extra parameters are for converting to/from def_ids in the
35 // data buffer. Whatever format you choose should not contain pipe characters.
36
37 pub type DefIdConvert<'a> = &'a mut FnMut(DefId) -> DefId;
38
39 pub struct TyDecoder<'a, 'tcx: 'a> {
40     data: &'a [u8],
41     krate: ast::CrateNum,
42     pos: usize,
43     tcx: &'a ty::ctxt<'tcx>,
44     conv_def_id: DefIdConvert<'a>,
45 }
46
47 impl<'a,'tcx> TyDecoder<'a,'tcx> {
48     pub fn with_doc(tcx: &'a ty::ctxt<'tcx>,
49                     crate_num: ast::CrateNum,
50                     doc: rbml::Doc<'a>,
51                     conv: DefIdConvert<'a>)
52                     -> TyDecoder<'a,'tcx> {
53         TyDecoder::new(doc.data, crate_num, doc.start, tcx, conv)
54     }
55
56     pub fn new(data: &'a [u8],
57                crate_num: ast::CrateNum,
58                pos: usize,
59                tcx: &'a ty::ctxt<'tcx>,
60                conv: DefIdConvert<'a>)
61                -> TyDecoder<'a, 'tcx> {
62         TyDecoder {
63             data: data,
64             krate: crate_num,
65             pos: pos,
66             tcx: tcx,
67             conv_def_id: conv,
68         }
69     }
70
71     fn peek(&self) -> char {
72         self.data[self.pos] as char
73     }
74
75     fn next(&mut self) -> char {
76         let ch = self.data[self.pos] as char;
77         self.pos = self.pos + 1;
78         return ch;
79     }
80
81     fn next_byte(&mut self) -> u8 {
82         let b = self.data[self.pos];
83         self.pos = self.pos + 1;
84         return b;
85     }
86
87     fn scan<F>(&mut self, mut is_last: F) -> &'a [u8]
88         where F: FnMut(char) -> bool,
89     {
90         let start_pos = self.pos;
91         debug!("scan: '{}' (start)", self.data[self.pos] as char);
92         while !is_last(self.data[self.pos] as char) {
93             self.pos += 1;
94             debug!("scan: '{}'", self.data[self.pos] as char);
95         }
96         let end_pos = self.pos;
97         self.pos += 1;
98         return &self.data[start_pos..end_pos];
99     }
100
101     fn parse_vuint(&mut self) -> usize {
102         let res = rbml::reader::vuint_at(self.data, self.pos).unwrap();
103         self.pos = res.next;
104         res.val
105     }
106
107     fn parse_name(&mut self, last: char) -> ast::Name {
108         fn is_last(b: char, c: char) -> bool { return c == b; }
109         let bytes = self.scan(|a| is_last(last, a));
110         token::intern(str::from_utf8(bytes).unwrap())
111     }
112
113     fn parse_size(&mut self) -> Option<usize> {
114         assert_eq!(self.next(), '/');
115
116         if self.peek() == '|' {
117             assert_eq!(self.next(), '|');
118             None
119         } else {
120             let n = self.parse_uint();
121             assert_eq!(self.next(), '|');
122             Some(n)
123         }
124     }
125
126     fn parse_vec_per_param_space<T, F>(&mut self, mut f: F) -> VecPerParamSpace<T> where
127         F: FnMut(&mut TyDecoder<'a, 'tcx>) -> T,
128     {
129         let mut r = VecPerParamSpace::empty();
130         for &space in &subst::ParamSpace::all() {
131             assert_eq!(self.next(), '[');
132             while self.peek() != ']' {
133                 r.push(space, f(self));
134             }
135             assert_eq!(self.next(), ']');
136         }
137         r
138     }
139
140     pub fn parse_substs(&mut self) -> subst::Substs<'tcx> {
141         let regions = self.parse_region_substs();
142         let types = self.parse_vec_per_param_space(|this| this.parse_ty());
143         subst::Substs { types: types, regions: regions }
144     }
145
146     fn parse_region_substs(&mut self) -> subst::RegionSubsts {
147         match self.next() {
148             'e' => subst::ErasedRegions,
149             'n' => {
150                 subst::NonerasedRegions(
151                     self.parse_vec_per_param_space(|this| this.parse_region()))
152             }
153             _ => panic!("parse_bound_region: bad input")
154         }
155     }
156
157     fn parse_bound_region(&mut self) -> ty::BoundRegion {
158         match self.next() {
159             'a' => {
160                 let id = self.parse_u32();
161                 assert_eq!(self.next(), '|');
162                 ty::BrAnon(id)
163             }
164             '[' => {
165                 let def = self.parse_def();
166                 let name = token::intern(&self.parse_str(']'));
167                 ty::BrNamed(def, name)
168             }
169             'f' => {
170                 let id = self.parse_u32();
171                 assert_eq!(self.next(), '|');
172                 ty::BrFresh(id)
173             }
174             'e' => ty::BrEnv,
175             _ => panic!("parse_bound_region: bad input")
176         }
177     }
178
179     pub fn parse_region(&mut self) -> ty::Region {
180         match self.next() {
181             'b' => {
182                 assert_eq!(self.next(), '[');
183                 let id = ty::DebruijnIndex::new(self.parse_u32());
184                 assert_eq!(self.next(), '|');
185                 let br = self.parse_bound_region();
186                 assert_eq!(self.next(), ']');
187                 ty::ReLateBound(id, br)
188             }
189             'B' => {
190                 assert_eq!(self.next(), '[');
191                 let def_id = self.parse_def();
192                 let space = self.parse_param_space();
193                 assert_eq!(self.next(), '|');
194                 let index = self.parse_u32();
195                 assert_eq!(self.next(), '|');
196                 let name = token::intern(&self.parse_str(']'));
197                 ty::ReEarlyBound(ty::EarlyBoundRegion {
198                     def_id: def_id,
199                     space: space,
200                     index: index,
201                     name: name
202                 })
203             }
204             'f' => {
205                 assert_eq!(self.next(), '[');
206                 let scope = self.parse_scope();
207                 assert_eq!(self.next(), '|');
208                 let br = self.parse_bound_region();
209                 assert_eq!(self.next(), ']');
210                 ty::ReFree(ty::FreeRegion { scope: scope,
211                                             bound_region: br})
212             }
213             's' => {
214                 let scope = self.parse_scope();
215                 assert_eq!(self.next(), '|');
216                 ty::ReScope(scope)
217             }
218             't' => {
219                 ty::ReStatic
220             }
221             'e' => {
222                 ty::ReStatic
223             }
224             _ => panic!("parse_region: bad input")
225         }
226     }
227
228     fn parse_scope(&mut self) -> region::CodeExtent {
229         self.tcx.region_maps.bogus_code_extent(match self.next() {
230             // This creates scopes with the wrong NodeId. This isn't
231             // actually a problem because scopes only exist *within*
232             // functions, and functions aren't loaded until trans which
233             // doesn't care about regions.
234             //
235             // May still be worth fixing though.
236             'P' => {
237                 assert_eq!(self.next(), '[');
238                 let fn_id = self.parse_uint() as ast::NodeId;
239                 assert_eq!(self.next(), '|');
240                 let body_id = self.parse_uint() as ast::NodeId;
241                 assert_eq!(self.next(), ']');
242                 region::CodeExtentData::ParameterScope {
243                     fn_id: fn_id, body_id: body_id
244                 }
245             }
246             'M' => {
247                 let node_id = self.parse_uint() as ast::NodeId;
248                 region::CodeExtentData::Misc(node_id)
249             }
250             'D' => {
251                 let node_id = self.parse_uint() as ast::NodeId;
252                 region::CodeExtentData::DestructionScope(node_id)
253             }
254             'B' => {
255                 assert_eq!(self.next(), '[');
256                 let node_id = self.parse_uint() as ast::NodeId;
257                 assert_eq!(self.next(), '|');
258                 let first_stmt_index = self.parse_u32();
259                 assert_eq!(self.next(), ']');
260                 let block_remainder = region::BlockRemainder {
261                     block: node_id, first_statement_index: first_stmt_index,
262                 };
263                 region::CodeExtentData::Remainder(block_remainder)
264             }
265             _ => panic!("parse_scope: bad input")
266         })
267     }
268
269     fn parse_opt<T, F>(&mut self, f: F) -> Option<T>
270         where F: FnOnce(&mut TyDecoder<'a, 'tcx>) -> T,
271     {
272         match self.next() {
273             'n' => None,
274             's' => Some(f(self)),
275             _ => panic!("parse_opt: bad input")
276         }
277     }
278
279     fn parse_str(&mut self, term: char) -> String {
280         let mut result = String::new();
281         while self.peek() != term {
282             unsafe {
283                 result.as_mut_vec().push_all(&[self.next_byte()])
284             }
285         }
286         self.next();
287         result
288     }
289
290     pub fn parse_trait_ref(&mut self) -> ty::TraitRef<'tcx> {
291         let def = self.parse_def();
292         let substs = self.tcx.mk_substs(self.parse_substs());
293         ty::TraitRef {def_id: def, substs: substs}
294     }
295
296     pub fn parse_ty(&mut self) -> Ty<'tcx> {
297         let tcx = self.tcx;
298         match self.next() {
299             'b' => return tcx.types.bool,
300             'i' => { /* eat the s of is */ self.next(); return tcx.types.isize },
301             'u' => { /* eat the s of us */ self.next(); return tcx.types.usize },
302             'M' => {
303                 match self.next() {
304                     'b' => return tcx.types.u8,
305                     'w' => return tcx.types.u16,
306                     'l' => return tcx.types.u32,
307                     'd' => return tcx.types.u64,
308                     'B' => return tcx.types.i8,
309                     'W' => return tcx.types.i16,
310                     'L' => return tcx.types.i32,
311                     'D' => return tcx.types.i64,
312                     'f' => return tcx.types.f32,
313                     'F' => return tcx.types.f64,
314                     _ => panic!("parse_ty: bad numeric type")
315                 }
316             }
317             'c' => return tcx.types.char,
318             't' => {
319                 assert_eq!(self.next(), '[');
320                 let did = self.parse_def();
321                 let substs = self.parse_substs();
322                 assert_eq!(self.next(), ']');
323                 let def = self.tcx.lookup_adt_def(did);
324                 return tcx.mk_enum(def, self.tcx.mk_substs(substs));
325             }
326             'x' => {
327                 assert_eq!(self.next(), '[');
328                 let trait_ref = ty::Binder(self.parse_trait_ref());
329                 let bounds = self.parse_existential_bounds();
330                 assert_eq!(self.next(), ']');
331                 return tcx.mk_trait(trait_ref, bounds);
332             }
333             'p' => {
334                 assert_eq!(self.next(), '[');
335                 let index = self.parse_u32();
336                 assert_eq!(self.next(), '|');
337                 let space = self.parse_param_space();
338                 assert_eq!(self.next(), '|');
339                 let name = token::intern(&self.parse_str(']'));
340                 return tcx.mk_param(space, index, name);
341             }
342             '~' => return tcx.mk_box(self.parse_ty()),
343             '*' => return tcx.mk_ptr(self.parse_mt()),
344             '&' => {
345                 let r = self.parse_region();
346                 let mt = self.parse_mt();
347                 return tcx.mk_ref(tcx.mk_region(r), mt);
348             }
349             'V' => {
350                 let t = self.parse_ty();
351                 return match self.parse_size() {
352                     Some(n) => tcx.mk_array(t, n),
353                     None => tcx.mk_slice(t)
354                 };
355             }
356             'v' => {
357                 return tcx.mk_str();
358             }
359             'T' => {
360                 assert_eq!(self.next(), '[');
361                 let mut params = Vec::new();
362                 while self.peek() != ']' { params.push(self.parse_ty()); }
363                 self.pos = self.pos + 1;
364                 return tcx.mk_tup(params);
365             }
366             'F' => {
367                 let def_id = self.parse_def();
368                 return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(self.parse_bare_fn_ty()));
369             }
370             'G' => {
371                 return tcx.mk_fn(None, tcx.mk_bare_fn(self.parse_bare_fn_ty()));
372             }
373             '#' => {
374                 // This is a hacky little caching scheme. The idea is that if we encode
375                 // the same type twice, the second (and third, and fourth...) time we will
376                 // just write `#123`, where `123` is the offset in the metadata of the
377                 // first appearance. Now when we are *decoding*, if we see a `#123`, we
378                 // can first check a cache (`tcx.rcache`) for that offset. If we find something,
379                 // we return it (modulo closure types, see below). But if not, then we
380                 // jump to offset 123 and read the type from there.
381
382                 let pos = self.parse_vuint();
383                 let key = ty::CReaderCacheKey { cnum: self.krate, pos: pos };
384                 match tcx.rcache.borrow().get(&key).cloned() {
385                     Some(tt) => {
386                         // If there is a closure buried in the type some where, then we
387                         // need to re-convert any def ids (see case 'k', below). That means
388                         // we can't reuse the cached version.
389                         if !tt.has_closure_types() {
390                             return tt;
391                         }
392                     }
393                     None => {}
394                 }
395
396                 let mut substate = TyDecoder::new(self.data,
397                                                   self.krate,
398                                                   pos,
399                                                   self.tcx,
400                                                   self.conv_def_id);
401                 let tt = substate.parse_ty();
402                 tcx.rcache.borrow_mut().insert(key, tt);
403                 return tt;
404             }
405             '\"' => {
406                 let _ = self.parse_def();
407                 let inner = self.parse_ty();
408                 inner
409             }
410             'a' => {
411                 assert_eq!(self.next(), '[');
412                 let did = self.parse_def();
413                 let substs = self.parse_substs();
414                 assert_eq!(self.next(), ']');
415                 let def = self.tcx.lookup_adt_def(did);
416                 return self.tcx.mk_struct(def, self.tcx.mk_substs(substs));
417             }
418             'k' => {
419                 assert_eq!(self.next(), '[');
420                 let did = self.parse_def();
421                 let substs = self.parse_substs();
422                 let mut tys = vec![];
423                 while self.peek() != '.' {
424                     tys.push(self.parse_ty());
425                 }
426                 assert_eq!(self.next(), '.');
427                 assert_eq!(self.next(), ']');
428                 return self.tcx.mk_closure(did, self.tcx.mk_substs(substs), tys);
429             }
430             'P' => {
431                 assert_eq!(self.next(), '[');
432                 let trait_ref = self.parse_trait_ref();
433                 let name = token::intern(&self.parse_str(']'));
434                 return tcx.mk_projection(trait_ref, name);
435             }
436             'e' => {
437                 return tcx.types.err;
438             }
439             c => { panic!("unexpected char in type string: {}", c);}
440         }
441     }
442
443     fn parse_mutability(&mut self) -> hir::Mutability {
444         match self.peek() {
445             'm' => { self.next(); hir::MutMutable }
446             _ => { hir::MutImmutable }
447         }
448     }
449
450     fn parse_mt(&mut self) -> ty::TypeAndMut<'tcx> {
451         let m = self.parse_mutability();
452         ty::TypeAndMut { ty: self.parse_ty(), mutbl: m }
453     }
454
455     fn parse_def(&mut self) -> DefId {
456         let def_id = parse_defid(self.scan(|c| c == '|'));
457         return (self.conv_def_id)(def_id);
458     }
459
460     fn parse_uint(&mut self) -> usize {
461         let mut n = 0;
462         loop {
463             let cur = self.peek();
464             if cur < '0' || cur > '9' { return n; }
465             self.pos = self.pos + 1;
466             n *= 10;
467             n += (cur as usize) - ('0' as usize);
468         };
469     }
470
471     fn parse_u32(&mut self) -> u32 {
472         let n = self.parse_uint();
473         let m = n as u32;
474         assert_eq!(m as usize, n);
475         m
476     }
477
478     fn parse_param_space(&mut self) -> subst::ParamSpace {
479         subst::ParamSpace::from_uint(self.parse_uint())
480     }
481
482     fn parse_abi_set(&mut self) -> abi::Abi {
483         assert_eq!(self.next(), '[');
484         let bytes = self.scan(|c| c == ']');
485         let abi_str = str::from_utf8(bytes).unwrap();
486         abi::lookup(&abi_str[..]).expect(abi_str)
487     }
488
489     pub fn parse_closure_ty(&mut self) -> ty::ClosureTy<'tcx> {
490         let unsafety = parse_unsafety(self.next());
491         let sig = self.parse_sig();
492         let abi = self.parse_abi_set();
493         ty::ClosureTy {
494             unsafety: unsafety,
495             sig: sig,
496             abi: abi,
497         }
498     }
499
500     pub fn parse_bare_fn_ty(&mut self) -> ty::BareFnTy<'tcx> {
501         let unsafety = parse_unsafety(self.next());
502         let abi = self.parse_abi_set();
503         let sig = self.parse_sig();
504         ty::BareFnTy {
505             unsafety: unsafety,
506             abi: abi,
507             sig: sig
508         }
509     }
510
511     fn parse_sig(&mut self) -> ty::PolyFnSig<'tcx> {
512         assert_eq!(self.next(), '[');
513         let mut inputs = Vec::new();
514         while self.peek() != ']' {
515             inputs.push(self.parse_ty());
516         }
517         self.pos += 1; // eat the ']'
518         let variadic = match self.next() {
519             'V' => true,
520             'N' => false,
521             r => panic!(format!("bad variadic: {}", r)),
522         };
523         let output = match self.peek() {
524             'z' => {
525                 self.pos += 1;
526                 ty::FnDiverging
527             }
528             _ => ty::FnConverging(self.parse_ty())
529         };
530         ty::Binder(ty::FnSig {inputs: inputs,
531                               output: output,
532                               variadic: variadic})
533     }
534
535     pub fn parse_predicate(&mut self) -> ty::Predicate<'tcx> {
536         match self.next() {
537             't' => ty::Binder(self.parse_trait_ref()).to_predicate(),
538             'e' => ty::Binder(ty::EquatePredicate(self.parse_ty(),
539                                                   self.parse_ty())).to_predicate(),
540             'r' => ty::Binder(ty::OutlivesPredicate(self.parse_region(),
541                                                     self.parse_region())).to_predicate(),
542             'o' => ty::Binder(ty::OutlivesPredicate(self.parse_ty(),
543                                                     self.parse_region())).to_predicate(),
544             'p' => ty::Binder(self.parse_projection_predicate()).to_predicate(),
545             'w' => ty::Predicate::WellFormed(self.parse_ty()),
546             'O' => {
547                 let def_id = self.parse_def();
548                 assert_eq!(self.next(), '|');
549                 ty::Predicate::ObjectSafe(def_id)
550             }
551             c => panic!("Encountered invalid character in metadata: {}", c)
552         }
553     }
554
555     fn parse_projection_predicate(&mut self) -> ty::ProjectionPredicate<'tcx> {
556         ty::ProjectionPredicate {
557             projection_ty: ty::ProjectionTy {
558                 trait_ref: self.parse_trait_ref(),
559                 item_name: token::intern(&self.parse_str('|')),
560             },
561             ty: self.parse_ty(),
562         }
563     }
564
565     pub fn parse_type_param_def(&mut self) -> ty::TypeParameterDef<'tcx> {
566         let name = self.parse_name(':');
567         let def_id = self.parse_def();
568         let space = self.parse_param_space();
569         assert_eq!(self.next(), '|');
570         let index = self.parse_u32();
571         assert_eq!(self.next(), '|');
572         let default_def_id = self.parse_def();
573         let default = self.parse_opt(|this| this.parse_ty());
574         let object_lifetime_default = self.parse_object_lifetime_default();
575
576         ty::TypeParameterDef {
577             name: name,
578             def_id: def_id,
579             space: space,
580             index: index,
581             default_def_id: default_def_id,
582             default: default,
583             object_lifetime_default: object_lifetime_default,
584         }
585     }
586
587     pub fn parse_region_param_def(&mut self) -> ty::RegionParameterDef {
588         let name = self.parse_name(':');
589         let def_id = self.parse_def();
590         let space = self.parse_param_space();
591         assert_eq!(self.next(), '|');
592         let index = self.parse_u32();
593         assert_eq!(self.next(), '|');
594         let mut bounds = vec![];
595         loop {
596             match self.next() {
597                 'R' => bounds.push(self.parse_region()),
598                 '.' => { break; }
599                 c => {
600                     panic!("parse_region_param_def: bad bounds ('{}')", c)
601                 }
602             }
603         }
604         ty::RegionParameterDef {
605             name: name,
606             def_id: def_id,
607             space: space,
608             index: index,
609             bounds: bounds
610         }
611     }
612
613
614     fn parse_object_lifetime_default(&mut self) -> ty::ObjectLifetimeDefault {
615         match self.next() {
616             'a' => ty::ObjectLifetimeDefault::Ambiguous,
617             'b' => ty::ObjectLifetimeDefault::BaseDefault,
618             's' => {
619                 let region = self.parse_region();
620                 ty::ObjectLifetimeDefault::Specific(region)
621             }
622             _ => panic!("parse_object_lifetime_default: bad input")
623         }
624     }
625
626     pub fn parse_existential_bounds(&mut self) -> ty::ExistentialBounds<'tcx> {
627         let builtin_bounds = self.parse_builtin_bounds();
628         let region_bound = self.parse_region();
629         let mut projection_bounds = Vec::new();
630
631         loop {
632             match self.next() {
633                 'P' => {
634                     projection_bounds.push(ty::Binder(self.parse_projection_predicate()));
635                 }
636                 '.' => { break; }
637                 c => {
638                     panic!("parse_bounds: bad bounds ('{}')", c)
639                 }
640             }
641         }
642
643         ty::ExistentialBounds::new(
644             region_bound, builtin_bounds, projection_bounds)
645     }
646
647     fn parse_builtin_bounds(&mut self) -> ty::BuiltinBounds {
648         let mut builtin_bounds = ty::BuiltinBounds::empty();
649         loop {
650             match self.next() {
651                 'S' => {
652                     builtin_bounds.insert(ty::BoundSend);
653                 }
654                 'Z' => {
655                     builtin_bounds.insert(ty::BoundSized);
656                 }
657                 'P' => {
658                     builtin_bounds.insert(ty::BoundCopy);
659                 }
660                 'T' => {
661                     builtin_bounds.insert(ty::BoundSync);
662                 }
663                 '.' => {
664                     return builtin_bounds;
665                 }
666                 c => {
667                     panic!("parse_bounds: bad builtin bounds ('{}')", c)
668                 }
669             }
670         }
671     }
672 }
673
674 // Rust metadata parsing
675 fn parse_defid(buf: &[u8]) -> DefId {
676     let mut colon_idx = 0;
677     let len = buf.len();
678     while colon_idx < len && buf[colon_idx] != ':' as u8 { colon_idx += 1; }
679     if colon_idx == len {
680         error!("didn't find ':' when parsing def id");
681         panic!();
682     }
683
684     let crate_part = &buf[0..colon_idx];
685     let def_part = &buf[colon_idx + 1..len];
686
687     let crate_num = match str::from_utf8(crate_part).ok().and_then(|s| {
688         s.parse::<usize>().ok()
689     }) {
690         Some(cn) => cn as ast::CrateNum,
691         None => panic!("internal error: parse_defid: crate number expected, found {:?}",
692                        crate_part)
693     };
694     let def_num = match str::from_utf8(def_part).ok().and_then(|s| {
695         s.parse::<usize>().ok()
696     }) {
697         Some(dn) => dn,
698         None => panic!("internal error: parse_defid: id expected, found {:?}",
699                        def_part)
700     };
701     let index = DefIndex::new(def_num);
702     DefId { krate: crate_num, index: index }
703 }
704
705 fn parse_unsafety(c: char) -> hir::Unsafety {
706     match c {
707         'u' => hir::Unsafety::Unsafe,
708         'n' => hir::Unsafety::Normal,
709         _ => panic!("parse_unsafety: bad unsafety {}", c)
710     }
711 }