From 092d04a40a3db44af2dd50e43a77449a7e56dd13 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 9 Dec 2014 10:36:46 -0500 Subject: [PATCH 1/5] Rename FnStyle trait to Unsafety. --- src/librustc/metadata/tydecode.rs | 16 +++---- src/librustc/metadata/tyencode.rs | 10 ++-- src/librustc/middle/effect.rs | 8 ++-- src/librustc/middle/infer/coercion.rs | 2 +- src/librustc/middle/infer/combine.rs | 16 +++---- src/librustc/middle/infer/equate.rs | 6 +-- src/librustc/middle/infer/error_reporting.rs | 14 +++--- src/librustc/middle/infer/glb.rs | 9 ++-- src/librustc/middle/infer/lub.rs | 9 ++-- src/librustc/middle/infer/sub.rs | 8 ++-- src/librustc/middle/traits/select.rs | 4 +- src/librustc/middle/ty.rs | 18 +++---- src/librustc/middle/ty_fold.rs | 4 +- src/librustc/util/ppaux.rs | 24 +++++----- src/librustc_driver/test.rs | 2 +- src/librustc_trans/trans/callee.rs | 4 +- src/librustc_trans/trans/debuginfo.rs | 16 +++---- src/librustc_typeck/astconv.rs | 20 ++++---- src/librustc_typeck/check/closure.rs | 10 ++-- src/librustc_typeck/check/method/confirm.rs | 2 +- src/librustc_typeck/check/method/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 50 ++++++++++---------- src/librustc_typeck/collect.rs | 18 +++---- src/librustc_typeck/lib.rs | 4 +- src/librustdoc/clean/inline.rs | 8 ++-- src/librustdoc/clean/mod.rs | 28 +++++------ src/librustdoc/doctree.rs | 2 +- src/librustdoc/html/format.rs | 22 ++++----- src/librustdoc/html/render.rs | 16 +++---- src/librustdoc/visit_ast.rs | 4 +- src/libsyntax/ast.rs | 29 +++++------- src/libsyntax/ast_map/blocks.rs | 8 ++-- src/libsyntax/ast_util.rs | 8 ++-- src/libsyntax/ext/build.rs | 2 +- src/libsyntax/ext/deriving/generic/mod.rs | 2 +- src/libsyntax/fold.rs | 20 ++++---- src/libsyntax/parse/mod.rs | 2 +- src/libsyntax/parse/parser.rs | 48 ++++++++----------- src/libsyntax/print/pprust.rs | 48 +++++++++---------- src/libsyntax/test.rs | 2 +- src/libsyntax/visit.rs | 2 +- 41 files changed, 254 insertions(+), 273 deletions(-) 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/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..c638182d7f33f 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); 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/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..9673b9ab58630 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, @@ -2354,7 +2354,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 +3994,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 +4404,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()) @@ -5871,12 +5871,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/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..5b1ca8fc1c0e6 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 }; @@ -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/collect.rs b/src/librustc_typeck/collect.rs index 09cf708047601..0bb0f95a66b5c 100644 --- a/src/librustc_typeck/collect.rs +++ b/src/librustc_typeck/collect.rs @@ -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(), @@ -1446,7 +1446,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 +1457,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 +2151,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/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 3ee07df6ed447..75cf0c7a26b59 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -171,13 +171,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 +299,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..1d0929746c2f8 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) } } @@ -1111,7 +1111,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 +1364,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 +1378,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 +1789,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 +1798,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 +2071,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..a25d4352430d4 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, } 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..54b7ead5469a5 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), @@ -1813,13 +1813,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 +1841,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..1706df10d9a18 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, } } diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs index ae7a2127e9f60..812b1baa8f74f 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,7 +1604,7 @@ 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), 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_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/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..820ff08a25539 100644 --- a/src/libsyntax/ext/deriving/generic/mod.rs +++ b/src/libsyntax/ext/deriving/generic/mod.rs @@ -684,7 +684,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/fold.rs b/src/libsyntax/fold.rs index 611faa2c2c909..c2c77e5a16c8e 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) @@ -1077,7 +1077,7 @@ pub fn noop_fold_type_method(m: TypeMethod, fld: &mut T) -> TypeMetho id, ident, attrs, - fn_style, + unsafety, abi, decl, generics, @@ -1089,7 +1089,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), @@ -1211,7 +1211,7 @@ pub fn noop_fold_method(m: P, folder: &mut T) -> SmallVector< generics, abi, explicit_self, - fn_style, + unsafety, decl, body, vis) => { @@ -1219,7 +1219,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..cc96d45a1c8dd 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), @@ -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, @@ -5554,7 +5544,7 @@ impl<'a> Parser<'a> { // 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 +5565,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, diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs index 87905db22f349..53399aba99a9d 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, @@ -1188,7 +1188,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 +1223,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 +2164,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 +2588,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 +2603,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 +2872,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 +2906,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 +2920,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 +2950,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..6eedb77889ada 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), From 5686a91914ac678ccb78220367daefe585a0d66a Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 9 Dec 2014 19:59:20 -0500 Subject: [PATCH 2/5] Parse `unsafe trait` but do not do anything with it beyond parsing and integrating into rustdoc etc. --- src/librustc/lint/builtin.rs | 2 +- src/librustc/metadata/common.rs | 2 ++ src/librustc/metadata/decoder.rs | 5 +++++ src/librustc/metadata/encoder.rs | 11 ++++++++++- src/librustc/middle/privacy.rs | 10 +++++----- src/librustc/middle/resolve.rs | 4 ++-- src/librustc/middle/resolve_lifetime.rs | 2 +- src/librustc/middle/ty.rs | 4 +++- src/librustc_trans/save/mod.rs | 2 +- src/librustc_typeck/check/mod.rs | 2 +- src/librustc_typeck/collect.rs | 12 +++++++----- src/librustc_typeck/variance.rs | 2 +- src/librustdoc/clean/inline.rs | 1 + src/librustdoc/clean/mod.rs | 2 ++ src/librustdoc/doctree.rs | 1 + src/librustdoc/html/render.rs | 3 ++- src/librustdoc/visit_ast.rs | 3 ++- src/libsyntax/ast.rs | 3 ++- src/libsyntax/ast_map/mod.rs | 2 +- src/libsyntax/config.rs | 4 ++-- src/libsyntax/fold.rs | 5 +++-- src/libsyntax/parse/parser.rs | 24 +++++++++++++++++++++--- src/libsyntax/print/pprust.rs | 8 +++++--- src/libsyntax/visit.rs | 2 +- src/test/pretty/trait-safety.rs | 21 +++++++++++++++++++++ 25 files changed, 103 insertions(+), 34 deletions(-) create mode 100644 src/test/pretty/trait-safety.rs diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index e19fa01b2e4e8..5af7fec418168 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); 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..371242863984d 100644 --- a/src/librustc/metadata/decoder.rs +++ b/src/librustc/metadata/decoder.rs @@ -368,8 +368,13 @@ 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 = match reader::maybe_get_doc(item_doc, tag_unsafety) { + Some(_) => ast::Unsafety::Unsafe, + None => ast::Unsafety::Normal, + }; 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..cb8de25644801 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -1308,13 +1308,22 @@ 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); + + match trait_def.unsafety { + ast::Unsafety::Unsafe => { + rbml_w.start_tag(tag_unsafety); + rbml_w.end_tag(); + } + ast::Unsafety::Normal => { } + } + 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); diff --git a/src/librustc/middle/privacy.rs b/src/librustc/middle/privacy.rs index 79bb19a1e535f..352c2add00028 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) => { @@ -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) => { @@ -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) => { @@ -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 } diff --git a/src/librustc/middle/resolve.rs b/src/librustc/middle/resolve.rs index f2c83291b79e7..2e52bab2ae3ee 100644 --- a/src/librustc/middle/resolve.rs +++ b/src/librustc/middle/resolve.rs @@ -1583,7 +1583,7 @@ impl<'a> Resolver<'a> { ItemImpl(_, Some(_), _, _) => parent, - ItemTrait(_, _, _, ref items) => { + ItemTrait(_, _, _, _, ref items) => { let name_bindings = self.add_child(name, parent.clone(), @@ -4241,7 +4241,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..683948cd2e7e9 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| { diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 9673b9ab58630..4c4df698f3380 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -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 @@ -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() diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs index 329241b24e652..779fcd708647b 100644 --- a/src/librustc_trans/save/mod.rs +++ b/src/librustc_trans/save/mod.rs @@ -1050,7 +1050,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_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5b1ca8fc1c0e6..c64519c96dd1c 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -625,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 { diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs index 0bb0f95a66b5c..643d8eb60ceea 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() { @@ -1144,7 +1144,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 +1335,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 +1370,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 { 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 75cf0c7a26b59..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, diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1d0929746c2f8..92184ce93deec 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -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), diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs index a25d4352430d4..79f04e91260d8 100644 --- a/src/librustdoc/doctree.rs +++ b/src/librustdoc/doctree.rs @@ -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, diff --git a/src/librustdoc/html/render.rs b/src/librustdoc/html/render.rs index 54b7ead5469a5..1977b6320d0ec 100644 --- a/src/librustdoc/html/render.rs +++ b/src/librustdoc/html/render.rs @@ -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,
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index 1706df10d9a18..f94e647b1cf03 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -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(),
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index 812b1baa8f74f..1cc6b6feee83c 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1611,7 +1611,8 @@ pub enum Item_ {
     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,
diff --git a/src/libsyntax/ast_map/mod.rs b/src/libsyntax/ast_map/mod.rs
index 6f1d2d39b3049..a2cdc4d2fbc7d 100644
--- a/src/libsyntax/ast_map/mod.rs
+++ b/src/libsyntax/ast_map/mod.rs
@@ -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/config.rs b/src/libsyntax/config.rs
index 87426dce91817..ee6515921177a 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -139,11 +139,11 @@ fn fold_item_underscore(cx: &mut Context, item: ast::Item_) -> ast::Item_
                                        .collect();
             ast::ItemImpl(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/fold.rs b/src/libsyntax/fold.rs
index c2c77e5a16c8e..daed014f4eb07 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -1035,7 +1035,7 @@ pub fn noop_fold_item_underscore(i: Item_, folder: &mut T) -> Item_ {
                      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 +1063,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)
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index cc96d45a1c8dd..b2c30797cacb4 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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) {
@@ -5539,6 +5539,23 @@ 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::Fn) &&
                 self.look_ahead(1, |f| !Parser::fn_expr_lookahead(f)) {
             // FUNCTION ITEM
@@ -5614,7 +5631,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,
diff --git a/src/libsyntax/print/pprust.rs b/src/libsyntax/print/pprust.rs
index 53399aba99a9d..037118b145f4b 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -955,9 +955,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 {
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 6eedb77889ada..7bb79a15f4549 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -311,7 +311,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/pretty/trait-safety.rs b/src/test/pretty/trait-safety.rs
new file mode 100644
index 0000000000000..42e578482e6e0
--- /dev/null
+++ b/src/test/pretty/trait-safety.rs
@@ -0,0 +1,21 @@
+// 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);
+}
+
+pub unsafe trait PubUnsafeTrait {
+    fn foo(&self);
+}
+
+fn main() { }

From 22f777ba2ecfcd8d914d37db310a6feb4ad5219e Mon Sep 17 00:00:00 2001
From: Niko Matsakis 
Date: Wed, 10 Dec 2014 06:15:06 -0500
Subject: [PATCH 3/5] Parse `unsafe impl` but don't do anything particularly
 interesting with the results.

---
 src/librustc/lint/builtin.rs                 |  2 +-
 src/librustc/metadata/decoder.rs             | 14 ++++++++----
 src/librustc/metadata/encoder.rs             | 23 ++++++++++----------
 src/librustc/middle/dead.rs                  |  2 +-
 src/librustc/middle/infer/error_reporting.rs |  2 +-
 src/librustc/middle/privacy.rs               | 10 ++++-----
 src/librustc/middle/reachable.rs             |  4 ++--
 src/librustc/middle/resolve.rs               |  7 +++---
 src/librustc/middle/resolve_lifetime.rs      |  2 +-
 src/librustc/middle/ty.rs                    |  4 ++--
 src/librustc_trans/save/mod.rs               |  5 +++--
 src/librustc_trans/trans/base.rs             |  2 +-
 src/librustc_typeck/check/mod.rs             |  2 +-
 src/librustc_typeck/coherence/mod.rs         |  4 ++--
 src/librustc_typeck/coherence/orphan.rs      |  4 ++--
 src/librustc_typeck/collect.rs               |  3 ++-
 src/librustdoc/doctree.rs                    |  1 +
 src/librustdoc/visit_ast.rs                  |  3 ++-
 src/libsyntax/ast.rs                         |  3 ++-
 src/libsyntax/ast_map/mod.rs                 |  2 +-
 src/libsyntax/config.rs                      |  4 ++--
 src/libsyntax/ext/deriving/generic/mod.rs    |  3 ++-
 src/libsyntax/feature_gate.rs                |  2 +-
 src/libsyntax/fold.rs                        |  7 +++---
 src/libsyntax/parse/parser.rs                | 22 ++++++++++++++++---
 src/libsyntax/print/pprust.rs                | 10 ++++++---
 src/libsyntax/visit.rs                       |  3 ++-
 src/test/pretty/trait-safety.rs              |  4 ++++
 28 files changed, 97 insertions(+), 57 deletions(-)

diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 5af7fec418168..3040125d97e32 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -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/decoder.rs b/src/librustc/metadata/decoder.rs
index 371242863984d..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,10 +377,7 @@ 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 = match reader::maybe_get_doc(item_doc, tag_unsafety) {
-        Some(_) => ast::Unsafety::Unsafe,
-        None => ast::Unsafety::Normal,
-    };
+    let unsafety = parse_unsafety(item_doc);
 
     ty::TraitDef {
         unsafety: unsafety,
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index cb8de25644801..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 => {
@@ -1315,15 +1316,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_family(rbml_w, 'I');
         encode_item_variances(rbml_w, ecx, item.id);
         let trait_def = ty::lookup_trait_def(tcx, def_id);
-
-        match trait_def.unsafety {
-            ast::Unsafety::Unsafe => {
-                rbml_w.start_tag(tag_unsafety);
-                rbml_w.end_tag();
-            }
-            ast::Unsafety::Normal => { }
-        }
-
+        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);
@@ -1683,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
@@ -1864,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/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/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index c638182d7f33f..5c2944f898ed2 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -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/privacy.rs b/src/librustc/middle/privacy.rs
index 352c2add00028..8cce1321d728b 100644
--- a/src/librustc/middle/privacy.rs
+++ b/src/librustc/middle/privacy.rs
@@ -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() {
@@ -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");
@@ -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) => {
@@ -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 2e52bab2ae3ee..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,7 +1581,7 @@ impl<'a> Resolver<'a> {
                 parent
             }
 
-            ItemImpl(_, Some(_), _, _) => parent,
+            ItemImpl(_, _, Some(_), _, _) => parent,
 
             ItemTrait(_, _, _, _, ref items) => {
                 let name_bindings =
@@ -4230,7 +4230,8 @@ impl<'a> Resolver<'a> {
                 });
             }
 
-            ItemImpl(ref generics,
+            ItemImpl(_,
+                     ref generics,
                      ref implemented_traits,
                      ref self_type,
                      ref impl_items) => {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 683948cd2e7e9..48d6ac847d8d0 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -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/ty.rs b/src/librustc/middle/ty.rs
index 4c4df698f3380..d6fd3d9a94388 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -4741,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))
@@ -5722,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
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 779fcd708647b..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) => {
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_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index c64519c96dd1c..e0df94745d6a9 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -595,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));
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index defad95f749bd..7bc79d6e4a421 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -145,7 +145,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 +325,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| {
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/collect.rs b/src/librustc_typeck/collect.rs
index 643d8eb60ceea..61b8e6c956cab 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -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) => {
diff --git a/src/librustdoc/doctree.rs b/src/librustdoc/doctree.rs
index 79f04e91260d8..6592ca498dc64 100644
--- a/src/librustdoc/doctree.rs
+++ b/src/librustdoc/doctree.rs
@@ -184,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/visit_ast.rs b/src/librustdoc/visit_ast.rs
index f94e647b1cf03..4374ce5deef4e 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -338,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 1cc6b6feee83c..206fb26eb55cb 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -1617,7 +1617,8 @@ pub enum Item_ {
                                 // 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/mod.rs b/src/libsyntax/ast_map/mod.rs
index a2cdc4d2fbc7d..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) => {
diff --git a/src/libsyntax/config.rs b/src/libsyntax/config.rs
index ee6515921177a..d2185a00876d2 100644
--- a/src/libsyntax/config.rs
+++ b/src/libsyntax/config.rs
@@ -133,11 +133,11 @@ 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(u, a, b, c, methods) => {
             let methods = methods.into_iter()
diff --git a/src/libsyntax/ext/deriving/generic/mod.rs b/src/libsyntax/ext/deriving/generic/mod.rs
index 820ff08a25539..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()
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 daed014f4eb07..8a578c2cb05c0 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -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,7 +1030,8 @@ 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)
@@ -1160,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
diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs
index b2c30797cacb4..d1991c0463f44 100644
--- a/src/libsyntax/parse/parser.rs
+++ b/src/libsyntax/parse/parser.rs
@@ -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))
     }
 
@@ -5556,6 +5556,22 @@ 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::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
@@ -5644,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 037118b145f4b..db122f271a9c4 100644
--- a/src/libsyntax/print/pprust.rs
+++ b/src/libsyntax/print/pprust.rs
@@ -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));
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index 7bb79a15f4549..3535c6e267eba 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -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) => {
diff --git a/src/test/pretty/trait-safety.rs b/src/test/pretty/trait-safety.rs
index 42e578482e6e0..b96dbbf3cc964 100644
--- a/src/test/pretty/trait-safety.rs
+++ b/src/test/pretty/trait-safety.rs
@@ -14,6 +14,10 @@ unsafe trait UnsafeTrait {
     fn foo(&self);
 }
 
+unsafe impl UnsafeTrait for int {
+    fn foo(&self) { }
+}
+
 pub unsafe trait PubUnsafeTrait {
     fn foo(&self);
 }

From 5fe0ad1c0fde4c93ec010e95457d5831d11f013d Mon Sep 17 00:00:00 2001
From: Niko Matsakis 
Date: Wed, 10 Dec 2014 10:59:20 -0500
Subject: [PATCH 4/5] Implement `unsafe trait` semantics.

---
 src/librustc_typeck/coherence/mod.rs          |  2 +
 src/librustc_typeck/coherence/unsafety.rs     | 77 +++++++++++++++++++
 src/test/compile-fail/trait-safety-fn-body.rs | 25 ++++++
 .../trait-safety-inherent-impl.rs             | 19 +++++
 .../compile-fail/trait-safety-trait-impl.rs   | 28 +++++++
 5 files changed, 151 insertions(+)
 create mode 100644 src/librustc_typeck/coherence/unsafety.rs
 create mode 100644 src/test/compile-fail/trait-safety-fn-body.rs
 create mode 100644 src/test/compile-fail/trait-safety-inherent-impl.rs
 create mode 100644 src/test/compile-fail/trait-safety-trait-impl.rs

diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 7bc79d6e4a421..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,
@@ -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/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/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.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() { }

From 7855893ac7cbac32dcc801dcefe1ec845fa92616 Mon Sep 17 00:00:00 2001
From: Niko Matsakis 
Date: Wed, 10 Dec 2014 17:24:10 -0500
Subject: [PATCH 5/5] Add a bunch of new tests per Alex's suggestion.

---
 src/test/auxiliary/trait-safety-lib.rs        | 19 +++++++++++
 .../trait-safety-trait-impl-cc.rs             | 25 +++++++++++++++
 src/test/run-pass/trait-safety-ok-cc.rs       | 32 +++++++++++++++++++
 src/test/run-pass/trait-safety-ok.rs          | 26 +++++++++++++++
 4 files changed, 102 insertions(+)
 create mode 100644 src/test/auxiliary/trait-safety-lib.rs
 create mode 100644 src/test/compile-fail/trait-safety-trait-impl-cc.rs
 create mode 100644 src/test/run-pass/trait-safety-ok-cc.rs
 create mode 100644 src/test/run-pass/trait-safety-ok.rs

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-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/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));
+}