Skip to content

Commit 6085a71

Browse files
committed
auto merge of #19703 : nikomatsakis/rust/unsafe-trait, r=acrichto
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 #13231
2 parents 93c0610 + 7855893 commit 6085a71

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

67 files changed

+694
-351
lines changed

src/librustc/lint/builtin.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1721,15 +1721,15 @@ impl LintPass for Stability {
17211721
if self.is_internal(cx, item.span) { return }
17221722

17231723
match item.node {
1724-
ast::ItemTrait(_, _, ref supertraits, _) => {
1724+
ast::ItemTrait(_, _, _, ref supertraits, _) => {
17251725
for t in supertraits.iter() {
17261726
if let ast::TraitTyParamBound(ref t) = *t {
17271727
let id = ty::trait_ref_to_def_id(cx.tcx, &t.trait_ref);
17281728
self.lint(cx, id, t.trait_ref.path.span);
17291729
}
17301730
}
17311731
}
1732-
ast::ItemImpl(_, Some(ref t), _, _) => {
1732+
ast::ItemImpl(_, _, Some(ref t), _, _) => {
17331733
let id = ty::trait_ref_to_def_id(cx.tcx, t);
17341734
self.lint(cx, id, t.path.span);
17351735
}

src/librustc/metadata/common.rs

+2
Original file line numberDiff line numberDiff line change
@@ -255,3 +255,5 @@ pub const tag_method_ty_generics: uint = 0xa7;
255255
pub const tag_predicate: uint = 0xa8;
256256
pub const tag_predicate_space: uint = 0xa9;
257257
pub const tag_predicate_data: uint = 0xb0;
258+
259+
pub const tag_unsafety: uint = 0xb1;

src/librustc/metadata/decoder.rs

+11
Original file line numberDiff line numberDiff line change
@@ -361,15 +361,26 @@ fn item_to_def_like(item: rbml::Doc, did: ast::DefId, cnum: ast::CrateNum)
361361
}
362362
}
363363

364+
fn parse_unsafety(item_doc: rbml::Doc) -> ast::Unsafety {
365+
let unsafety_doc = reader::get_doc(item_doc, tag_unsafety);
366+
if reader::doc_as_u8(unsafety_doc) != 0 {
367+
ast::Unsafety::Unsafe
368+
} else {
369+
ast::Unsafety::Normal
370+
}
371+
}
372+
364373
pub fn get_trait_def<'tcx>(cdata: Cmd,
365374
item_id: ast::NodeId,
366375
tcx: &ty::ctxt<'tcx>) -> ty::TraitDef<'tcx>
367376
{
368377
let item_doc = lookup_item(item_id, cdata.data());
369378
let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
370379
let bounds = trait_def_bounds(item_doc, tcx, cdata);
380+
let unsafety = parse_unsafety(item_doc);
371381

372382
ty::TraitDef {
383+
unsafety: unsafety,
373384
generics: generics,
374385
bounds: bounds,
375386
trait_ref: Rc::new(item_trait_ref(item_doc, tcx, cdata))

src/librustc/metadata/encoder.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -1205,7 +1205,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
12051205
None => {}
12061206
}
12071207
}
1208-
ast::ItemImpl(_, ref opt_trait, ref ty, ref ast_items) => {
1208+
ast::ItemImpl(unsafety, _, ref opt_trait, ref ty, ref ast_items) => {
12091209
// We need to encode information about the default methods we
12101210
// have inherited, so we drive this based on the impl structure.
12111211
let impl_items = tcx.impl_items.borrow();
@@ -1218,6 +1218,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
12181218
encode_bounds_and_type(rbml_w, ecx, &lookup_item_type(tcx, def_id));
12191219
encode_name(rbml_w, item.ident.name);
12201220
encode_attributes(rbml_w, item.attrs.as_slice());
1221+
encode_unsafety(rbml_w, unsafety);
12211222
match ty.node {
12221223
ast::TyPath(ref path, _) if path.segments
12231224
.len() == 1 => {
@@ -1308,13 +1309,14 @@ fn encode_info_for_item(ecx: &EncodeContext,
13081309
}
13091310
}
13101311
}
1311-
ast::ItemTrait(_, _, _, ref ms) => {
1312+
ast::ItemTrait(_, _, _, _, ref ms) => {
13121313
add_to_index(item, rbml_w, index);
13131314
rbml_w.start_tag(tag_items_data_item);
13141315
encode_def_id(rbml_w, def_id);
13151316
encode_family(rbml_w, 'I');
13161317
encode_item_variances(rbml_w, ecx, item.id);
13171318
let trait_def = ty::lookup_trait_def(tcx, def_id);
1319+
encode_unsafety(rbml_w, trait_def.unsafety);
13181320
encode_generics(rbml_w, ecx, &trait_def.generics, tag_item_generics);
13191321
encode_trait_ref(rbml_w, ecx, &*trait_def.trait_ref, tag_item_trait_ref);
13201322
encode_name(rbml_w, item.ident.name);
@@ -1674,6 +1676,14 @@ fn encode_attributes(rbml_w: &mut Encoder, attrs: &[ast::Attribute]) {
16741676
rbml_w.end_tag();
16751677
}
16761678

1679+
fn encode_unsafety(rbml_w: &mut Encoder, unsafety: ast::Unsafety) {
1680+
let byte: u8 = match unsafety {
1681+
ast::Unsafety::Normal => 0,
1682+
ast::Unsafety::Unsafe => 1,
1683+
};
1684+
rbml_w.wr_tagged_u8(tag_unsafety, byte);
1685+
}
1686+
16771687
fn encode_crate_deps(rbml_w: &mut Encoder, cstore: &cstore::CStore) {
16781688
fn get_ordered_deps(cstore: &cstore::CStore) -> Vec<decoder::CrateDep> {
16791689
// Pull the cnums and name,vers,hash out of cstore
@@ -1855,7 +1865,7 @@ struct ImplVisitor<'a, 'b:'a, 'c:'a, 'tcx:'b> {
18551865

18561866
impl<'a, 'b, 'c, 'tcx, 'v> Visitor<'v> for ImplVisitor<'a, 'b, 'c, 'tcx> {
18571867
fn visit_item(&mut self, item: &ast::Item) {
1858-
if let ast::ItemImpl(_, Some(ref trait_ref), _, _) = item.node {
1868+
if let ast::ItemImpl(_, _, Some(ref trait_ref), _, _) = item.node {
18591869
let def_map = &self.ecx.tcx.def_map;
18601870
let trait_def = def_map.borrow()[trait_ref.ref_id].clone();
18611871
let def_id = trait_def.def_id();

src/librustc/metadata/tydecode.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -549,11 +549,11 @@ fn parse_hex(st: &mut PState) -> uint {
549549
};
550550
}
551551

552-
fn parse_fn_style(c: char) -> ast::FnStyle {
552+
fn parse_unsafety(c: char) -> ast::Unsafety {
553553
match c {
554-
'u' => ast::UnsafeFn,
555-
'n' => ast::NormalFn,
556-
_ => panic!("parse_fn_style: bad fn_style {}", c)
554+
'u' => ast::Unsafety::Unsafe,
555+
'n' => ast::Unsafety::Normal,
556+
_ => panic!("parse_unsafety: bad unsafety {}", c)
557557
}
558558
}
559559

@@ -575,14 +575,14 @@ fn parse_onceness(c: char) -> ast::Onceness {
575575

576576
fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
577577
conv: conv_did) -> ty::ClosureTy<'tcx> {
578-
let fn_style = parse_fn_style(next(st));
578+
let unsafety = parse_unsafety(next(st));
579579
let onceness = parse_onceness(next(st));
580580
let store = parse_trait_store(st, |x,y| conv(x,y));
581581
let bounds = parse_existential_bounds(st, |x,y| conv(x,y));
582582
let sig = parse_sig(st, |x,y| conv(x,y));
583583
let abi = parse_abi_set(st);
584584
ty::ClosureTy {
585-
fn_style: fn_style,
585+
unsafety: unsafety,
586586
onceness: onceness,
587587
store: store,
588588
bounds: bounds,
@@ -593,11 +593,11 @@ fn parse_closure_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
593593

594594
fn parse_bare_fn_ty<'a, 'tcx>(st: &mut PState<'a, 'tcx>,
595595
conv: conv_did) -> ty::BareFnTy<'tcx> {
596-
let fn_style = parse_fn_style(next(st));
596+
let unsafety = parse_unsafety(next(st));
597597
let abi = parse_abi_set(st);
598598
let sig = parse_sig(st, |x,y| conv(x,y));
599599
ty::BareFnTy {
600-
fn_style: fn_style,
600+
unsafety: unsafety,
601601
abi: abi,
602602
sig: sig
603603
}

src/librustc/metadata/tyencode.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -313,10 +313,10 @@ fn enc_sty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
313313
}
314314
}
315315

316-
fn enc_fn_style(w: &mut SeekableMemWriter, p: ast::FnStyle) {
316+
fn enc_unsafety(w: &mut SeekableMemWriter, p: ast::Unsafety) {
317317
match p {
318-
ast::NormalFn => mywrite!(w, "n"),
319-
ast::UnsafeFn => mywrite!(w, "u"),
318+
ast::Unsafety::Normal => mywrite!(w, "n"),
319+
ast::Unsafety::Unsafe => mywrite!(w, "u"),
320320
}
321321
}
322322

@@ -335,14 +335,14 @@ fn enc_onceness(w: &mut SeekableMemWriter, o: ast::Onceness) {
335335

336336
pub fn enc_bare_fn_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
337337
ft: &ty::BareFnTy<'tcx>) {
338-
enc_fn_style(w, ft.fn_style);
338+
enc_unsafety(w, ft.unsafety);
339339
enc_abi(w, ft.abi);
340340
enc_fn_sig(w, cx, &ft.sig);
341341
}
342342

343343
pub fn enc_closure_ty<'a, 'tcx>(w: &mut SeekableMemWriter, cx: &ctxt<'a, 'tcx>,
344344
ft: &ty::ClosureTy<'tcx>) {
345-
enc_fn_style(w, ft.fn_style);
345+
enc_unsafety(w, ft.unsafety);
346346
enc_onceness(w, ft.onceness);
347347
enc_trait_store(w, cx, ft.store);
348348
enc_existential_bounds(w, cx, &ft.bounds);

src/librustc/middle/dead.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -355,7 +355,7 @@ impl<'v> Visitor<'v> for LifeSeeder {
355355
ast::ItemEnum(ref enum_def, _) if allow_dead_code => {
356356
self.worklist.extend(enum_def.variants.iter().map(|variant| variant.node.id));
357357
}
358-
ast::ItemImpl(_, Some(ref _trait_ref), _, ref impl_items) => {
358+
ast::ItemImpl(_, _, Some(ref _trait_ref), _, ref impl_items) => {
359359
for impl_item in impl_items.iter() {
360360
match *impl_item {
361361
ast::MethodImplItem(ref method) => {

src/librustc/middle/effect.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,8 @@ impl Copy for UnsafeContext {}
3434

3535
fn type_is_unsafe_function(ty: Ty) -> bool {
3636
match ty.sty {
37-
ty::ty_bare_fn(ref f) => f.fn_style == ast::UnsafeFn,
38-
ty::ty_closure(ref f) => f.fn_style == ast::UnsafeFn,
37+
ty::ty_bare_fn(ref f) => f.unsafety == ast::Unsafety::Unsafe,
38+
ty::ty_closure(ref f) => f.unsafety == ast::Unsafety::Unsafe,
3939
_ => false,
4040
}
4141
}
@@ -92,9 +92,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
9292

9393
let (is_item_fn, is_unsafe_fn) = match fn_kind {
9494
visit::FkItemFn(_, _, fn_style, _) =>
95-
(true, fn_style == ast::UnsafeFn),
95+
(true, fn_style == ast::Unsafety::Unsafe),
9696
visit::FkMethod(_, _, method) =>
97-
(true, method.pe_fn_style() == ast::UnsafeFn),
97+
(true, method.pe_unsafety() == ast::Unsafety::Unsafe),
9898
_ => (false, false),
9999
};
100100

src/librustc/middle/infer/coercion.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -521,7 +521,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
521521
debug!("coerce_from_bare_fn(a={}, b={})",
522522
a.repr(self.get_ref().infcx.tcx), b.repr(self.get_ref().infcx.tcx));
523523

524-
if fn_ty_a.abi != abi::Rust || fn_ty_a.fn_style != ast::NormalFn {
524+
if fn_ty_a.abi != abi::Rust || fn_ty_a.unsafety != ast::Unsafety::Normal {
525525
return self.subtype(a, b);
526526
}
527527

src/librustc/middle/infer/combine.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use middle::ty_fold;
5151
use middle::ty_fold::{TypeFoldable};
5252
use util::ppaux::Repr;
5353

54-
use syntax::ast::{Onceness, FnStyle};
54+
use syntax::ast::{Onceness, Unsafety};
5555
use syntax::ast;
5656
use syntax::abi;
5757
use syntax::codemap::Span;
@@ -193,12 +193,12 @@ pub trait Combine<'tcx> {
193193

194194
fn bare_fn_tys(&self, a: &ty::BareFnTy<'tcx>,
195195
b: &ty::BareFnTy<'tcx>) -> cres<'tcx, ty::BareFnTy<'tcx>> {
196-
let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style));
196+
let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
197197
let abi = try!(self.abi(a.abi, b.abi));
198198
let sig = try!(self.fn_sigs(&a.sig, &b.sig));
199-
Ok(ty::BareFnTy {fn_style: fn_style,
200-
abi: abi,
201-
sig: sig})
199+
Ok(ty::BareFnTy {unsafety: unsafety,
200+
abi: abi,
201+
sig: sig})
202202
}
203203

204204
fn closure_tys(&self, a: &ty::ClosureTy<'tcx>,
@@ -219,13 +219,13 @@ pub trait Combine<'tcx> {
219219
return Err(ty::terr_sigil_mismatch(expected_found(self, a.store, b.store)))
220220
}
221221
};
222-
let fn_style = try!(self.fn_styles(a.fn_style, b.fn_style));
222+
let unsafety = try!(self.unsafeties(a.unsafety, b.unsafety));
223223
let onceness = try!(self.oncenesses(a.onceness, b.onceness));
224224
let bounds = try!(self.existential_bounds(a.bounds, b.bounds));
225225
let sig = try!(self.fn_sigs(&a.sig, &b.sig));
226226
let abi = try!(self.abi(a.abi, b.abi));
227227
Ok(ty::ClosureTy {
228-
fn_style: fn_style,
228+
unsafety: unsafety,
229229
onceness: onceness,
230230
store: store,
231231
bounds: bounds,
@@ -240,7 +240,7 @@ pub trait Combine<'tcx> {
240240
self.contratys(a, b).and_then(|t| Ok(t))
241241
}
242242

243-
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle>;
243+
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety>;
244244

245245
fn abi(&self, a: abi::Abi, b: abi::Abi) -> cres<'tcx, abi::Abi> {
246246
if a == b {

src/librustc/middle/infer/equate.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use middle::infer::{TypeTrace, Subtype};
2121
use middle::infer::type_variable::{EqTo};
2222
use util::ppaux::{Repr};
2323

24-
use syntax::ast::{Onceness, FnStyle};
24+
use syntax::ast::{Onceness, Unsafety};
2525

2626
pub struct Equate<'f, 'tcx: 'f> {
2727
fields: CombineFields<'f, 'tcx>
@@ -70,9 +70,9 @@ impl<'f, 'tcx> Combine<'tcx> for Equate<'f, 'tcx> {
7070
Ok(ty::mt { mutbl: a.mutbl, ty: t })
7171
}
7272

73-
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> {
73+
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
7474
if a != b {
75-
Err(ty::terr_fn_style_mismatch(expected_found(self, a, b)))
75+
Err(ty::terr_unsafety_mismatch(expected_found(self, a, b)))
7676
} else {
7777
Ok(a)
7878
}

src/librustc/middle/infer/error_reporting.rs

+8-8
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ trait ErrorReportingHelpers<'tcx> {
157157

158158
fn give_expl_lifetime_param(&self,
159159
decl: &ast::FnDecl,
160-
fn_style: ast::FnStyle,
160+
unsafety: ast::Unsafety,
161161
ident: ast::Ident,
162162
opt_explicit_self: Option<&ast::ExplicitSelf_>,
163163
generics: &ast::Generics,
@@ -828,7 +828,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
828828
ast::MethodImplItem(ref m) => {
829829
Some((m.pe_fn_decl(),
830830
m.pe_generics(),
831-
m.pe_fn_style(),
831+
m.pe_unsafety(),
832832
m.pe_ident(),
833833
Some(&m.pe_explicit_self().node),
834834
m.span))
@@ -841,7 +841,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
841841
ast::ProvidedMethod(ref m) => {
842842
Some((m.pe_fn_decl(),
843843
m.pe_generics(),
844-
m.pe_fn_style(),
844+
m.pe_unsafety(),
845845
m.pe_ident(),
846846
Some(&m.pe_explicit_self().node),
847847
m.span))
@@ -853,14 +853,14 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
853853
},
854854
None => None
855855
};
856-
let (fn_decl, generics, fn_style, ident, expl_self, span)
856+
let (fn_decl, generics, unsafety, ident, expl_self, span)
857857
= node_inner.expect("expect item fn");
858858
let taken = lifetimes_in_scope(self.tcx, scope_id);
859859
let life_giver = LifeGiver::with_taken(taken.as_slice());
860860
let rebuilder = Rebuilder::new(self.tcx, fn_decl, expl_self,
861861
generics, same_regions, &life_giver);
862862
let (fn_decl, expl_self, generics) = rebuilder.rebuild();
863-
self.give_expl_lifetime_param(&fn_decl, fn_style, ident,
863+
self.give_expl_lifetime_param(&fn_decl, unsafety, ident,
864864
expl_self.as_ref(), &generics, span);
865865
}
866866
}
@@ -1407,12 +1407,12 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
14071407
impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
14081408
fn give_expl_lifetime_param(&self,
14091409
decl: &ast::FnDecl,
1410-
fn_style: ast::FnStyle,
1410+
unsafety: ast::Unsafety,
14111411
ident: ast::Ident,
14121412
opt_explicit_self: Option<&ast::ExplicitSelf_>,
14131413
generics: &ast::Generics,
14141414
span: codemap::Span) {
1415-
let suggested_fn = pprust::fun_to_string(decl, fn_style, ident,
1415+
let suggested_fn = pprust::fun_to_string(decl, unsafety, ident,
14161416
opt_explicit_self, generics);
14171417
let msg = format!("consider using an explicit lifetime \
14181418
parameter as shown: {}", suggested_fn);
@@ -1690,7 +1690,7 @@ fn lifetimes_in_scope(tcx: &ty::ctxt,
16901690
match tcx.map.find(parent) {
16911691
Some(node) => match node {
16921692
ast_map::NodeItem(item) => match item.node {
1693-
ast::ItemImpl(ref gen, _, _, _) => {
1693+
ast::ItemImpl(_, ref gen, _, _, _) => {
16941694
taken.push_all(gen.lifetimes.as_slice());
16951695
}
16961696
_ => ()

src/librustc/middle/infer/glb.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,7 @@ use super::{TypeTrace, Subtype};
2020
use middle::ty::{BuiltinBounds};
2121
use middle::ty::{mod, Ty};
2222
use syntax::ast::{Many, Once, MutImmutable, MutMutable};
23-
use syntax::ast::{NormalFn, UnsafeFn};
24-
use syntax::ast::{Onceness, FnStyle};
23+
use syntax::ast::{Onceness, Unsafety};
2524
use util::ppaux::mt_to_string;
2625
use util::ppaux::Repr;
2726

@@ -81,10 +80,10 @@ impl<'f, 'tcx> Combine<'tcx> for Glb<'f, 'tcx> {
8180
self.lub().tys(a, b)
8281
}
8382

84-
fn fn_styles(&self, a: FnStyle, b: FnStyle) -> cres<'tcx, FnStyle> {
83+
fn unsafeties(&self, a: Unsafety, b: Unsafety) -> cres<'tcx, Unsafety> {
8584
match (a, b) {
86-
(NormalFn, _) | (_, NormalFn) => Ok(NormalFn),
87-
(UnsafeFn, UnsafeFn) => Ok(UnsafeFn)
85+
(Unsafety::Normal, _) | (_, Unsafety::Normal) => Ok(Unsafety::Normal),
86+
(Unsafety::Unsafe, Unsafety::Unsafe) => Ok(Unsafety::Unsafe)
8887
}
8988
}
9089

0 commit comments

Comments
 (0)