diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e19fa01b2e4e8..3040125d97e32 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1721,7 +1721,7 @@ impl LintPass for Stability { if self.is_internal(cx, item.span) { return } match item.node { - ast::ItemTrait(_, _, ref supertraits, _) => { + ast::ItemTrait(_, _, _, ref supertraits, _) => { for t in supertraits.iter() { if let ast::TraitTyParamBound(ref t) = *t { let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref); @@ -1729,7 +1729,7 @@ impl LintPass for Stability { } } } - ast::ItemImpl(_, Some(ref t), _, _) => { + ast::ItemImpl(_, _, Some(ref t), _, _) => { let id = ty::trait_ref_to_def_id(cx.tcx, t); self.lint(cx, id, t.path.span); } diff --git a/src/librustc/metadata/common.rs b/src/librustc/metadata/common.rs index 99e7966b66f68..b698e4fcc7f7b 100644 --- a/src/librustc/metadata/common.rs +++ b/src/librustc/metadata/common.rs @@ -255,3 +255,5 @@ pub const tag_method_ty_generics: uint = 0xa7; pub const tag_predicate: uint = 0xa8; pub const tag_predicate_space: uint = 0xa9; pub const tag_predicate_data: uint = 0xb0; + +pub const tag_unsafety: uint = 0xb1; diff --git a/src/librustc/metadata/decoder.rs b/src/librustc/metadata/decoder.rs index 4e892f53186bc..b78112f1f7850 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -361,6 +361,15 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum) } } +fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety { + let unsafety_doc = reader::get_doc(item_doc, tag_unsafety); + if reader::doc_as_u8(unsafety_doc) != 0 { + ast::Unsafety::Unsafe + } else { + ast::Unsafety::Normal + } +} + pub fn get_trait_def<'tcx>(cdata: Cmd, item_id: ast::NodeId, tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx> @@ -368,8 +377,10 @@ pub fn get_trait_def<'tcx>(cdata: Cmd, let item_doc = lookup_item(item_id, cdata.data()); let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics); let bounds = trait_def_bounds(item_doc, tcx, cdata); + let unsafety = parse_unsafety(item_doc); ty::TraitDef { + unsafety: unsafety, generics: generics, bounds: bounds, trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata)) diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 9804e3c20aa35..a1f04b7412b32 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1205,7 +1205,7 @@ fn encode_info_for_item(ecx: &EncodeContext, None => {} } } - ast::ItemImpl(_, ref opt_trait, ref ty, ref ast_items) => { + ast::ItemImpl(unsafety, _, ref opt_trait, ref ty, ref ast_items) => { // We need to encode information about the default methods we // have inherited, so we drive this based on the impl structure. let impl_items = tcx.impl_items.borrow(); @@ -1218,6 +1218,7 @@ fn encode_info_for_item(ecx: &EncodeContext, encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id)); encode_name(rbml_w, item.ident.name); encode_attributes(rbml_w, item.attrs.as_slice()); + encode_unsafety(rbml_w, unsafety); match ty.node { ast::TyPath(ref path, _) if path.segments .len() == 1 => { @@ -1308,13 +1309,14 @@ fn encode_info_for_item(ecx: &EncodeContext, } } } - ast::ItemTrait(_, _, _, ref ms) => { + ast::ItemTrait(_, _, _, _, ref ms) => { add_to_index(item, rbml_w, index); rbml_w.start_tag(tag_items_data_item); encode_def_id(rbml_w, def_id); encode_family(rbml_w, 'I'); encode_item_variances(rbml_w, ecx, item.id); let trait_def = ty::lookup_trait_def(tcx, def_id); + encode_unsafety(rbml_w, trait_def.unsafety); encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics); encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref); encode_name(rbml_w, item.ident.name); @@ -1674,6 +1676,14 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) { rbml_w.end_tag(); } +fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) { + let byte: u8 = match unsafety { + ast::Unsafety::Normal => 0, + ast::Unsafety::Unsafe => 1, + }; + rbml_w.wr_tagged_u8(tag_unsafety, byte); +} + fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) { fn get_ordered_deps(cstore: &cstore::CStore) -> Vec { // Pull the cnums and name,vers,hash out of cstore @@ -1855,7 +1865,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> { impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> { fn visit_item(&mut self, item: &ast::Item) { - if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node { + if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node { let def_map = &self.ecx.tcx.def_map; let trait_def = def_map.borrow()[trait_ref.ref_id].clone(); let def_id = trait_def.def_id(); diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs index 7358b3bc9c969..d649c6491314c 100644 --- a/src/librustc/metadata/tydecode.rs +++ b/src/librustc/metadata/tydecode.rs @@ -549,11 +549,11 @@ fn parse_hex(st: &mut PState) -> uint { }; } -fn parse_fn_style(c: char) -> ast::FnStyle { +fn parse_unsafety(c: char) -> ast::Unsafety { match c { - 'u' => ast::UnsafeFn, - 'n' => ast::NormalFn, - _ => panic!("parse_fn_style: bad fn_style {}", c) + 'u' => ast::Unsafety::Unsafe, + 'n' => ast::Unsafety::Normal, + _ => panic!("parse_unsafety: bad unsafety {}", c) } } @@ -575,14 +575,14 @@ fn parse_onceness(c: char) -> ast::Onceness { fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::ClosureTy<'tcx> { - let fn_style = parse_fn_style(next(st)); + let unsafety = parse_unsafety(next(st)); let onceness = parse_onceness(next(st)); let store = parse_trait_store(st, |x,y| conv(x,y)); let bounds = parse_existential_bounds(st, |x,y| conv(x,y)); let sig = parse_sig(st, |x,y| conv(x,y)); let abi = parse_abi_set(st); ty::ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, store: store, bounds: bounds, @@ -593,11 +593,11 @@ fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>, conv: conv_did) -> ty::BareFnTy<'tcx> { - let fn_style = parse_fn_style(next(st)); + let unsafety = parse_unsafety(next(st)); let abi = parse_abi_set(st); let sig = parse_sig(st, |x,y| conv(x,y)); ty::BareFnTy { - fn_style: fn_style, + unsafety: unsafety, abi: abi, sig: sig } diff --git a/src/librustc/metadata/tyencode.rs b/src/librustc/metadata/tyencode.rs index 54376cd7b9078..9b9d2ab42df2b 100644 --- a/src/librustc/metadata/tyencode.rs +++ b/src/librustc/metadata/tyencode.rs @@ -313,10 +313,10 @@ fn enc_sty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, } } -fn enc_fn_style(w: &mut SeekableMemWriter, p: ast::FnStyle) { +fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) { match p { - ast::NormalFn => mywrite!(w, "n"), - ast::UnsafeFn => mywrite!(w, "u"), + ast::Unsafety::Normal => mywrite!(w, "n"), + ast::Unsafety::Unsafe => mywrite!(w, "u"), } } @@ -335,14 +335,14 @@ fn enc_onceness(w: &mut SeekableMemWriter, o: ast::Onceness) { pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, ft: &ty::BareFnTy<'tcx>) { - enc_fn_style(w, ft.fn_style); + enc_unsafety(w, ft.unsafety); enc_abi(w, ft.abi); enc_fn_sig(w, cx, &ft.sig); } pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>, ft: &ty::ClosureTy<'tcx>) { - enc_fn_style(w, ft.fn_style); + enc_unsafety(w, ft.unsafety); enc_onceness(w, ft.onceness); enc_trait_store(w, cx, ft.store); enc_existential_bounds(w, cx, &ft.bounds); diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index d2f43faa00355..939775e750713 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -355,7 +355,7 @@ impl<'v> Visitor<'v> for LifeSeeder { ast::ItemEnum(ref enum_def, _) if allow_dead_code => { self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id)); } - ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => { + ast::ItemImpl(_, _, Some(ref _trait_ref), _, ref impl_items) => { for impl_item in impl_items.iter() { match *impl_item { ast::MethodImplItem(ref method) => { diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs index 8bf43c70c26d9..d16ce3ad678b3 100644 --- a/src/librustc/middle/effect.rs +++ b/src/librustc/middle/effect.rs @@ -34,8 +34,8 @@ impl Copy for UnsafeContext {} fn type_is_unsafe_function(ty: Ty) -> bool { match ty.sty { - ty::ty_bare_fn(ref f) => f.fn_style == ast::UnsafeFn, - ty::ty_closure(ref f) => f.fn_style == ast::UnsafeFn, + ty::ty_bare_fn(ref f) => f.unsafety == ast::Unsafety::Unsafe, + ty::ty_closure(ref f) => f.unsafety == ast::Unsafety::Unsafe, _ => false, } } @@ -92,9 +92,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> { let (is_item_fn, is_unsafe_fn) = match fn_kind { visit::FkItemFn(_, _, fn_style, _) => - (true, fn_style == ast::UnsafeFn), + (true, fn_style == ast::Unsafety::Unsafe), visit::FkMethod(_, _, method) => - (true, method.pe_fn_style() == ast::UnsafeFn), + (true, method.pe_unsafety() == ast::Unsafety::Unsafe), _ => (false, false), }; diff --git a/src/librustc/middle/infer/coercion.rs b/src/librustc/middle/infer/coercion.rs index c6422b36e384d..1d1ee39d68435 100644 --- a/src/librustc/middle/infer/coercion.rs +++ b/src/librustc/middle/infer/coercion.rs @@ -521,7 +521,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> { debug!("coerce_from_bare_fn(a={}, b={})", a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx)); - if fn_ty_a.abi != abi::Rust || fn_ty_a.fn_style != ast::NormalFn { + if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal { return self.subtype(a, b); } diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs index ab9c5b86aeb62..26bba55594b5e 100644 --- a/src/librustc/middle/infer/combine.rs +++ b/src/librustc/middle/infer/combine.rs @@ -51,7 +51,7 @@ use middle::ty_fold; use middle::ty_fold::{TypeFoldable}; use util::ppaux::Repr; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; use syntax::ast; use syntax::abi; use syntax::codemap::Span; @@ -193,12 +193,12 @@ pub trait Combine<'tcx> { fn bare_fn_tys(&self, a: &ty::BareFnTy<'tcx>, b: &ty::BareFnTy<'tcx>) -> cres<'tcx, ty::BareFnTy<'tcx>> { - let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style)); + let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); let abi = try!(self.abi(a.abi, b.abi)); let sig = try!(self.fn_sigs(&a.sig, &b.sig)); - Ok(ty::BareFnTy {fn_style: fn_style, - abi: abi, - sig: sig}) + Ok(ty::BareFnTy {unsafety: unsafety, + abi: abi, + sig: sig}) } fn closure_tys(&self, a: &ty::ClosureTy<'tcx>, @@ -219,13 +219,13 @@ pub trait Combine<'tcx> { return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store))) } }; - let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style)); + let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety)); let onceness = try!(self.oncenesses(a.onceness, b.onceness)); let bounds = try!(self.existential_bounds(a.bounds, b.bounds)); let sig = try!(self.fn_sigs(&a.sig, &b.sig)); let abi = try!(self.abi(a.abi, b.abi)); Ok(ty::ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, store: store, bounds: bounds, @@ -240,7 +240,7 @@ pub trait Combine<'tcx> { self.contratys(a, b).and_then(|t| Ok(t)) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle>; + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>; fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<'tcx, abi::Abi> { if a == b { diff --git a/src/librustc/middle/infer/equate.rs b/src/librustc/middle/infer/equate.rs index a79a50b1781eb..1738b8db99b37 100644 --- a/src/librustc/middle/infer/equate.rs +++ b/src/librustc/middle/infer/equate.rs @@ -21,7 +21,7 @@ use middle::infer::{TypeTrace, Subtype}; use middle::infer::type_variable::{EqTo}; use util::ppaux::{Repr}; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; pub struct Equate<'f, 'tcx: 'f> { fields: CombineFields<'f, 'tcx> @@ -70,9 +70,9 @@ impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> { Ok(ty::mt { mutbl: a.mutbl, ty: t }) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { if a != b { - Err(ty::terr_fn_style_mismatch(expected_found(self, a, b))) + Err(ty::terr_unsafety_mismatch(expected_found(self, a, b))) } else { Ok(a) } diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs index 0c346519672d8..5c2944f898ed2 100644 --- a/src/librustc/middle/infer/error_reporting.rs +++ b/src/librustc/middle/infer/error_reporting.rs @@ -157,7 +157,7 @@ trait ErrorReportingHelpers<'tcx> { fn give_expl_lifetime_param(&self, decl: &ast::FnDecl, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, ident: ast::Ident, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics, @@ -828,7 +828,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ast::MethodImplItem(ref m) => { Some((m.pe_fn_decl(), m.pe_generics(), - m.pe_fn_style(), + m.pe_unsafety(), m.pe_ident(), Some(&m.pe_explicit_self().node), m.span)) @@ -841,7 +841,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { ast::ProvidedMethod(ref m) => { Some((m.pe_fn_decl(), m.pe_generics(), - m.pe_fn_style(), + m.pe_unsafety(), m.pe_ident(), Some(&m.pe_explicit_self().node), m.span)) @@ -853,14 +853,14 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> { }, None => None }; - let (fn_decl, generics, fn_style, ident, expl_self, span) + let (fn_decl, generics, unsafety, ident, expl_self, span) = node_inner.expect("expect item fn"); let taken = lifetimes_in_scope(self.tcx, scope_id); let life_giver = LifeGiver::with_taken(taken.as_slice()); let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self, generics, same_regions, &life_giver); let (fn_decl, expl_self, generics) = rebuilder.rebuild(); - self.give_expl_lifetime_param(&fn_decl, fn_style, ident, + self.give_expl_lifetime_param(&fn_decl, unsafety, ident, expl_self.as_ref(), &generics, span); } } @@ -1407,12 +1407,12 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> { impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> { fn give_expl_lifetime_param(&self, decl: &ast::FnDecl, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, ident: ast::Ident, opt_explicit_self: Option<&ast::ExplicitSelf_>, generics: &ast::Generics, span: codemap::Span) { - let suggested_fn = pprust::fun_to_string(decl, fn_style, ident, + let suggested_fn = pprust::fun_to_string(decl, unsafety, ident, opt_explicit_self, generics); let msg = format!("consider using an explicit lifetime \ parameter as shown: {}", suggested_fn); @@ -1690,7 +1690,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt, match tcx.map.find(parent) { Some(node) => match node { ast_map::NodeItem(item) => match item.node { - ast::ItemImpl(ref gen, _, _, _) => { + ast::ItemImpl(_, ref gen, _, _, _) => { taken.push_all(gen.lifetimes.as_slice()); } _ => () diff --git a/src/librustc/middle/infer/glb.rs b/src/librustc/middle/infer/glb.rs index 4237a7af32fc1..9fc4e095c43bd 100644 --- a/src/librustc/middle/infer/glb.rs +++ b/src/librustc/middle/infer/glb.rs @@ -20,8 +20,7 @@ use super::{TypeTrace, Subtype}; use middle::ty::{BuiltinBounds}; use middle::ty::{mod, Ty}; use syntax::ast::{Many, Once, MutImmutable, MutMutable}; -use syntax::ast::{NormalFn, UnsafeFn}; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; use util::ppaux::mt_to_string; use util::ppaux::Repr; @@ -81,10 +80,10 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> { self.lub().tys(a, b) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { match (a, b) { - (NormalFn, _) | (_, NormalFn) => Ok(NormalFn), - (UnsafeFn, UnsafeFn) => Ok(UnsafeFn) + (Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal), + (Unsafety::Unsafe, Unsafety::Unsafe) => Ok(Unsafety::Unsafe) } } diff --git a/src/librustc/middle/infer/lub.rs b/src/librustc/middle/infer/lub.rs index f53ba571062b2..f27b07c9c9d45 100644 --- a/src/librustc/middle/infer/lub.rs +++ b/src/librustc/middle/infer/lub.rs @@ -20,8 +20,7 @@ use super::{TypeTrace, Subtype}; use middle::ty::{BuiltinBounds}; use middle::ty::{mod, Ty}; use syntax::ast::{Many, Once}; -use syntax::ast::{NormalFn, UnsafeFn}; -use syntax::ast::{Onceness, FnStyle}; +use syntax::ast::{Onceness, Unsafety}; use syntax::ast::{MutMutable, MutImmutable}; use util::ppaux::mt_to_string; use util::ppaux::Repr; @@ -77,10 +76,10 @@ impl<'f, 'tcx> Combine<'tcx> for Lub<'f, 'tcx> { self.glb().tys(a, b) } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { match (a, b) { - (UnsafeFn, _) | (_, UnsafeFn) => Ok(UnsafeFn), - (NormalFn, NormalFn) => Ok(NormalFn), + (Unsafety::Unsafe, _) | (_, Unsafety::Unsafe) => Ok(Unsafety::Unsafe), + (Unsafety::Normal, Unsafety::Normal) => Ok(Unsafety::Normal), } } diff --git a/src/librustc/middle/infer/sub.rs b/src/librustc/middle/infer/sub.rs index c470b2488273a..00c79bc726cf6 100644 --- a/src/librustc/middle/infer/sub.rs +++ b/src/librustc/middle/infer/sub.rs @@ -23,7 +23,7 @@ use middle::ty::{mod, Ty}; use middle::ty::TyVar; use util::ppaux::{Repr}; -use syntax::ast::{Onceness, FnStyle, MutImmutable, MutMutable}; +use syntax::ast::{Onceness, MutImmutable, MutMutable, Unsafety}; /// "Greatest lower bound" (common subtype) @@ -93,9 +93,9 @@ impl<'f, 'tcx> Combine<'tcx> for Sub<'f, 'tcx> { Ok(*a) // return is meaningless in sub, just return *a } - fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> { - self.lub().fn_styles(a, b).compare(b, || { - ty::terr_fn_style_mismatch(expected_found(self, a, b)) + fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> { + self.lub().unsafeties(a, b).compare(b, || { + ty::terr_unsafety_mismatch(expected_found(self, a, b)) }) } diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 79bb19a1e535f..8cce1321d728b 100644 --- a/src/librustc/middle/privacy.rs +++ b/src/librustc/middle/privacy.rs @@ -76,7 +76,7 @@ impl<'v> Visitor<'v> for ParentVisitor { // method to the root. In this case, if the trait is private, then // parent all the methods to the trait to indicate that they're // private. - ast::ItemTrait(_, _, _, ref methods) if item.vis != ast::Public => { + ast::ItemTrait(_, _, _, _, ref methods) if item.vis != ast::Public => { for m in methods.iter() { match *m { ast::ProvidedMethod(ref m) => { @@ -241,7 +241,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // undefined symbols at linkage time if this case is not handled. // // * Private trait impls for private types can be completely ignored - ast::ItemImpl(_, _, ref ty, ref impl_items) => { + ast::ItemImpl(_, _, _, ref ty, ref impl_items) => { let public_ty = match ty.node { ast::TyPath(_, id) => { match self.tcx.def_map.borrow()[id].clone() { @@ -282,7 +282,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> { // Default methods on traits are all public so long as the trait // is public - ast::ItemTrait(_, _, _, ref methods) if public_first => { + ast::ItemTrait(_, _, _, _, ref methods) if public_first => { for method in methods.iter() { match *method { ast::ProvidedMethod(ref m) => { @@ -611,7 +611,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> { // invoked, and the struct/enum itself is private. Crawl // back up the chains to find the relevant struct/enum that // was private. - ast::ItemImpl(_, _, ref ty, _) => { + ast::ItemImpl(_, _, _, ref ty, _) => { let id = match ty.node { ast::TyPath(_, id) => id, _ => return Some((err_span, err_msg, None)), @@ -1096,7 +1096,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { match item.node { // implementations of traits don't need visibility qualifiers because // that's controlled by having the trait in scope. - ast::ItemImpl(_, Some(..), _, ref impl_items) => { + ast::ItemImpl(_, _, Some(..), _, ref impl_items) => { check_inherited(item.span, item.vis, "visibility qualifiers have no effect on trait \ impls"); @@ -1134,7 +1134,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { } } - ast::ItemTrait(_, _, _, ref methods) => { + ast::ItemTrait(_, _, _, _, ref methods) => { for m in methods.iter() { match *m { ast::ProvidedMethod(ref m) => { @@ -1175,7 +1175,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { }; check_inherited(tcx, item.span, item.vis); match item.node { - ast::ItemImpl(_, _, _, ref impl_items) => { + ast::ItemImpl(_, _, _, _, ref impl_items) => { for impl_item in impl_items.iter() { match *impl_item { ast::MethodImplItem(ref m) => { @@ -1198,7 +1198,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> { ast::ItemStruct(ref def, _) => check_struct(&**def), - ast::ItemTrait(_, _, _, ref methods) => { + ast::ItemTrait(_, _, _, _, ref methods) => { for m in methods.iter() { match *m { ast::RequiredMethod(..) => {} @@ -1305,7 +1305,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // namespace (the contents have their own privacies). ast::ItemForeignMod(_) => {} - ast::ItemTrait(_, _, ref bounds, _) => { + ast::ItemTrait(_, _, _, ref bounds, _) => { if !self.trait_is_public(item.id) { return } @@ -1320,7 +1320,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> { // (i.e. we could just return here to not check them at // all, or some worse estimation of whether an impl is // publicly visible. - ast::ItemImpl(ref g, ref trait_ref, ref self_, ref impl_items) => { + ast::ItemImpl(_, ref g, ref trait_ref, ref self_, ref impl_items) => { // `impl [... for] Private` is never visible. let self_contains_private; // impl [... for] Public<...>, but not `impl [... for] diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index fa02c940aa754..38d3b859c9d22 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -55,7 +55,7 @@ fn item_might_be_inlined(item: &ast::Item) -> bool { } match item.node { - ast::ItemImpl(ref generics, _, _, _) | + ast::ItemImpl(_, ref generics, _, _, _) | ast::ItemFn(_, _, _, ref generics, _) => { generics_require_inlining(generics) } @@ -216,7 +216,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { .map .expect_item(impl_did.node) .node { - ast::ItemImpl(ref generics, _, _, _) => { + ast::ItemImpl(_, ref generics, _, _, _) => { generics_require_inlining(generics) } _ => false diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index f2c83291b79e7..c6fdd845ea775 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1432,7 +1432,7 @@ impl<'a> Resolver<'a> { parent } - ItemImpl(_, None, ref ty, ref impl_items) => { + ItemImpl(_, _, None, ref ty, ref impl_items) => { // If this implements an anonymous trait, then add all the // methods within to a new module, if the type was defined // within this module. @@ -1581,9 +1581,9 @@ impl<'a> Resolver<'a> { parent } - ItemImpl(_, Some(_), _, _) => parent, + ItemImpl(_, _, Some(_), _, _) => parent, - ItemTrait(_, _, _, ref items) => { + ItemTrait(_, _, _, _, ref items) => { let name_bindings = self.add_child(name, parent.clone(), @@ -4230,7 +4230,8 @@ impl<'a> Resolver<'a> { }); } - ItemImpl(ref generics, + ItemImpl(_, + ref generics, ref implemented_traits, ref self_type, ref impl_items) => { @@ -4241,7 +4242,7 @@ impl<'a> Resolver<'a> { impl_items.as_slice()); } - ItemTrait(ref generics, ref unbound, ref bounds, ref trait_items) => { + ItemTrait(_, ref generics, ref unbound, ref bounds, ref trait_items) => { // Create a new rib for the self type. let mut self_type_rib = Rib::new(ItemRibKind); diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs index ee0fc32702064..48d6ac847d8d0 100644 --- a/src/librustc/middle/resolve_lifetime.rs +++ b/src/librustc/middle/resolve_lifetime.rs @@ -106,7 +106,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { ast::ItemTy(_, ref generics) | ast::ItemEnum(_, ref generics) | ast::ItemStruct(_, ref generics) | - ast::ItemTrait(ref generics, _, _, _) => { + ast::ItemTrait(_, ref generics, _, _, _) => { // These kinds of items have only early bound lifetime parameters. let lifetimes = &generics.lifetimes; self.with(EarlyScope(subst::TypeSpace, lifetimes, &ROOT_SCOPE), |this| { @@ -114,7 +114,7 @@ impl<'a, 'v> Visitor<'v> for LifetimeContext<'a> { visit::walk_item(this, item); }); } - ast::ItemImpl(ref generics, _, _, _) => { + ast::ItemImpl(_, ref generics, _, _, _) => { // Impls have both early- and late-bound lifetimes. self.visit_early_late(subst::TypeSpace, generics, |this| { this.check_lifetime_defs(&generics.lifetimes); diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs index c3c4acd8191c0..8b31132f73621 100644 --- a/src/librustc/middle/traits/select.rs +++ b/src/librustc/middle/traits/select.rs @@ -791,7 +791,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // provide an impl, but only for suitable `fn` pointers ty::ty_bare_fn(ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::FnSig { inputs: _, @@ -1505,7 +1505,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { let self_ty = self.infcx.shallow_resolve(obligation.self_ty()); let sig = match self_ty.sty { ty::ty_bare_fn(ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, ref sig }) => { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 98d4761508a28..d6fd3d9a94388 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -80,7 +80,7 @@ use std::rc::Rc; use std::collections::enum_set::{EnumSet, CLike}; use std::collections::hash_map::{HashMap, Occupied, Vacant}; use syntax::abi; -use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, FnStyle, Ident, ItemTrait, LOCAL_CRATE}; +use syntax::ast::{CrateNum, DefId, DUMMY_NODE_ID, Ident, ItemTrait, LOCAL_CRATE}; use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField}; use syntax::ast::{Visibility}; @@ -908,14 +908,14 @@ pub fn type_escapes_depth(ty: Ty, depth: uint) -> bool { #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct BareFnTy<'tcx> { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub abi: abi::Abi, pub sig: FnSig<'tcx>, } #[deriving(Clone, PartialEq, Eq, Hash, Show)] pub struct ClosureTy<'tcx> { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub onceness: ast::Onceness, pub store: TraitStore, pub bounds: ExistentialBounds, @@ -1380,7 +1380,7 @@ impl Copy for expected_found {} #[deriving(Clone, Show)] pub enum type_err<'tcx> { terr_mismatch, - terr_fn_style_mismatch(expected_found), + terr_unsafety_mismatch(expected_found), terr_onceness_mismatch(expected_found), terr_abi_mismatch(expected_found), terr_mutability, @@ -1915,6 +1915,8 @@ pub struct Polytype<'tcx> { /// As `Polytype` but for a trait ref. pub struct TraitDef<'tcx> { + pub unsafety: ast::Unsafety, + /// Generic type definitions. Note that `Self` is listed in here /// as having a single bound, the trait itself (e.g., in the trait /// `Eq`, there is a single bound `Self : Eq`). This is so that @@ -2354,7 +2356,7 @@ pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, let input_args = input_tys.iter().map(|ty| *ty).collect(); mk_bare_fn(cx, BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: FnSig { inputs: input_args, @@ -3994,7 +3996,7 @@ pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, ty::mk_closure( cx, - ty::ClosureTy {fn_style: b.fn_style, + ty::ClosureTy {unsafety: b.unsafety, onceness: ast::Many, store: store, bounds: bounds, @@ -4404,7 +4406,7 @@ pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String { match *err { terr_cyclic_ty => "cyclic type of infinite size".to_string(), terr_mismatch => "types differ".to_string(), - terr_fn_style_mismatch(values) => { + terr_unsafety_mismatch(values) => { format!("expected {} fn, found {} fn", values.expected.to_string(), values.found.to_string()) @@ -4572,7 +4574,7 @@ pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) match cx.map.find(id.node) { Some(ast_map::NodeItem(item)) => { match item.node { - ItemTrait(_, _, _, ref ms) => { + ItemTrait(_, _, _, _, ref ms) => { let (_, p) = ast_util::split_trait_methods(ms.as_slice()); p.iter() @@ -4739,7 +4741,7 @@ pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) match cx.map.find(id.node) { Some(ast_map::NodeItem(item)) => { match item.node { - ast::ItemImpl(_, ref opt_trait, _, _) => { + ast::ItemImpl(_, _, ref opt_trait, _, _) => { match opt_trait { &Some(ref t) => { Some(ty::node_id_to_trait_ref(cx, t.ref_id)) @@ -5720,7 +5722,7 @@ pub fn trait_id_of_impl(tcx: &ctxt, match node { ast_map::NodeItem(item) => { match item.node { - ast::ItemImpl(_, Some(ref trait_ref), _, _) => { + ast::ItemImpl(_, _, Some(ref trait_ref), _, _) => { Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id) } _ => None @@ -5871,12 +5873,12 @@ pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 { } ty_bare_fn(ref b) => { byte!(14); - hash!(b.fn_style); + hash!(b.unsafety); hash!(b.abi); } ty_closure(ref c) => { byte!(15); - hash!(c.fn_style); + hash!(c.unsafety); hash!(c.onceness); hash!(c.bounds); match c.store { diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index 63ee71dc6a51a..5d0c584864dbc 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -563,7 +563,7 @@ pub fn super_fold_bare_fn_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, { ty::BareFnTy { sig: fty.sig.fold_with(this), abi: fty.abi, - fn_style: fty.fn_style } + unsafety: fty.unsafety } } pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, @@ -573,7 +573,7 @@ pub fn super_fold_closure_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T, ty::ClosureTy { store: fty.store.fold_with(this), sig: fty.sig.fold_with(this), - fn_style: fty.fn_style, + unsafety: fty.unsafety, onceness: fty.onceness, bounds: fty.bounds.fold_with(this), abi: fty.abi, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index f8276fa8f84d4..74e312803f31a 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -259,16 +259,16 @@ pub fn trait_ref_to_string<'tcx>(cx: &ctxt<'tcx>, pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { fn bare_fn_to_string<'tcx>(cx: &ctxt<'tcx>, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, abi: abi::Abi, ident: Option, sig: &ty::FnSig<'tcx>) -> String { let mut s = String::new(); - match fn_style { - ast::NormalFn => {} - _ => { - s.push_str(fn_style.to_string().as_slice()); + match unsafety { + ast::Unsafety::Normal => {} + ast::Unsafety::Unsafe => { + s.push_str(unsafety.to_string().as_slice()); s.push(' '); } }; @@ -302,10 +302,10 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { } } - match cty.fn_style { - ast::NormalFn => {} - _ => { - s.push_str(cty.fn_style.to_string().as_slice()); + match cty.unsafety { + ast::Unsafety::Normal => {} + ast::Unsafety::Unsafe => { + s.push_str(cty.unsafety.to_string().as_slice()); s.push(' '); } }; @@ -414,7 +414,7 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String { closure_to_string(cx, &**f) } ty_bare_fn(ref f) => { - bare_fn_to_string(cx, f.fn_style, f.abi, None, &f.sig) + bare_fn_to_string(cx, f.unsafety, f.abi, None, &f.sig) } ty_infer(infer_ty) => infer_ty_to_string(cx, infer_ty), ty_err => "[type error]".to_string(), @@ -1001,8 +1001,8 @@ impl<'tcx> Repr<'tcx> for ast::Visibility { impl<'tcx> Repr<'tcx> for ty::BareFnTy<'tcx> { fn repr(&self, tcx: &ctxt<'tcx>) -> String { - format!("BareFnTy {{fn_style: {}, abi: {}, sig: {}}}", - self.fn_style, + format!("BareFnTy {{unsafety: {}, abi: {}, sig: {}}}", + self.unsafety, self.abi.to_string(), self.sig.repr(tcx)) } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index dda3754cf7371..6a50af3bc7992 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -270,7 +270,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> { -> Ty<'tcx> { ty::mk_closure(self.infcx.tcx, ty::ClosureTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, onceness: ast::Many, store: ty::RegionTraitStore(region_bound, ast::MutMutable), bounds: ty::region_existential_bound(region_bound), diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 329241b24e652..712d6217dde81 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -282,7 +282,7 @@ impl <'l, 'tcx> DxrVisitor<'l, 'tcx> { NodeItem(item) => { scope_id = item.id; match item.node { - ast::ItemImpl(_, _, ref ty, _) => { + ast::ItemImpl(_, _, _, ref ty, _) => { let mut result = String::from_str("<"); result.push_str(ty_to_string(&**ty).as_slice()); @@ -1040,7 +1040,8 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { self.process_const(item, &**typ, &**expr), ast::ItemStruct(ref def, ref ty_params) => self.process_struct(item, &**def, ty_params), ast::ItemEnum(ref def, ref ty_params) => self.process_enum(item, def, ty_params), - ast::ItemImpl(ref ty_params, + ast::ItemImpl(_, + ref ty_params, ref trait_ref, ref typ, ref impl_items) => { @@ -1050,7 +1051,7 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DxrVisitor<'l, 'tcx> { &**typ, impl_items) } - ast::ItemTrait(ref generics, _, ref trait_refs, ref methods) => + ast::ItemTrait(_, ref generics, _, ref trait_refs, ref methods) => self.process_trait(item, generics, trait_refs, methods), ast::ItemMod(ref m) => self.process_mod(item, m), ast::ItemTy(ref ty, ref ty_params) => { diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index b2578fdbc054b..83779ffbe161c 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2304,7 +2304,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) { let mut v = TransItemVisitor{ ccx: ccx }; v.visit_block(&**body); } - ast::ItemImpl(ref generics, _, _, ref impl_items) => { + ast::ItemImpl(_, ref generics, _, _, ref impl_items) => { meth::trans_impl(ccx, item.ident, impl_items.as_slice(), diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs index 67e1735d9a3b7..81d44d8441479 100644 --- a/src/librustc_trans/trans/callee.rs +++ b/src/librustc_trans/trans/callee.rs @@ -278,7 +278,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( // which is the fn pointer, and `args`, which is the arguments tuple. let (input_tys, output_ty) = match bare_fn_ty.sty { - ty::ty_bare_fn(ty::BareFnTy { fn_style: ast::NormalFn, + ty::ty_bare_fn(ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: synabi::Rust, sig: ty::FnSig { inputs: ref input_tys, output: output_ty, @@ -294,7 +294,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>( }; let tuple_input_ty = ty::mk_tup(tcx, input_tys.to_vec()); let tuple_fn_ty = ty::mk_bare_fn(tcx, - ty::BareFnTy { fn_style: ast::NormalFn, + ty::BareFnTy { unsafety: ast::Unsafety::Normal, abi: synabi::RustCall, sig: ty::FnSig { inputs: vec![bare_fn_ty_ref, diff --git a/src/librustc_trans/trans/debuginfo.rs b/src/librustc_trans/trans/debuginfo.rs index 66258f228cd7b..3f8c951786dfa 100644 --- a/src/librustc_trans/trans/debuginfo.rs +++ b/src/librustc_trans/trans/debuginfo.rs @@ -433,8 +433,8 @@ impl<'tcx> TypeMap<'tcx> { &trait_data.principal.substs, &mut unique_type_id); }, - ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { - if fn_style == ast::UnsafeFn { + ty::ty_bare_fn(ty::BareFnTy{ unsafety, abi, ref sig } ) => { + if unsafety == ast::Unsafety::Unsafe { unique_type_id.push_str("unsafe "); } @@ -551,13 +551,13 @@ impl<'tcx> TypeMap<'tcx> { cx: &CrateContext<'a, 'tcx>, closure_ty: ty::ClosureTy<'tcx>, unique_type_id: &mut String) { - let ty::ClosureTy { fn_style, + let ty::ClosureTy { unsafety, onceness, store, ref bounds, ref sig, abi: _ } = closure_ty; - if fn_style == ast::UnsafeFn { + if unsafety == ast::Unsafety::Unsafe { unique_type_id.push_str("unsafe "); } @@ -3767,8 +3767,8 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, push_item_name(cx, trait_data.principal.def_id, false, output); push_type_params(cx, &trait_data.principal.substs, output); }, - ty::ty_bare_fn(ty::BareFnTy{ fn_style, abi, ref sig } ) => { - if fn_style == ast::UnsafeFn { + ty::ty_bare_fn(ty::BareFnTy{ unsafety, abi, ref sig } ) => { + if unsafety == ast::Unsafety::Unsafe { output.push_str("unsafe "); } @@ -3810,13 +3810,13 @@ fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, } } }, - ty::ty_closure(box ty::ClosureTy { fn_style, + ty::ty_closure(box ty::ClosureTy { unsafety, onceness, store, ref sig, .. // omitting bounds ... }) => { - if fn_style == ast::UnsafeFn { + if unsafety == ast::Unsafety::Unsafe { output.push_str("unsafe "); } diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs index 762aed3dfa8ea..b3272a1475351 100644 --- a/src/librustc_typeck/astconv.rs +++ b/src/librustc_typeck/astconv.rs @@ -924,7 +924,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( tcx.sess.span_err(ast_ty.span, "variadic function must have C calling convention"); } - ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.fn_style, bf.abi, &*bf.decl)) + ty::mk_bare_fn(tcx, ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl)) } ast::TyClosure(ref f) => { // Use corresponding trait store to figure out default bounds @@ -935,7 +935,7 @@ pub fn ast_ty_to_ty<'tcx, AC: AstConv<'tcx>, RS: RegionScope>( None, f.bounds.as_slice()); let fn_decl = ty_of_closure(this, - f.fn_style, + f.unsafety, f.onceness, bounds, ty::RegionTraitStore( @@ -1082,7 +1082,7 @@ struct SelfInfo<'a, 'tcx> { pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( this: &AC, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, untransformed_self_ty: Ty<'tcx>, explicit_self: &ast::ExplicitSelf, decl: &ast::FnDecl, @@ -1094,22 +1094,22 @@ pub fn ty_of_method<'tcx, AC: AstConv<'tcx>>( }); let (bare_fn_ty, optional_explicit_self_category) = ty_of_method_or_bare_fn(this, - fn_style, + unsafety, abi, self_info, decl); (bare_fn_ty, optional_explicit_self_category.unwrap()) } -pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, fn_style: ast::FnStyle, abi: abi::Abi, +pub fn ty_of_bare_fn<'tcx, AC: AstConv<'tcx>>(this: &AC, unsafety: ast::Unsafety, abi: abi::Abi, decl: &ast::FnDecl) -> ty::BareFnTy<'tcx> { - let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, fn_style, abi, None, decl); + let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl); bare_fn_ty } fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( this: &AC, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, abi: abi::Abi, opt_self_info: Option>, decl: &ast::FnDecl) @@ -1207,7 +1207,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx, AC: AstConv<'tcx>>( }; (ty::BareFnTy { - fn_style: fn_style, + unsafety: unsafety, abi: abi, sig: ty::FnSig { inputs: self_and_input_tys, @@ -1301,7 +1301,7 @@ fn determine_explicit_self_category<'a, 'tcx, AC: AstConv<'tcx>, pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( this: &AC, - fn_style: ast::FnStyle, + unsafety: ast::Unsafety, onceness: ast::Onceness, bounds: ty::ExistentialBounds, store: ty::TraitStore, @@ -1346,7 +1346,7 @@ pub fn ty_of_closure<'tcx, AC: AstConv<'tcx>>( debug!("ty_of_closure: output_ty={}", output_ty.repr(this.tcx())); ty::ClosureTy { - fn_style: fn_style, + unsafety: unsafety, onceness: onceness, store: store, bounds: bounds, diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs index 692bd31638e34..e3fec2c8b1df2 100644 --- a/src/librustc_typeck/check/closure.rs +++ b/src/librustc_typeck/check/closure.rs @@ -89,7 +89,7 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, let mut fn_ty = astconv::ty_of_closure( fcx, - ast::NormalFn, + ast::Unsafety::Normal, ast::Many, // The `RegionTraitStore` and region_existential_bounds @@ -119,7 +119,7 @@ fn check_unboxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, fcx.write_ty(expr.id, closure_type); check_fn(fcx.ccx, - ast::NormalFn, + ast::Unsafety::Normal, expr.id, &fn_ty.sig, decl, @@ -304,7 +304,7 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // construct the function type let fn_ty = astconv::ty_of_closure(fcx, - ast::NormalFn, + ast::Unsafety::Normal, expected_onceness, expected_bounds, store, @@ -321,9 +321,9 @@ fn check_boxed_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, // style inferred for it, then check it under its parent's style. // Otherwise, use its own let (inherited_style, inherited_style_id) = match store { - ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style, + ty::RegionTraitStore(..) => (fcx.ps.borrow().unsafety, fcx.ps.borrow().def), - ty::UniqTraitStore => (ast::NormalFn, expr.id) + ty::UniqTraitStore => (ast::Unsafety::Normal, expr.id) }; check_fn(fcx.ccx, diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index 3c7cecc96a320..7463652a93136 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -115,7 +115,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { // Create the final `MethodCallee`. let fty = ty::mk_bare_fn(self.tcx(), ty::BareFnTy { sig: method_sig, - fn_style: pick.method_ty.fty.fn_style, + unsafety: pick.method_ty.fty.unsafety, abi: pick.method_ty.fty.abi.clone(), }); let callee = MethodCallee { diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs index d081b97b71ad8..d97a9c9e39b19 100644 --- a/src/librustc_typeck/check/method/mod.rs +++ b/src/librustc_typeck/check/method/mod.rs @@ -205,7 +205,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>, let transformed_self_ty = fn_sig.inputs[0]; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { sig: fn_sig, - fn_style: bare_fn_ty.fn_style, + unsafety: bare_fn_ty.unsafety, abi: bare_fn_ty.abi.clone(), }); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index fdc57579d072b..e0df94745d6a9 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -180,35 +180,33 @@ enum Expectation<'tcx> { impl<'tcx> Copy for Expectation<'tcx> {} -#[deriving(Clone)] -pub struct FnStyleState { +#[deriving(Copy, Clone)] +pub struct UnsafetyState { pub def: ast::NodeId, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, from_fn: bool } -impl Copy for FnStyleState {} - -impl FnStyleState { - pub fn function(fn_style: ast::FnStyle, def: ast::NodeId) -> FnStyleState { - FnStyleState { def: def, fn_style: fn_style, from_fn: true } +impl UnsafetyState { + pub fn function(unsafety: ast::Unsafety, def: ast::NodeId) -> UnsafetyState { + UnsafetyState { def: def, unsafety: unsafety, from_fn: true } } - pub fn recurse(&mut self, blk: &ast::Block) -> FnStyleState { - match self.fn_style { + pub fn recurse(&mut self, blk: &ast::Block) -> UnsafetyState { + match self.unsafety { // If this unsafe, then if the outer function was already marked as // unsafe we shouldn't attribute the unsafe'ness to the block. This // way the block can be warned about instead of ignoring this // extraneous block (functions are never warned about). - ast::UnsafeFn if self.from_fn => *self, + ast::Unsafety::Unsafe if self.from_fn => *self, - fn_style => { - let (fn_style, def) = match blk.rules { - ast::UnsafeBlock(..) => (ast::UnsafeFn, blk.id), - ast::DefaultBlock => (fn_style, self.def), + unsafety => { + let (unsafety, def) = match blk.rules { + ast::UnsafeBlock(..) => (ast::Unsafety::Unsafe, blk.id), + ast::DefaultBlock => (unsafety, self.def), }; - FnStyleState{ def: def, - fn_style: fn_style, + UnsafetyState{ def: def, + unsafety: unsafety, from_fn: false } } } @@ -240,7 +238,7 @@ pub struct FnCtxt<'a, 'tcx: 'a> { ret_ty: ty::FnOutput<'tcx>, - ps: RefCell, + ps: RefCell, inh: &'a Inherited<'a, 'tcx>, @@ -312,7 +310,7 @@ pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, writeback_errors: Cell::new(false), err_count_on_creation: ccx.tcx.sess.err_count(), ret_ty: rty, - ps: RefCell::new(FnStyleState::function(ast::NormalFn, 0)), + ps: RefCell::new(UnsafetyState::function(ast::Unsafety::Normal, 0)), inh: inh, ccx: ccx } @@ -374,7 +372,7 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, match fty.sty { ty::ty_bare_fn(ref fn_ty) => { let inh = Inherited::new(ccx.tcx, param_env); - let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig, + let fcx = check_fn(ccx, fn_ty.unsafety, id, &fn_ty.sig, decl, id, body, &inh); vtable::select_all_fcx_obligations_or_error(&fcx); @@ -476,8 +474,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for GatherLocalsVisitor<'a, 'tcx> { /// * ... /// * inherited: other fields inherited from the enclosing fn (if any) fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, - fn_style: ast::FnStyle, - fn_style_id: ast::NodeId, + unsafety: ast::Unsafety, + unsafety_id: ast::NodeId, fn_sig: &ty::FnSig<'tcx>, decl: &ast::FnDecl, fn_id: ast::NodeId, @@ -506,7 +504,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>, writeback_errors: Cell::new(false), err_count_on_creation: err_count_on_creation, ret_ty: ret_ty, - ps: RefCell::new(FnStyleState::function(fn_style, fn_style_id)), + ps: RefCell::new(UnsafetyState::function(unsafety, unsafety_id)), inh: inherited, ccx: ccx }; @@ -597,7 +595,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id); check_bare_fn(ccx, &**decl, &**body, it.id, fn_pty.ty, param_env); } - ast::ItemImpl(_, ref opt_trait_ref, _, ref impl_items) => { + ast::ItemImpl(_, _, ref opt_trait_ref, _, ref impl_items) => { debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id); let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id)); @@ -627,7 +625,7 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) { } } - ast::ItemTrait(_, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, _, ref trait_methods) => { let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id)); for trait_method in trait_methods.iter() { match *trait_method { @@ -4493,8 +4491,8 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expected: Expectation<'tcx>) { let prev = { let mut fcx_ps = fcx.ps.borrow_mut(); - let fn_style_state = fcx_ps.recurse(blk); - replace(&mut *fcx_ps, fn_style_state) + let unsafety_state = fcx_ps.recurse(blk); + replace(&mut *fcx_ps, unsafety_state) }; let mut warned = false; @@ -5696,7 +5694,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) { (n_tps, inputs, ty::FnConverging(output)) }; let fty = ty::mk_bare_fn(tcx, ty::BareFnTy { - fn_style: ast::UnsafeFn, + unsafety: ast::Unsafety::Unsafe, abi: abi::RustIntrinsic, sig: FnSig { inputs: inputs, diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index defad95f749bd..a55f3c6191940 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -50,6 +50,7 @@ use util::ppaux::Repr; mod orphan; mod overlap; +mod unsafety; fn get_base_type<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>, span: Span, @@ -145,7 +146,7 @@ impl<'a, 'tcx, 'v> visit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> { //debug!("(checking coherence) item '{}'", token::get_ident(item.ident)); match item.node { - ItemImpl(_, ref opt_trait, _, _) => { + ItemImpl(_, _, ref opt_trait, _, _) => { match opt_trait.clone() { Some(opt_trait) => { self.cc.check_implementation(item, &[opt_trait]); @@ -325,7 +326,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Converts an implementation in the AST to a vector of items. fn create_impl_from_item(&self, item: &Item) -> Vec { match item.node { - ItemImpl(_, ref trait_refs, _, ref ast_items) => { + ItemImpl(_, _, ref trait_refs, _, ref ast_items) => { let mut items: Vec = ast_items.iter() .map(|ast_item| { @@ -620,6 +621,7 @@ pub fn check_coherence(crate_context: &CrateCtxt) { inference_context: new_infer_ctxt(crate_context.tcx), inherent_impls: RefCell::new(FnvHashMap::new()), }.check(crate_context.tcx.map.krate()); + unsafety::check(crate_context.tcx); orphan::check(crate_context.tcx); overlap::check(crate_context.tcx); } diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs index dc3afaae35f61..1803bf766dda1 100644 --- a/src/librustc_typeck/coherence/orphan.rs +++ b/src/librustc_typeck/coherence/orphan.rs @@ -44,7 +44,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { fn visit_item(&mut self, item: &'v ast::Item) { let def_id = ast_util::local_def(item.id); match item.node { - ast::ItemImpl(_, None, _, _) => { + ast::ItemImpl(_, _, None, _, _) => { // For inherent impls, self type must be a nominal type // defined in this crate. debug!("coherence2::orphan check: inherent impl {}", item.repr(self.tcx)); @@ -64,7 +64,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OrphanChecker<'cx, 'tcx> { } } } - ast::ItemImpl(_, Some(_), _, _) => { + ast::ItemImpl(_, _, Some(_), _, _) => { // "Trait" impl debug!("coherence2::orphan check: trait impl {}", item.repr(self.tcx)); if traits::is_orphan_impl(self.tcx, def_id) { diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs new file mode 100644 index 0000000000000..07a84846c47ad --- /dev/null +++ b/src/librustc_typeck/coherence/unsafety.rs @@ -0,0 +1,77 @@ +// Copyright 2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! Unsafety checker: every impl either implements a trait defined in this +//! crate or pertains to a type defined in this crate. + +use middle::ty; +use syntax::ast::{Item, ItemImpl}; +use syntax::ast; +use syntax::ast_util; +use syntax::visit; +use util::ppaux::UserString; + +pub fn check(tcx: &ty::ctxt) { + let mut orphan = UnsafetyChecker { tcx: tcx }; + visit::walk_crate(&mut orphan, tcx.map.krate()); +} + +struct UnsafetyChecker<'cx, 'tcx:'cx> { + tcx: &'cx ty::ctxt<'tcx> +} + +impl<'cx, 'tcx,'v> visit::Visitor<'v> for UnsafetyChecker<'cx, 'tcx> { + fn visit_item(&mut self, item: &'v ast::Item) { + match item.node { + ast::ItemImpl(unsafety, _, _, _, _) => { + match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) { + None => { + // Inherent impl. + match unsafety { + ast::Unsafety::Normal => { /* OK */ } + ast::Unsafety::Unsafe => { + self.tcx.sess.span_err( + item.span, + "inherent impls cannot be declared as unsafe"); + } + } + } + + Some(trait_ref) => { + let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id); + match (trait_def.unsafety, unsafety) { + (ast::Unsafety::Normal, ast::Unsafety::Unsafe) => { + self.tcx.sess.span_err( + item.span, + format!("implementing the trait `{}` is not unsafe", + trait_ref.user_string(self.tcx)).as_slice()); + } + + (ast::Unsafety::Unsafe, ast::Unsafety::Normal) => { + self.tcx.sess.span_err( + item.span, + format!("the trait `{}` requires an `unsafe impl` declaration", + trait_ref.user_string(self.tcx)).as_slice()); + } + + (ast::Unsafety::Unsafe, ast::Unsafety::Unsafe) | + (ast::Unsafety::Normal, ast::Unsafety::Normal) => { + /* OK */ + } + } + } + } + } + _ => { } + } + + visit::walk_item(self, item); + } +} diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 09cf708047601..61b8e6c956cab 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -258,7 +258,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, trait_def: &ty::TraitDef<'tcx>) { let tcx = ccx.tcx; if let ast_map::NodeItem(item) = tcx.map.get(trait_id) { - if let ast::ItemTrait(_, _, _, ref trait_items) = item.node { + if let ast::ItemTrait(_, _, _, _, ref trait_items) = item.node { // For each method, construct a suitable ty::Method and // store it into the `tcx.impl_or_trait_items` table: for trait_item in trait_items.iter() { @@ -277,7 +277,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, &m.explicit_self, m.abi, &m.generics, - &m.fn_style, + &m.unsafety, &*m.decl) } ast::ProvidedMethod(ref m) => { @@ -291,7 +291,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m.pe_explicit_self(), m.pe_abi(), m.pe_generics(), - &m.pe_fn_style(), + &m.pe_unsafety(), &*m.pe_fn_decl()) } ast::TypeTraitItem(ref at) => { @@ -366,7 +366,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, m_explicit_self: &ast::ExplicitSelf, m_abi: abi::Abi, m_generics: &ast::Generics, - m_fn_style: &ast::FnStyle, + m_unsafety: &ast::Unsafety, m_decl: &ast::FnDecl) -> ty::Method<'tcx> { let ty_generics = @@ -386,7 +386,7 @@ fn collect_trait_methods<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let trait_self_ty = ty::mk_self_type(tmcx.tcx(), local_def(trait_id)); astconv::ty_of_method(&tmcx, - *m_fn_style, + *m_unsafety, trait_self_ty, m_explicit_self, m_decl, @@ -572,7 +572,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, method_generics: &m_ty_generics, }; astconv::ty_of_method(&imcx, - m.pe_fn_style(), + m.pe_unsafety(), untransformed_rcvr_ty, m.pe_explicit_self(), &*m.pe_fn_decl(), @@ -586,7 +586,7 @@ fn convert_methods<'a,'tcx,'i,I>(ccx: &CrateCtxt<'a, 'tcx>, method_generics: &m_ty_generics, }; astconv::ty_of_method(&tmcx, - m.pe_fn_style(), + m.pe_unsafety(), untransformed_rcvr_ty, m.pe_explicit_self(), &*m.pe_fn_decl(), @@ -1045,7 +1045,8 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { enum_definition.variants.as_slice(), generics); }, - ast::ItemImpl(ref generics, + ast::ItemImpl(_, + ref generics, ref opt_trait_ref, ref selfty, ref impl_items) => { @@ -1144,7 +1145,7 @@ pub fn convert(ccx: &CrateCtxt, it: &ast::Item) { AllowEqConstraints::DontAllow); } }, - ast::ItemTrait(_, _, _, ref trait_methods) => { + ast::ItemTrait(_, _, _, _, ref trait_methods) => { let trait_def = trait_def_of_item(ccx, it); debug!("trait_def: ident={} trait_def={}", @@ -1335,12 +1336,13 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, return def.clone(); } - let (generics, unbound, bounds, items) = match it.node { - ast::ItemTrait(ref generics, + let (unsafety, generics, unbound, bounds, items) = match it.node { + ast::ItemTrait(unsafety, + ref generics, ref unbound, ref supertraits, ref items) => { - (generics, unbound, supertraits, items.as_slice()) + (unsafety, generics, unbound, supertraits, items.as_slice()) } ref s => { tcx.sess.span_bug( @@ -1369,6 +1371,7 @@ pub fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, let substs = mk_item_substs(ccx, &ty_generics); let trait_def = Rc::new(ty::TraitDef { + unsafety: unsafety, generics: ty_generics, bounds: bounds, trait_ref: Rc::new(ty::TraitRef { @@ -1446,7 +1449,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) tcx.tcache.borrow_mut().insert(local_def(it.id), pty.clone()); return pty; } - ast::ItemFn(ref decl, fn_style, abi, ref generics, _) => { + ast::ItemFn(ref decl, unsafety, abi, ref generics, _) => { let ty_generics = ty_generics_for_fn_or_method( ccx, generics, @@ -1457,7 +1460,7 @@ pub fn ty_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item) ccx: ccx, generics: &ty_generics, }; - astconv::ty_of_bare_fn(&fcx, fn_style, abi, &**decl) + astconv::ty_of_bare_fn(&fcx, unsafety, abi, &**decl) }; let pty = Polytype { generics: ty_generics, @@ -2151,7 +2154,7 @@ pub fn ty_of_foreign_fn_decl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, ccx.tcx, ty::BareFnTy { abi: abi, - fn_style: ast::UnsafeFn, + unsafety: ast::Unsafety::Unsafe, sig: ty::FnSig {inputs: input_tys, output: output, variadic: decl.variadic} diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs index 32c732c246716..d55d642f74651 100644 --- a/src/librustc_typeck/lib.rs +++ b/src/librustc_typeck/lib.rs @@ -226,7 +226,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt, _ => () } let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::FnSig { inputs: Vec::new(), @@ -274,7 +274,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt, } let se_ty = ty::mk_bare_fn(tcx, ty::BareFnTy { - fn_style: ast::NormalFn, + unsafety: ast::Unsafety::Normal, abi: abi::Rust, sig: ty::FnSig { inputs: vec!( diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs index bd7db560d9e4a..8fe14bae0f5bc 100644 --- a/src/librustc_typeck/variance.rs +++ b/src/librustc_typeck/variance.rs @@ -358,7 +358,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for TermsContext<'a, 'tcx> { match item.node { ast::ItemEnum(_, ref generics) | ast::ItemStruct(_, ref generics) | - ast::ItemTrait(ref generics, _, _, _) => { + ast::ItemTrait(_, ref generics, _, _, _) => { for (i, p) in generics.lifetimes.iter().enumerate() { let id = p.lifetime.id; self.add_inferred(item.id, RegionParam, TypeSpace, i, id); diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3ee07df6ed447..a7d7c5207550b 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -161,6 +161,7 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, let trait_def = ty::lookup_trait_def(tcx, did); let (bounds, default_unbound) = trait_def.bounds.clean(cx); clean::Trait { + unsafety: def.unsafety, generics: (&def.generics, subst::TypeSpace).clean(cx), items: items.collect(), bounds: bounds, @@ -171,13 +172,13 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt, fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Function { let t = ty::lookup_item_type(tcx, did); let (decl, style) = match t.ty.sty { - ty::ty_bare_fn(ref f) => ((did, &f.sig).clean(cx), f.fn_style), + ty::ty_bare_fn(ref f) => ((did, &f.sig).clean(cx), f.unsafety), _ => panic!("bad function"), }; clean::Function { decl: decl, generics: (&t.generics, subst::FnSpace).clean(cx), - fn_style: style, + unsafety: style, } } @@ -299,10 +300,10 @@ fn build_impl(cx: &DocContext, tcx: &ty::ctxt, let mut item = method.clean(cx); item.inner = match item.inner.clone() { clean::TyMethodItem(clean::TyMethod { - fn_style, decl, self_, generics + unsafety, decl, self_, generics }) => { clean::MethodItem(clean::Method { - fn_style: fn_style, + unsafety: unsafety, decl: decl, self_: self_, generics: generics, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 8045dab6c2d67..92184ce93deec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -740,7 +740,7 @@ impl<'a, 'tcx> Clean for (&'a ty::Generics<'tcx>, subst::ParamSpace) { pub struct Method { pub generics: Generics, pub self_: SelfTy, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub decl: FnDecl, } @@ -768,7 +768,7 @@ impl Clean for ast::Method { inner: MethodItem(Method { generics: self.pe_generics().clean(cx), self_: self.pe_explicit_self().node.clean(cx), - fn_style: self.pe_fn_style().clone(), + unsafety: self.pe_unsafety().clone(), decl: decl, }), } @@ -777,7 +777,7 @@ impl Clean for ast::Method { #[deriving(Clone, Encodable, Decodable)] pub struct TyMethod { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub decl: FnDecl, pub generics: Generics, pub self_: SelfTy, @@ -804,7 +804,7 @@ impl Clean for ast::TypeMethod { visibility: None, stability: get_stability(cx, ast_util::local_def(self.id)), inner: TyMethodItem(TyMethod { - fn_style: self.fn_style.clone(), + unsafety: self.unsafety.clone(), decl: decl, self_: self.explicit_self.node.clean(cx), generics: self.generics.clean(cx), @@ -838,7 +838,7 @@ impl Clean for ast::ExplicitSelf_ { pub struct Function { pub decl: FnDecl, pub generics: Generics, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, } impl Clean for doctree::Function { @@ -853,7 +853,7 @@ impl Clean for doctree::Function { inner: FunctionItem(Function { decl: self.decl.clean(cx), generics: self.generics.clean(cx), - fn_style: self.fn_style, + unsafety: self.unsafety, }), } } @@ -864,7 +864,7 @@ pub struct ClosureDecl { pub lifetimes: Vec, pub decl: FnDecl, pub onceness: ast::Onceness, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub bounds: Vec, } @@ -874,7 +874,7 @@ impl Clean for ast::ClosureTy { lifetimes: self.lifetimes.clean(cx), decl: self.decl.clean(cx), onceness: self.onceness, - fn_style: self.fn_style, + unsafety: self.unsafety, bounds: self.bounds.clean(cx) } } @@ -974,6 +974,7 @@ impl Clean for ast::FunctionRetTy { #[deriving(Clone, Encodable, Decodable)] pub struct Trait { + pub unsafety: ast::Unsafety, pub items: Vec, pub generics: Generics, pub bounds: Vec, @@ -991,6 +992,7 @@ impl Clean for doctree::Trait { visibility: self.vis.clean(cx), stability: self.stab.clean(cx), inner: TraitItem(Trait { + unsafety: self.unsafety, items: self.items.clean(cx), generics: self.generics.clean(cx), bounds: self.bounds.clean(cx), @@ -1111,7 +1113,7 @@ impl<'tcx> Clean for ty::Method<'tcx> { attrs: inline::load_attrs(cx, cx.tcx(), self.def_id), source: Span::empty(), inner: TyMethodItem(TyMethod { - fn_style: self.fty.fn_style, + unsafety: self.fty.unsafety, generics: (&self.generics, subst::FnSpace).clean(cx), self_: self_, decl: (self.def_id, &sig).clean(cx), @@ -1364,7 +1366,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { type_: box mt.ty.clean(cx), }, ty::ty_bare_fn(ref fty) => BareFunction(box BareFunctionDecl { - fn_style: fty.fn_style, + unsafety: fty.unsafety, generics: Generics { lifetimes: Vec::new(), type_params: Vec::new(), @@ -1378,7 +1380,7 @@ impl<'tcx> Clean for ty::Ty<'tcx> { lifetimes: Vec::new(), // FIXME: this looks wrong... decl: (ast_util::local_def(0), &fty.sig).clean(cx), onceness: fty.onceness, - fn_style: fty.fn_style, + unsafety: fty.unsafety, bounds: fty.bounds.clean(cx), }; match fty.store { @@ -1789,7 +1791,7 @@ impl Clean for doctree::Typedef { #[deriving(Clone, Encodable, Decodable, PartialEq)] pub struct BareFunctionDecl { - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub generics: Generics, pub decl: FnDecl, pub abi: String, @@ -1798,7 +1800,7 @@ pub struct BareFunctionDecl { impl Clean for ast::BareFnTy { fn clean(&self, cx: &DocContext) -> BareFunctionDecl { BareFunctionDecl { - fn_style: self.fn_style, + unsafety: self.unsafety, generics: Generics { lifetimes: self.lifetimes.clean(cx), type_params: Vec::new(), @@ -2071,7 +2073,7 @@ impl Clean for ast::ForeignItem { ForeignFunctionItem(Function { decl: decl.clean(cx), generics: generics.clean(cx), - fn_style: ast::UnsafeFn, + unsafety: ast::Unsafety::Unsafe, }) } ast::ForeignItemStatic(ref ty, mutbl) => { diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index 1aac91c4a5c7a..6592ca498dc64 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -129,7 +129,7 @@ pub struct Function { pub name: Ident, pub vis: ast::Visibility, pub stab: Option, - pub fn_style: ast::FnStyle, + pub unsafety: ast::Unsafety, pub whence: Span, pub generics: ast::Generics, } @@ -170,6 +170,7 @@ pub struct Constant { } pub struct Trait { + pub unsafety: ast::Unsafety, pub name: Ident, pub items: Vec, //should be TraitItem pub generics: ast::Generics, @@ -183,6 +184,7 @@ pub struct Trait { } pub struct Impl { + pub unsafety: ast::Unsafety, pub generics: ast::Generics, pub trait_: Option, pub for_: P, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index cf92a71369fa3..6a2929beca22e 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -32,7 +32,7 @@ use html::render::{cache, CURRENT_LOCATION_KEY}; pub struct VisSpace(pub Option); /// Similarly to VisSpace, this structure is used to render a function style with a /// space after it. -pub struct FnStyleSpace(pub ast::FnStyle); +pub struct UnsafetySpace(pub ast::Unsafety); /// Wrapper struct for properly emitting a method declaration. pub struct Method<'a>(pub &'a clean::SelfTy, pub &'a clean::FnDecl); /// Similar to VisSpace, but used for mutability @@ -49,7 +49,7 @@ pub struct WhereClause<'a>(pub &'a clean::Generics); pub struct TyParamBounds<'a>(pub &'a [clean::TyParamBound]); impl Copy for VisSpace {} -impl Copy for FnStyleSpace {} +impl Copy for UnsafetySpace {} impl Copy for MutableSpace {} impl Copy for RawMutableSpace {} @@ -59,9 +59,9 @@ impl VisSpace { } } -impl FnStyleSpace { - pub fn get(&self) -> ast::FnStyle { - let FnStyleSpace(v) = *self; v +impl UnsafetySpace { + pub fn get(&self) -> ast::Unsafety { + let UnsafetySpace(v) = *self; v } } @@ -404,7 +404,7 @@ impl fmt::Show for clean::Type { clean::Primitive(prim) => primitive_link(f, prim, prim.to_string()), clean::Closure(ref decl) => { write!(f, "{style}{lifetimes}|{args}|{bounds}{arrow}", - style = FnStyleSpace(decl.fn_style), + style = UnsafetySpace(decl.unsafety), lifetimes = if decl.lifetimes.len() == 0 { "".to_string() } else { @@ -433,7 +433,7 @@ impl fmt::Show for clean::Type { } clean::Proc(ref decl) => { write!(f, "{style}{lifetimes}proc({args}){bounds}{arrow}", - style = FnStyleSpace(decl.fn_style), + style = UnsafetySpace(decl.unsafety), lifetimes = if decl.lifetimes.len() == 0 { "".to_string() } else { @@ -454,7 +454,7 @@ impl fmt::Show for clean::Type { } clean::BareFunction(ref decl) => { write!(f, "{}{}fn{}{}", - FnStyleSpace(decl.fn_style), + UnsafetySpace(decl.unsafety), match decl.abi.as_slice() { "" => " extern ".to_string(), "\"Rust\"" => "".to_string(), @@ -584,11 +584,11 @@ impl fmt::Show for VisSpace { } } -impl fmt::Show for FnStyleSpace { +impl fmt::Show for UnsafetySpace { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.get() { - ast::UnsafeFn => write!(f, "unsafe "), - ast::NormalFn => Ok(()) + ast::Unsafety::Unsafe => write!(f, "unsafe "), + ast::Unsafety::Normal => Ok(()) } } } diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 542169620e648..1977b6320d0ec 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -58,7 +58,7 @@ use rustc::util::nodemap::NodeSet; use clean; use doctree; use fold::DocFolder; -use html::format::{VisSpace, Method, FnStyleSpace, MutableSpace, Stability}; +use html::format::{VisSpace, Method, UnsafetySpace, MutableSpace, Stability}; use html::format::{ConciseStability, TyParamBounds, WhereClause}; use html::highlight; use html::item_type::ItemType; @@ -1664,10 +1664,10 @@ fn item_static(w: &mut fmt::Formatter, it: &clean::Item, fn item_function(w: &mut fmt::Formatter, it: &clean::Item, f: &clean::Function) -> fmt::Result { - try!(write!(w, "
{vis}{fn_style}fn \
+    try!(write!(w, "
{vis}{unsafety}fn \
                     {name}{generics}{decl}{where_clause}
", vis = VisSpace(it.visibility), - fn_style = FnStyleSpace(f.fn_style), + unsafety = UnsafetySpace(f.unsafety), name = it.name.as_ref().unwrap().as_slice(), generics = f.generics, where_clause = WhereClause(&f.generics), @@ -1693,8 +1693,9 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item, } // Output the trait definition - try!(write!(w, "
{}trait {}{}{}{} ",
+    try!(write!(w, "
{}{}trait {}{}{}{} ",
                   VisSpace(it.visibility),
+                  UnsafetySpace(t.unsafety),
                   it.name.as_ref().unwrap().as_slice(),
                   t.generics,
                   bounds,
@@ -1813,13 +1814,13 @@ fn item_trait(w: &mut fmt::Formatter, cx: &Context, it: &clean::Item,
 }
 
 fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
-    fn method(w: &mut fmt::Formatter, it: &clean::Item, fn_style: ast::FnStyle,
+    fn method(w: &mut fmt::Formatter, it: &clean::Item, unsafety: ast::Unsafety,
            g: &clean::Generics, selfty: &clean::SelfTy,
            d: &clean::FnDecl) -> fmt::Result {
         write!(w, "{}fn {name}\
                    {generics}{decl}{where_clause}",
-               match fn_style {
-                   ast::UnsafeFn => "unsafe ",
+               match unsafety {
+                   ast::Unsafety::Unsafe => "unsafe ",
                    _ => "",
                },
                ty = shortty(it),
@@ -1841,10 +1842,10 @@ fn render_method(w: &mut fmt::Formatter, meth: &clean::Item) -> fmt::Result {
     }
     match meth.inner {
         clean::TyMethodItem(ref m) => {
-            method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
+            method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl)
         }
         clean::MethodItem(ref m) => {
-            method(w, meth, m.fn_style, &m.generics, &m.self_, &m.decl)
+            method(w, meth, m.unsafety, &m.generics, &m.self_, &m.decl)
         }
         clean::AssociatedTypeItem(ref typ) => {
             assoc_type(w, meth, typ)
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index b5b34ef6efe6a..4374ce5deef4e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -121,7 +121,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
 
     pub fn visit_fn(&mut self, item: &ast::Item,
                     name: ast::Ident, fd: &ast::FnDecl,
-                    fn_style: &ast::FnStyle, _abi: &abi::Abi,
+                    unsafety: &ast::Unsafety, _abi: &abi::Abi,
                     gen: &ast::Generics) -> Function {
         debug!("Visiting fn");
         Function {
@@ -133,7 +133,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
             name: name,
             whence: item.span,
             generics: gen.clone(),
-            fn_style: *fn_style,
+            unsafety: *unsafety,
         }
     }
 
@@ -322,8 +322,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.constants.push(s);
             },
-            ast::ItemTrait(ref gen, ref def_ub, ref b, ref items) => {
+            ast::ItemTrait(unsafety, ref gen, ref def_ub, ref b, ref items) => {
                 let t = Trait {
+                    unsafety: unsafety,
                     name: name,
                     items: items.clone(),
                     generics: gen.clone(),
@@ -337,8 +338,9 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
                 };
                 om.traits.push(t);
             },
-            ast::ItemImpl(ref gen, ref tr, ref ty, ref items) => {
+            ast::ItemImpl(unsafety, ref gen, ref tr, ref ty, ref items) => {
                 let i = Impl {
+                    unsafety: unsafety,
                     generics: gen.clone(),
                     trait_: tr.clone(),
                     for_: ty.clone(),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index ae7a2127e9f60..206fb26eb55cb 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -20,7 +20,6 @@ pub use self::Decl_::*;
 pub use self::ExplicitSelf_::*;
 pub use self::Expr_::*;
 pub use self::FloatTy::*;
-pub use self::FnStyle::*;
 pub use self::FunctionRetTy::*;
 pub use self::ForeignItem_::*;
 pub use self::ImplItem::*;
@@ -1027,7 +1026,7 @@ pub struct TypeField {
 pub struct TypeMethod {
     pub ident: Ident,
     pub attrs: Vec,
-    pub fn_style: FnStyle,
+    pub unsafety: Unsafety,
     pub abi: Abi,
     pub decl: P,
     pub generics: Generics,
@@ -1198,7 +1197,7 @@ impl fmt::Show for Onceness {
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct ClosureTy {
     pub lifetimes: Vec,
-    pub fn_style: FnStyle,
+    pub unsafety: Unsafety,
     pub onceness: Onceness,
     pub decl: P,
     pub bounds: TyParamBounds,
@@ -1206,7 +1205,7 @@ pub struct ClosureTy {
 
 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash, Show)]
 pub struct BareFnTy {
-    pub fn_style: FnStyle,
+    pub unsafety: Unsafety,
     pub abi: Abi,
     pub lifetimes: Vec,
     pub decl: P
@@ -1304,21 +1303,17 @@ pub struct FnDecl {
     pub variadic: bool
 }
 
-#[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
-pub enum FnStyle {
-    /// Declared with "unsafe fn"
-    UnsafeFn,
-    /// Declared with "fn"
-    NormalFn,
+#[deriving(Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
+pub enum Unsafety {
+    Unsafe,
+    Normal,
 }
 
-impl Copy for FnStyle {}
-
-impl fmt::Show for FnStyle {
+impl fmt::Show for Unsafety {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         match *self {
-            NormalFn => "normal".fmt(f),
-            UnsafeFn => "unsafe".fmt(f),
+            Unsafety::Normal => "normal".fmt(f),
+            Unsafety::Unsafe => "unsafe".fmt(f),
         }
     }
 }
@@ -1371,7 +1366,7 @@ pub enum Method_ {
              Generics,
              Abi,
              ExplicitSelf,
-             FnStyle,
+             Unsafety,
              P,
              P,
              Visibility),
@@ -1609,19 +1604,21 @@ pub struct Item {
 pub enum Item_ {
     ItemStatic(P, Mutability, P),
     ItemConst(P, P),
-    ItemFn(P, FnStyle, Abi, Generics, P),
+    ItemFn(P, Unsafety, Abi, Generics, P),
     ItemMod(Mod),
     ItemForeignMod(ForeignMod),
     ItemTy(P, Generics),
     ItemEnum(EnumDef, Generics),
     ItemStruct(P, Generics),
     /// Represents a Trait Declaration
-    ItemTrait(Generics,
+    ItemTrait(Unsafety,
+              Generics,
               Option, // (optional) default bound not required for Self.
                                 // Currently, only Sized makes sense here.
               TyParamBounds,
               Vec),
-    ItemImpl(Generics,
+    ItemImpl(Unsafety,
+             Generics,
              Option, // (optional) trait this impl implements
              P, // self
              Vec),
diff --git a/src/libsyntax/ast_map/blocks.rs b/src/libsyntax/ast_map/blocks.rs
index 5462918b66283..6decfd1c3addc 100644
--- a/src/libsyntax/ast_map/blocks.rs
+++ b/src/libsyntax/ast_map/blocks.rs
@@ -122,7 +122,7 @@ impl<'a> Code<'a> {
 struct ItemFnParts<'a> {
     ident:    ast::Ident,
     decl:     &'a ast::FnDecl,
-    style:    ast::FnStyle,
+    unsafety: ast::Unsafety,
     abi:      abi::Abi,
     generics: &'a ast::Generics,
     body:     &'a Block,
@@ -182,7 +182,7 @@ impl<'a> FnLikeNode<'a> {
 
     pub fn kind(self) -> visit::FnKind<'a> {
         let item = |: p: ItemFnParts<'a>| -> visit::FnKind<'a> {
-            visit::FkItemFn(p.ident, p.generics, p.style, p.abi)
+            visit::FkItemFn(p.ident, p.generics, p.unsafety, p.abi)
         };
         let closure = |: _: ClosureParts| {
             visit::FkFnBlock
@@ -200,9 +200,9 @@ impl<'a> FnLikeNode<'a> {
     {
         match self.node {
             ast_map::NodeItem(i) => match i.node {
-                ast::ItemFn(ref decl, style, abi, ref generics, ref block) =>
+                ast::ItemFn(ref decl, unsafety, abi, ref generics, ref block) =>
                     item_fn(ItemFnParts{
-                        ident: i.ident, decl: &**decl, style: style, body: &**block,
+                        ident: i.ident, decl: &**decl, unsafety: unsafety, body: &**block,
                         generics: generics, abi: abi, id: i.id, span: i.span
                     }),
                 _ => panic!("item FnLikeNode that is not fn-like"),
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 6f1d2d39b3049..6089f39e828b1 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -755,7 +755,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
         let parent = self.parent;
         self.parent = i.id;
         match i.node {
-            ItemImpl(_, _, _, ref impl_items) => {
+            ItemImpl(_, _, _, _, ref impl_items) => {
                 for impl_item in impl_items.iter() {
                     match *impl_item {
                         MethodImplItem(ref m) => {
@@ -786,7 +786,7 @@ impl<'ast> Visitor<'ast> for NodeCollector<'ast> {
                     None => {}
                 }
             }
-            ItemTrait(_, _, ref bounds, ref trait_items) => {
+            ItemTrait(_, _, _, ref bounds, ref trait_items) => {
                 for b in bounds.iter() {
                     if let TraitTyParamBound(ref t) = *b {
                         self.insert(t.trait_ref.ref_id, NodeItem(i));
diff --git a/src/libsyntax/ast_util.rs b/src/libsyntax/ast_util.rs
index 7579972c6d843..63c95a976d47d 100644
--- a/src/libsyntax/ast_util.rs
+++ b/src/libsyntax/ast_util.rs
@@ -233,14 +233,14 @@ pub fn trait_method_to_ty_method(method: &Method) -> TypeMethod {
                  ref generics,
                  abi,
                  ref explicit_self,
-                 fn_style,
+                 unsafety,
                  ref decl,
                  _,
                  vis) => {
             TypeMethod {
                 ident: ident,
                 attrs: method.attrs.clone(),
-                fn_style: fn_style,
+                unsafety: unsafety,
                 decl: (*decl).clone(),
                 generics: generics.clone(),
                 explicit_self: (*explicit_self).clone(),
@@ -722,7 +722,7 @@ pub trait PostExpansionMethod {
     fn pe_generics<'a>(&'a self) -> &'a ast::Generics;
     fn pe_abi(&self) -> Abi;
     fn pe_explicit_self<'a>(&'a self) -> &'a ast::ExplicitSelf;
-    fn pe_fn_style(&self) -> ast::FnStyle;
+    fn pe_unsafety(&self) -> ast::Unsafety;
     fn pe_fn_decl<'a>(&'a self) -> &'a ast::FnDecl;
     fn pe_body<'a>(&'a self) -> &'a ast::Block;
     fn pe_vis(&self) -> ast::Visibility;
@@ -749,7 +749,7 @@ impl PostExpansionMethod for Method {
     mf_method!(pe_abi,Abi,MethDecl(_,_,abi,_,_,_,_,_),abi)
     mf_method!(pe_explicit_self,&'a ast::ExplicitSelf,
                MethDecl(_,_,_,ref explicit_self,_,_,_,_),explicit_self)
-    mf_method!(pe_fn_style,ast::FnStyle,MethDecl(_,_,_,_,fn_style,_,_,_),fn_style)
+    mf_method!(pe_unsafety,ast::Unsafety,MethDecl(_,_,_,_,unsafety,_,_,_),unsafety)
     mf_method!(pe_fn_decl,&'a ast::FnDecl,MethDecl(_,_,_,_,_,ref decl,_,_),&**decl)
     mf_method!(pe_body,&'a ast::Block,MethDecl(_,_,_,_,_,_,ref body,_),&**body)
     mf_method!(pe_vis,ast::Visibility,MethDecl(_,_,_,_,_,_,_,vis),vis)
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index 87426dce91817..d2185a00876d2 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -133,17 +133,17 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_
     F: FnMut(&[ast::Attribute]) -> bool
 {
     let item = match item {
-        ast::ItemImpl(a, b, c, impl_items) => {
+        ast::ItemImpl(u, a, b, c, impl_items) => {
             let impl_items = impl_items.into_iter()
                                        .filter(|ii| impl_item_in_cfg(cx, ii))
                                        .collect();
-            ast::ItemImpl(a, b, c, impl_items)
+            ast::ItemImpl(u, a, b, c, impl_items)
         }
-        ast::ItemTrait(a, b, c, methods) => {
+        ast::ItemTrait(u, a, b, c, methods) => {
             let methods = methods.into_iter()
                                  .filter(|m| trait_method_in_cfg(cx, m))
                                  .collect();
-            ast::ItemTrait(a, b, c, methods)
+            ast::ItemTrait(u, a, b, c, methods)
         }
         ast::ItemStruct(def, generics) => {
             ast::ItemStruct(fold_struct(cx, def), generics)
diff --git a/src/libsyntax/ext/build.rs b/src/libsyntax/ext/build.rs
index 84040bcfa9f05..d35091f8ab0aa 100644
--- a/src/libsyntax/ext/build.rs
+++ b/src/libsyntax/ext/build.rs
@@ -969,7 +969,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
                   name,
                   Vec::new(),
                   ast::ItemFn(self.fn_decl(inputs, output),
-                              ast::NormalFn,
+                              ast::Unsafety::Normal,
                               abi::Rust,
                               generics,
                               body))
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index a75be40604ea6..f40be823a1a54 100644
--- a/src/libsyntax/ext/deriving/generic/mod.rs
+++ b/src/libsyntax/ext/deriving/generic/mod.rs
@@ -462,7 +462,8 @@ impl<'a> TraitDef<'a> {
             self.span,
             ident,
             a,
-            ast::ItemImpl(trait_generics,
+            ast::ItemImpl(ast::Unsafety::Normal,
+                          trait_generics,
                           opt_trait_ref,
                           self_type,
                           methods.into_iter()
@@ -684,7 +685,7 @@ impl<'a> MethodDef<'a> {
                                 fn_generics,
                                 abi,
                                 explicit_self,
-                                ast::NormalFn,
+                                ast::Unsafety::Normal,
                                 fn_decl,
                                 body_block,
                                 ast::Inherited)
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index 66fe672c3e5e8..9656629e14d77 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -215,7 +215,7 @@ impl<'a, 'v> Visitor<'v> for Context<'a> {
                 }
             }
 
-            ast::ItemImpl(_, _, _, ref items) => {
+            ast::ItemImpl(_, _, _, _, ref items) => {
                 if attr::contains_name(i.attrs.as_slice(),
                                        "unsafe_destructor") {
                     self.gate_feature("unsafe_destructor",
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index 611faa2c2c909..8a578c2cb05c0 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -415,9 +415,9 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P {
                 TyRptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt))
             }
             TyClosure(f) => {
-                TyClosure(f.map(|ClosureTy {fn_style, onceness, bounds, decl, lifetimes}| {
+                TyClosure(f.map(|ClosureTy {unsafety, onceness, bounds, decl, lifetimes}| {
                     ClosureTy {
-                        fn_style: fn_style,
+                        unsafety: unsafety,
                         onceness: onceness,
                         bounds: fld.fold_bounds(bounds),
                         decl: fld.fold_fn_decl(decl),
@@ -426,9 +426,9 @@ pub fn noop_fold_ty(t: P, fld: &mut T) -> P {
                 }))
             }
             TyBareFn(f) => {
-                TyBareFn(f.map(|BareFnTy {lifetimes, fn_style, abi, decl}| BareFnTy {
+                TyBareFn(f.map(|BareFnTy {lifetimes, unsafety, abi, decl}| BareFnTy {
                     lifetimes: fld.fold_lifetime_defs(lifetimes),
-                    fn_style: fn_style,
+                    unsafety: unsafety,
                     abi: abi,
                     decl: fld.fold_fn_decl(decl)
                 }))
@@ -983,10 +983,10 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
         ItemConst(t, e) => {
             ItemConst(folder.fold_ty(t), folder.fold_expr(e))
         }
-        ItemFn(decl, fn_style, abi, generics, body) => {
+        ItemFn(decl, unsafety, abi, generics, body) => {
             ItemFn(
                 folder.fold_fn_decl(decl),
-                fn_style,
+                unsafety,
                 abi,
                 folder.fold_generics(generics),
                 folder.fold_block(body)
@@ -1008,7 +1008,7 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
             let struct_def = folder.fold_struct_def(struct_def);
             ItemStruct(struct_def, folder.fold_generics(generics))
         }
-        ItemImpl(generics, ifce, ty, impl_items) => {
+        ItemImpl(unsafety, generics, ifce, ty, impl_items) => {
             let mut new_impl_items = Vec::new();
             for impl_item in impl_items.iter() {
                 match *impl_item {
@@ -1030,12 +1030,13 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
                     Some(folder.fold_trait_ref((*trait_ref).clone()))
                 }
             };
-            ItemImpl(folder.fold_generics(generics),
+            ItemImpl(unsafety,
+                     folder.fold_generics(generics),
                      ifce,
                      folder.fold_ty(ty),
                      new_impl_items)
         }
-        ItemTrait(generics, unbound, bounds, methods) => {
+        ItemTrait(unsafety, generics, unbound, bounds, methods) => {
             let bounds = folder.fold_bounds(bounds);
             let methods = methods.into_iter().flat_map(|method| {
                 let r = match method {
@@ -1063,7 +1064,8 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
                 };
                 r
             }).collect();
-            ItemTrait(folder.fold_generics(generics),
+            ItemTrait(unsafety,
+                      folder.fold_generics(generics),
                       unbound,
                       bounds,
                       methods)
@@ -1077,7 +1079,7 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho
         id,
         ident,
         attrs,
-        fn_style,
+        unsafety,
         abi,
         decl,
         generics,
@@ -1089,7 +1091,7 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho
         id: fld.new_id(id),
         ident: fld.fold_ident(ident),
         attrs: attrs.move_map(|a| fld.fold_attribute(a)),
-        fn_style: fn_style,
+        unsafety: unsafety,
         abi: abi,
         decl: fld.fold_fn_decl(decl),
         generics: fld.fold_generics(generics),
@@ -1159,7 +1161,7 @@ pub fn noop_fold_item_simple(Item {id, ident, attrs, node, vis, span}
     let node = folder.fold_item_underscore(node);
     let ident = match node {
         // The node may have changed, recompute the "pretty" impl name.
-        ItemImpl(_, ref maybe_trait, ref ty, _) => {
+        ItemImpl(_, _, ref maybe_trait, ref ty, _) => {
             ast_util::impl_pretty_name(maybe_trait, &**ty)
         }
         _ => ident
@@ -1211,7 +1213,7 @@ pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector<
                      generics,
                      abi,
                      explicit_self,
-                     fn_style,
+                     unsafety,
                      decl,
                      body,
                      vis) => {
@@ -1219,7 +1221,7 @@ pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector<
                          folder.fold_generics(generics),
                          abi,
                          folder.fold_explicit_self(explicit_self),
-                         fn_style,
+                         unsafety,
                          folder.fold_fn_decl(decl),
                          folder.fold_block(body),
                          vis)
diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs
index 310d5662afa20..d6f5d0e248a86 100644
--- a/src/libsyntax/parse/mod.rs
+++ b/src/libsyntax/parse/mod.rs
@@ -1062,7 +1062,7 @@ mod test {
                                                   span:sp(15,15)})), // not sure
                                 variadic: false
                             }),
-                                    ast::NormalFn,
+                                    ast::Unsafety::Normal,
                                     abi::Rust,
                                     ast::Generics{ // no idea on either of these:
                                         lifetimes: Vec::new(),
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index 381942a3e622f..d1991c0463f44 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -16,7 +16,7 @@ use self::ItemOrViewItem::*;
 use abi;
 use ast::{AssociatedType, BareFnTy, ClosureTy};
 use ast::{RegionTyParamBound, TraitTyParamBound};
-use ast::{ProvidedMethod, Public, FnStyle};
+use ast::{ProvidedMethod, Public, Unsafety};
 use ast::{Mod, BiAdd, Arg, Arm, Attribute, BindByRef, BindByValue};
 use ast::{BiBitAnd, BiBitOr, BiBitXor, BiRem, Block};
 use ast::{BlockCheckMode, CaptureByRef, CaptureByValue, CaptureClause};
@@ -34,7 +34,7 @@ use ast::{Many};
 use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind};
 use ast::{FnOnceUnboxedClosureKind};
 use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod, FunctionRetTy};
-use ast::{Ident, NormalFn, Inherited, ImplItem, Item, Item_, ItemStatic};
+use ast::{Ident, Inherited, ImplItem, Item, Item_, ItemStatic};
 use ast::{ItemEnum, ItemFn, ItemForeignMod, ItemImpl, ItemConst};
 use ast::{ItemMac, ItemMod, ItemStruct, ItemTrait, ItemTy};
 use ast::{LifetimeDef, Lit, Lit_};
@@ -60,7 +60,7 @@ use ast::{TyParam, TyParamBound, TyParen, TyPath, TyPolyTraitRef, TyPtr, TyQPath
 use ast::{TyRptr, TyTup, TyU32, TyVec, UnUniq};
 use ast::{TypeImplItem, TypeTraitItem, Typedef, UnboxedClosureKind};
 use ast::{UnnamedField, UnsafeBlock};
-use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
+use ast::{ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse};
 use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple};
 use ast::{Visibility, WhereClause};
 use ast;
@@ -1121,7 +1121,7 @@ impl<'a> Parser<'a> {
         Function Style
         */
 
-        let fn_style = self.parse_unsafety();
+        let unsafety = self.parse_unsafety();
         let abi = if self.eat_keyword(keywords::Extern) {
             self.parse_opt_abi().unwrap_or(abi::C)
         } else {
@@ -1139,7 +1139,7 @@ impl<'a> Parser<'a> {
         });
         TyBareFn(P(BareFnTy {
             abi: abi,
-            fn_style: fn_style,
+            unsafety: unsafety,
             lifetimes: lifetime_defs,
             decl: decl
         }))
@@ -1240,7 +1240,7 @@ impl<'a> Parser<'a> {
 
         */
 
-        let fn_style = self.parse_unsafety();
+        let unsafety = self.parse_unsafety();
 
         let lifetime_defs = self.parse_legacy_lifetime_defs(lifetime_defs);
 
@@ -1266,7 +1266,7 @@ impl<'a> Parser<'a> {
         });
 
         TyClosure(P(ClosureTy {
-            fn_style: fn_style,
+            unsafety: unsafety,
             onceness: Many,
             bounds: bounds,
             decl: decl,
@@ -1274,11 +1274,11 @@ impl<'a> Parser<'a> {
         }))
     }
 
-    pub fn parse_unsafety(&mut self) -> FnStyle {
+    pub fn parse_unsafety(&mut self) -> Unsafety {
         if self.eat_keyword(keywords::Unsafe) {
-            return UnsafeFn;
+            return Unsafety::Unsafe;
         } else {
-            return NormalFn;
+            return Unsafety::Normal;
         }
     }
 
@@ -1351,7 +1351,7 @@ impl<'a> Parser<'a> {
                 let lo = p.span.lo;
 
                 let vis = p.parse_visibility();
-                let style = p.parse_fn_style();
+                let style = p.parse_unsafety();
                 let abi = if p.eat_keyword(keywords::Extern) {
                     p.parse_opt_abi().unwrap_or(abi::C)
                 } else {
@@ -1379,7 +1379,7 @@ impl<'a> Parser<'a> {
                     RequiredMethod(TypeMethod {
                         ident: ident,
                         attrs: attrs,
-                        fn_style: style,
+                        unsafety: style,
                         decl: d,
                         generics: generics,
                         abi: abi,
@@ -4548,12 +4548,12 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse an item-position function declaration.
-    fn parse_item_fn(&mut self, fn_style: FnStyle, abi: abi::Abi) -> ItemInfo {
+    fn parse_item_fn(&mut self, unsafety: Unsafety, abi: abi::Abi) -> ItemInfo {
         let (ident, mut generics) = self.parse_fn_header();
         let decl = self.parse_fn_decl(false);
         self.parse_where_clause(&mut generics);
         let (inner_attrs, body) = self.parse_inner_attrs_and_block();
-        (ident, ItemFn(decl, fn_style, abi, generics, body), Some(inner_attrs))
+        (ident, ItemFn(decl, unsafety, abi, generics, body), Some(inner_attrs))
     }
 
     /// Parse a method in a trait impl
@@ -4591,7 +4591,7 @@ impl<'a> Parser<'a> {
                                                              self.span.hi) };
                 (ast::MethMac(m), self.span.hi, attrs)
             } else {
-                let fn_style = self.parse_fn_style();
+                let unsafety = self.parse_unsafety();
                 let abi = if self.eat_keyword(keywords::Extern) {
                     self.parse_opt_abi().unwrap_or(abi::C)
                 } else {
@@ -4612,7 +4612,7 @@ impl<'a> Parser<'a> {
                                generics,
                                abi,
                                explicit_self,
-                               fn_style,
+                               unsafety,
                                decl,
                                body,
                                visa),
@@ -4628,7 +4628,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parse trait Foo { ... }
-    fn parse_item_trait(&mut self) -> ItemInfo {
+    fn parse_item_trait(&mut self, unsafety: Unsafety) -> ItemInfo {
         let ident = self.parse_ident();
         let mut tps = self.parse_generics();
         let sized = self.parse_for_sized();
@@ -4639,7 +4639,7 @@ impl<'a> Parser<'a> {
         self.parse_where_clause(&mut tps);
 
         let meths = self.parse_trait_items();
-        (ident, ItemTrait(tps, sized, bounds, meths), None)
+        (ident, ItemTrait(unsafety, tps, sized, bounds, meths), None)
     }
 
     fn parse_impl_items(&mut self) -> (Vec, Vec) {
@@ -4667,7 +4667,7 @@ impl<'a> Parser<'a> {
     /// Parses two variants (with the region/type params always optional):
     ///    impl Foo { ... }
     ///    impl ToString for ~[T] { ... }
-    fn parse_item_impl(&mut self) -> ItemInfo {
+    fn parse_item_impl(&mut self, unsafety: ast::Unsafety) -> ItemInfo {
         // First, parse type parameters if necessary.
         let mut generics = self.parse_generics();
 
@@ -4706,7 +4706,7 @@ impl<'a> Parser<'a> {
         let ident = ast_util::impl_pretty_name(&opt_trait, &*ty);
 
         (ident,
-         ItemImpl(generics, opt_trait, ty, impl_items),
+         ItemImpl(unsafety, generics, opt_trait, ty, impl_items),
          Some(attrs))
     }
 
@@ -5143,16 +5143,6 @@ impl<'a> Parser<'a> {
         })
     }
 
-    /// Parse unsafe or not
-    fn parse_fn_style(&mut self) -> FnStyle {
-        if self.eat_keyword(keywords::Unsafe) {
-            UnsafeFn
-        } else {
-            NormalFn
-        }
-    }
-
-
     /// At this point, this is essentially a wrapper for
     /// parse_foreign_items.
     fn parse_foreign_mod_items(&mut self,
@@ -5491,7 +5481,7 @@ impl<'a> Parser<'a> {
                 // EXTERN FUNCTION ITEM
                 let abi = opt_abi.unwrap_or(abi::C);
                 let (ident, item_, extra_attrs) =
-                    self.parse_item_fn(NormalFn, abi);
+                    self.parse_item_fn(Unsafety::Normal, abi);
                 let last_span = self.last_span;
                 let item = self.mk_item(lo,
                                         last_span.hi,
@@ -5549,12 +5539,45 @@ impl<'a> Parser<'a> {
                                     maybe_append(attrs, extra_attrs));
             return IoviItem(item);
         }
+        if self.token.is_keyword(keywords::Unsafe) &&
+            self.look_ahead(1u, |t| t.is_keyword(keywords::Trait))
+        {
+            // UNSAFE TRAIT ITEM
+            self.expect_keyword(keywords::Unsafe);
+            self.expect_keyword(keywords::Trait);
+            let (ident, item_, extra_attrs) =
+                self.parse_item_trait(ast::Unsafety::Unsafe);
+            let last_span = self.last_span;
+            let item = self.mk_item(lo,
+                                    last_span.hi,
+                                    ident,
+                                    item_,
+                                    visibility,
+                                    maybe_append(attrs, extra_attrs));
+            return IoviItem(item);
+        }
+        if self.token.is_keyword(keywords::Unsafe) &&
+            self.look_ahead(1u, |t| t.is_keyword(keywords::Impl))
+        {
+            // IMPL ITEM
+            self.expect_keyword(keywords::Unsafe);
+            self.expect_keyword(keywords::Impl);
+            let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Unsafe);
+            let last_span = self.last_span;
+            let item = self.mk_item(lo,
+                                    last_span.hi,
+                                    ident,
+                                    item_,
+                                    visibility,
+                                    maybe_append(attrs, extra_attrs));
+            return IoviItem(item);
+        }
         if self.token.is_keyword(keywords::Fn) &&
                 self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) {
             // FUNCTION ITEM
             self.bump();
             let (ident, item_, extra_attrs) =
-                self.parse_item_fn(NormalFn, abi::Rust);
+                self.parse_item_fn(Unsafety::Normal, abi::Rust);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
@@ -5575,7 +5598,7 @@ impl<'a> Parser<'a> {
             };
             self.expect_keyword(keywords::Fn);
             let (ident, item_, extra_attrs) =
-                self.parse_item_fn(UnsafeFn, abi);
+                self.parse_item_fn(Unsafety::Unsafe, abi);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
@@ -5624,7 +5647,8 @@ impl<'a> Parser<'a> {
         }
         if self.eat_keyword(keywords::Trait) {
             // TRAIT ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_trait();
+            let (ident, item_, extra_attrs) =
+                self.parse_item_trait(ast::Unsafety::Normal);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
@@ -5636,7 +5660,7 @@ impl<'a> Parser<'a> {
         }
         if self.eat_keyword(keywords::Impl) {
             // IMPL ITEM
-            let (ident, item_, extra_attrs) = self.parse_item_impl();
+            let (ident, item_, extra_attrs) = self.parse_item_impl(ast::Unsafety::Normal);
             let last_span = self.last_span;
             let item = self.mk_item(lo,
                                     last_span.hi,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 87905db22f349..db122f271a9c4 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -363,11 +363,11 @@ pub fn ident_to_string(id: &ast::Ident) -> String {
     $to_string(|s| s.print_ident(*id))
 }
 
-pub fn fun_to_string(decl: &ast::FnDecl, fn_style: ast::FnStyle, name: ast::Ident,
+pub fn fun_to_string(decl: &ast::FnDecl, unsafety: ast::Unsafety, name: ast::Ident,
                   opt_explicit_self: Option<&ast::ExplicitSelf_>,
                   generics: &ast::Generics) -> String {
     $to_string(|s| {
-        try!(s.print_fn(decl, Some(fn_style), abi::Rust,
+        try!(s.print_fn(decl, Some(unsafety), abi::Rust,
                         name, generics, opt_explicit_self, ast::Inherited));
         try!(s.end()); // Close the head box
         s.end() // Close the outer box
@@ -707,7 +707,7 @@ impl<'a> State<'a> {
                 };
                 try!(self.print_ty_fn(Some(f.abi),
                                       None,
-                                      f.fn_style,
+                                      f.unsafety,
                                       ast::Many,
                                       &*f.decl,
                                       None,
@@ -726,7 +726,7 @@ impl<'a> State<'a> {
                 };
                 try!(self.print_ty_fn(None,
                                       Some('&'),
-                                      f.fn_style,
+                                      f.unsafety,
                                       f.onceness,
                                       &*f.decl,
                                       None,
@@ -858,10 +858,10 @@ impl<'a> State<'a> {
                 try!(word(&mut self.s, ";"));
                 try!(self.end()); // end the outer cbox
             }
-            ast::ItemFn(ref decl, fn_style, abi, ref typarams, ref body) => {
+            ast::ItemFn(ref decl, unsafety, abi, ref typarams, ref body) => {
                 try!(self.print_fn(
                     &**decl,
-                    Some(fn_style),
+                    Some(unsafety),
                     abi,
                     item.ident,
                     typarams,
@@ -917,12 +917,16 @@ impl<'a> State<'a> {
                 try!(self.print_struct(&**struct_def, generics, item.ident, item.span));
             }
 
-            ast::ItemImpl(ref generics,
+            ast::ItemImpl(unsafety,
+                          ref generics,
                           ref opt_trait,
                           ref ty,
                           ref impl_items) => {
-                try!(self.head(visibility_qualified(item.vis,
-                                                    "impl").as_slice()));
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("impl"));
+
                 if generics.is_parameterized() {
                     try!(self.print_generics(generics));
                     try!(space(&mut self.s));
@@ -955,9 +959,11 @@ impl<'a> State<'a> {
                 }
                 try!(self.bclose(item.span));
             }
-            ast::ItemTrait(ref generics, ref unbound, ref bounds, ref methods) => {
-                try!(self.head(visibility_qualified(item.vis,
-                                                    "trait").as_slice()));
+            ast::ItemTrait(unsafety, ref generics, ref unbound, ref bounds, ref methods) => {
+                try!(self.head(""));
+                try!(self.print_visibility(item.vis));
+                try!(self.print_unsafety(unsafety));
+                try!(self.word_nbsp("trait"));
                 try!(self.print_ident(item.ident));
                 try!(self.print_generics(generics));
                 if let &Some(ref tref) = unbound {
@@ -1188,7 +1194,7 @@ impl<'a> State<'a> {
         try!(self.print_outer_attributes(m.attrs.as_slice()));
         try!(self.print_ty_fn(None,
                               None,
-                              m.fn_style,
+                              m.unsafety,
                               ast::Many,
                               &*m.decl,
                               Some(m.ident),
@@ -1223,12 +1229,12 @@ impl<'a> State<'a> {
                           ref generics,
                           abi,
                           ref explicit_self,
-                          fn_style,
+                          unsafety,
                           ref decl,
                           ref body,
                           vis) => {
                 try!(self.print_fn(&**decl,
-                                   Some(fn_style),
+                                   Some(unsafety),
                                    abi,
                                    ident,
                                    generics,
@@ -2164,14 +2170,14 @@ impl<'a> State<'a> {
 
     pub fn print_fn(&mut self,
                     decl: &ast::FnDecl,
-                    fn_style: Option,
+                    unsafety: Option,
                     abi: abi::Abi,
                     name: ast::Ident,
                     generics: &ast::Generics,
                     opt_explicit_self: Option<&ast::ExplicitSelf_>,
                     vis: ast::Visibility) -> IoResult<()> {
         try!(self.head(""));
-        try!(self.print_fn_header_info(opt_explicit_self, fn_style, abi, vis));
+        try!(self.print_fn_header_info(opt_explicit_self, unsafety, abi, vis));
         try!(self.nbsp());
         try!(self.print_ident(name));
         try!(self.print_generics(generics));
@@ -2588,7 +2594,7 @@ impl<'a> State<'a> {
     pub fn print_ty_fn(&mut self,
                        opt_abi: Option,
                        opt_sigil: Option,
-                       fn_style: ast::FnStyle,
+                       unsafety: ast::Unsafety,
                        onceness: ast::Onceness,
                        decl: &ast::FnDecl,
                        id: Option,
@@ -2603,11 +2609,11 @@ impl<'a> State<'a> {
         if opt_sigil == Some('~') && onceness == ast::Once {
             try!(word(&mut self.s, "proc"));
         } else if opt_sigil == Some('&') {
-            try!(self.print_fn_style(fn_style));
+            try!(self.print_unsafety(unsafety));
             try!(self.print_extern_opt_abi(opt_abi));
         } else {
             assert!(opt_sigil.is_none());
-            try!(self.print_fn_style(fn_style));
+            try!(self.print_unsafety(unsafety));
             try!(self.print_opt_abi_and_extern_if_nondefault(opt_abi));
             try!(word(&mut self.s, "fn"));
         }
@@ -2872,10 +2878,10 @@ impl<'a> State<'a> {
         }
     }
 
-    pub fn print_opt_fn_style(&mut self,
-                            opt_fn_style: Option) -> IoResult<()> {
-        match opt_fn_style {
-            Some(fn_style) => self.print_fn_style(fn_style),
+    pub fn print_opt_unsafety(&mut self,
+                            opt_unsafety: Option) -> IoResult<()> {
+        match opt_unsafety {
+            Some(unsafety) => self.print_unsafety(unsafety),
             None => Ok(())
         }
     }
@@ -2906,11 +2912,11 @@ impl<'a> State<'a> {
 
     pub fn print_fn_header_info(&mut self,
                                 _opt_explicit_self: Option<&ast::ExplicitSelf_>,
-                                opt_fn_style: Option,
+                                opt_unsafety: Option,
                                 abi: abi::Abi,
                                 vis: ast::Visibility) -> IoResult<()> {
         try!(word(&mut self.s, visibility_qualified(vis, "").as_slice()));
-        try!(self.print_opt_fn_style(opt_fn_style));
+        try!(self.print_opt_unsafety(opt_unsafety));
 
         if abi != abi::Rust {
             try!(self.word_nbsp("extern"));
@@ -2920,10 +2926,10 @@ impl<'a> State<'a> {
         word(&mut self.s, "fn")
     }
 
-    pub fn print_fn_style(&mut self, s: ast::FnStyle) -> IoResult<()> {
+    pub fn print_unsafety(&mut self, s: ast::Unsafety) -> IoResult<()> {
         match s {
-            ast::NormalFn => Ok(()),
-            ast::UnsafeFn => self.word_nbsp("unsafe"),
+            ast::Unsafety::Normal => Ok(()),
+            ast::Unsafety::Unsafe => self.word_nbsp("unsafe"),
         }
     }
 }
@@ -2950,7 +2956,7 @@ mod test {
             variadic: false
         };
         let generics = ast_util::empty_generics();
-        assert_eq!(fun_to_string(&decl, ast::NormalFn, abba_ident,
+        assert_eq!(fun_to_string(&decl, ast::Unsafety::Normal, abba_ident,
                                None, &generics),
                    "fn abba()");
     }
diff --git a/src/libsyntax/test.rs b/src/libsyntax/test.rs
index ca2f190ce76be..155cabb153cfa 100644
--- a/src/libsyntax/test.rs
+++ b/src/libsyntax/test.rs
@@ -123,7 +123,7 @@ impl<'a> fold::Folder for TestHarnessGenerator<'a> {
 
         if is_test_fn(&self.cx, &*i) || is_bench_fn(&self.cx, &*i) {
             match i.node {
-                ast::ItemFn(_, ast::UnsafeFn, _, _, _) => {
+                ast::ItemFn(_, ast::Unsafety::Unsafe, _, _, _) => {
                     let diag = self.cx.span_diagnostic;
                     diag.span_fatal(i.span,
                                     "unsafe functions cannot be used for \
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index eca99df8e5561..3535c6e267eba 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -34,7 +34,7 @@ use owned_slice::OwnedSlice;
 
 pub enum FnKind<'a> {
     /// fn foo() or extern "Abi" fn foo()
-    FkItemFn(Ident, &'a Generics, FnStyle, Abi),
+    FkItemFn(Ident, &'a Generics, Unsafety, Abi),
 
     /// fn foo(&self)
     FkMethod(Ident, &'a Generics, &'a Method),
@@ -282,7 +282,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
             visitor.visit_generics(type_parameters);
             walk_enum_def(visitor, enum_definition, type_parameters)
         }
-        ItemImpl(ref type_parameters,
+        ItemImpl(_,
+                 ref type_parameters,
                  ref trait_reference,
                  ref typ,
                  ref impl_items) => {
@@ -311,7 +312,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item) {
                                      generics,
                                      item.id)
         }
-        ItemTrait(ref generics, _, ref bounds, ref methods) => {
+        ItemTrait(_, ref generics, _, ref bounds, ref methods) => {
             visitor.visit_generics(generics);
             walk_ty_param_bounds_helper(visitor, bounds);
             for method in methods.iter() {
diff --git a/src/test/auxiliary/trait-safety-lib.rs b/src/test/auxiliary/trait-safety-lib.rs
new file mode 100644
index 0000000000000..d5437690acdc7
--- /dev/null
+++ b/src/test/auxiliary/trait-safety-lib.rs
@@ -0,0 +1,19 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Simple smoke test that unsafe traits can be compiled etc.
+
+pub unsafe trait Foo {
+    fn foo(&self) -> int;
+}
+
+unsafe impl Foo for int {
+    fn foo(&self) -> int { *self }
+}
diff --git a/src/test/compile-fail/trait-safety-fn-body.rs b/src/test/compile-fail/trait-safety-fn-body.rs
new file mode 100644
index 0000000000000..d174092e4d0ac
--- /dev/null
+++ b/src/test/compile-fail/trait-safety-fn-body.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that an unsafe impl does not imply that unsafe actions are
+// legal in the methods.
+
+unsafe trait UnsafeTrait {
+    fn foo(self) { }
+}
+
+unsafe impl UnsafeTrait for *mut int {
+    fn foo(self) {
+        // Unsafe actions are not made legal by taking place in an unsafe trait:
+        *self += 1; //~ ERROR E0133
+    }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/trait-safety-inherent-impl.rs b/src/test/compile-fail/trait-safety-inherent-impl.rs
new file mode 100644
index 0000000000000..285d4c1ba8d14
--- /dev/null
+++ b/src/test/compile-fail/trait-safety-inherent-impl.rs
@@ -0,0 +1,19 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that inherent impls cannot be unsafe.
+
+struct SomeStruct;
+
+unsafe impl SomeStruct { //~ ERROR inherent impls cannot be declared as unsafe
+    fn foo(self) { }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/trait-safety-trait-impl-cc.rs b/src/test/compile-fail/trait-safety-trait-impl-cc.rs
new file mode 100644
index 0000000000000..21dd5a237c5db
--- /dev/null
+++ b/src/test/compile-fail/trait-safety-trait-impl-cc.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:trait-safety-lib.rs
+
+// Check that unsafe traits require unsafe impls and that inherent
+// impls cannot be unsafe.
+
+extern crate "trait-safety-lib" as lib;
+
+struct Bar;
+impl lib::Foo for Bar { //~ ERROR requires an `unsafe impl` declaration
+    fn foo(&self) -> int {
+        *self as int
+    }
+}
+
+fn main() { }
diff --git a/src/test/compile-fail/trait-safety-trait-impl.rs b/src/test/compile-fail/trait-safety-trait-impl.rs
new file mode 100644
index 0000000000000..1bd6d76360768
--- /dev/null
+++ b/src/test/compile-fail/trait-safety-trait-impl.rs
@@ -0,0 +1,28 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Check that unsafe traits require unsafe impls and that inherent
+// impls cannot be unsafe.
+
+trait SafeTrait {
+    fn foo(self) { }
+}
+
+unsafe trait UnsafeTrait {
+    fn foo(self) { }
+}
+
+unsafe impl UnsafeTrait for u8 { } // OK
+
+impl UnsafeTrait for u16 { } //~ ERROR requires an `unsafe impl` declaration
+
+unsafe impl SafeTrait for u32 { } //~ ERROR the trait `SafeTrait` is not unsafe
+
+fn main() { }
diff --git a/src/test/pretty/trait-safety.rs b/src/test/pretty/trait-safety.rs
new file mode 100644
index 0000000000000..b96dbbf3cc964
--- /dev/null
+++ b/src/test/pretty/trait-safety.rs
@@ -0,0 +1,25 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// pp-exact
+
+unsafe trait UnsafeTrait {
+    fn foo(&self);
+}
+
+unsafe impl UnsafeTrait for int {
+    fn foo(&self) { }
+}
+
+pub unsafe trait PubUnsafeTrait {
+    fn foo(&self);
+}
+
+fn main() { }
diff --git a/src/test/run-pass/trait-safety-ok-cc.rs b/src/test/run-pass/trait-safety-ok-cc.rs
new file mode 100644
index 0000000000000..99203d3e24acc
--- /dev/null
+++ b/src/test/run-pass/trait-safety-ok-cc.rs
@@ -0,0 +1,32 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// aux-build:trait-safety-lib.rs
+
+// Simple smoke test that unsafe traits can be compiled across crates.
+
+extern crate "trait-safety-lib" as lib;
+
+use lib::Foo;
+
+struct Bar { x: int }
+unsafe impl Foo for Bar {
+    fn foo(&self) -> int { self.x }
+}
+
+fn take_foo(f: &F) -> int { f.foo() }
+
+fn main() {
+    let x: int = 22;
+    assert_eq!(22, take_foo(&x));
+
+    let x: Bar = Bar { x: 23 };
+    assert_eq!(23, take_foo(&x));
+}
diff --git a/src/test/run-pass/trait-safety-ok.rs b/src/test/run-pass/trait-safety-ok.rs
new file mode 100644
index 0000000000000..a24796a7d0c31
--- /dev/null
+++ b/src/test/run-pass/trait-safety-ok.rs
@@ -0,0 +1,26 @@
+// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0  or the MIT license
+// , at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+// Simple smoke test that unsafe traits can be compiled etc.
+
+unsafe trait Foo {
+    fn foo(&self) -> int;
+}
+
+unsafe impl Foo for int {
+    fn foo(&self) -> int { *self }
+}
+
+fn take_foo(f: &F) -> int { f.foo() }
+
+fn main() {
+    let x: int = 22;
+    assert_eq!(22, take_foo(&x));
+}