Skip to content

Commit

Permalink
auto merge of rust-lang#19703 : nikomatsakis/rust/unsafe-trait, r=acr…
Browse files Browse the repository at this point in the history
…ichto

This PR allows declaring traits and impls as `unsafe`. An `unsafe` trait requires an `unsafe` impl. An `unsafe` impl does not permit unsafe code within its interior (unless that code is contained within an unsafe block or unsafe fn, as normal). The commits are standalone.

r? @alexcrichton 
cc rust-lang#13231
  • Loading branch information
bors committed Dec 14, 2014
2 parents 93c0610 + 7855893 commit 6085a71
Show file tree
Hide file tree
Showing 67 changed files with 694 additions and 351 deletions.
4 changes: 2 additions & 2 deletions src/librustc/lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1721,15 +1721,15 @@ 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);
self.lint(cx, id, t.trait_ref.path.span);
}
}
}
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);
}
Expand Down
2 changes: 2 additions & 0 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
11 changes: 11 additions & 0 deletions src/librustc/metadata/decoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -361,15 +361,26 @@ 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>
{
let item_doc = lookup_item(item_id, cdata.data());
let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
let bounds = trait_def_bounds(item_doc, tcx, cdata);
let unsafety = parse_unsafety(item_doc);

ty::TraitDef {
unsafety: unsafety,
generics: generics,
bounds: bounds,
trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))
Expand Down
16 changes: 13 additions & 3 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -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 => {
Expand Down Expand Up @@ -1308,13 +1309,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
}
}
}
ast::ItemTrait(_, _, _, ref ms) => {
ast::ItemTrait(_, _, _, _, ref ms) => {
add_to_index(item, rbml_w, index);
rbml_w.start_tag(tag_items_data_item);
encode_def_id(rbml_w, def_id);
encode_family(rbml_w, 'I');
encode_item_variances(rbml_w, ecx, item.id);
let trait_def = ty::lookup_trait_def(tcx, def_id);
encode_unsafety(rbml_w, trait_def.unsafety);
encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
encode_name(rbml_w, item.ident.name);
Expand Down Expand Up @@ -1674,6 +1676,14 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
rbml_w.end_tag();
}

fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
let byte: u8 = match unsafety {
ast::Unsafety::Normal => 0,
ast::Unsafety::Unsafe => 1,
};
rbml_w.wr_tagged_u8(tag_unsafety, byte);
}

fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
// Pull the cnums and name,vers,hash out of cstore
Expand Down Expand Up @@ -1855,7 +1865,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {

impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
fn visit_item(&mut self, item: &ast::Item) {
if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node {
if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node {
let def_map = &self.ecx.tcx.def_map;
let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
let def_id = trait_def.def_id();
Expand Down
16 changes: 8 additions & 8 deletions src/librustc/metadata/tydecode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
}

Expand All @@ -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,
Expand All @@ -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
}
Expand Down
10 changes: 5 additions & 5 deletions src/librustc/metadata/tyencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"),
}
}

Expand All @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/dead.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) => {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc/middle/effect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
}
}
Expand Down Expand Up @@ -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),
};

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/infer/coercion.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand Down
16 changes: 8 additions & 8 deletions src/librustc/middle/infer/combine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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>,
Expand All @@ -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,
Expand All @@ -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 {
Expand Down
6 changes: 3 additions & 3 deletions src/librustc/middle/infer/equate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
}
Expand Down
16 changes: 8 additions & 8 deletions src/librustc/middle/infer/error_reporting.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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))
Expand All @@ -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))
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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());
}
_ => ()
Expand Down
9 changes: 4 additions & 5 deletions src/librustc/middle/infer/glb.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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)
}
}

Expand Down
Loading

0 comments on commit 6085a71

Please sign in to comment.