rollup merge of #24921: tamird/bitflags-associated-const

Conflicts:
	src/librustc/lib.rs
This commit is contained in:
Alex Crichton 2015-04-29 15:49:07 -07:00
commit 2edb6438cb
24 changed files with 341 additions and 295 deletions

View File

@ -25,22 +25,23 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(associated_consts)]
#![feature(box_patterns)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(fs_canonicalize)]
#![feature(hash)]
#![feature(into_cow)]
#![feature(libc)]
#![feature(path_ext)]
#![feature(quote)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(path_ext)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(fs_canonicalize)]
#![feature(slice_patterns)]
#![cfg_attr(test, feature(test))]
#![allow(trivial_casts)]

View File

@ -46,33 +46,35 @@ bitflags! {
#[derive(RustcEncodable, RustcDecodable)]
flags ConstQualif: u8 {
// Const rvalue which can be placed behind a reference.
const PURE_CONST = 0b000000,
const PURE_CONST = 0,
// Inner mutability (can not be placed behind a reference) or behind
// &mut in a non-global expression. Can be copied from static memory.
const MUTABLE_MEM = 0b000001,
const MUTABLE_MEM = 1 << 0,
// Constant value with a type that implements Drop. Can be copied
// from static memory, similar to MUTABLE_MEM.
const NEEDS_DROP = 0b000010,
const NEEDS_DROP = 1 << 1,
// Even if the value can be placed in static memory, copying it from
// there is more expensive than in-place instantiation, and/or it may
// be too large. This applies to [T; N] and everything containing it.
// N.B.: references need to clear this flag to not end up on the stack.
const PREFER_IN_PLACE = 0b000100,
const PREFER_IN_PLACE = 1 << 2,
// May use more than 0 bytes of memory, doesn't impact the constness
// directly, but is not allowed to be borrowed mutably in a constant.
const NON_ZERO_SIZED = 0b001000,
const NON_ZERO_SIZED = 1 << 3,
// Actually borrowed, has to always be in static memory. Does not
// propagate, and requires the expression to behave like a 'static
// lvalue. The set of expressions with this flag is the minimum
// that have to be promoted.
const HAS_STATIC_BORROWS = 0b010000,
const HAS_STATIC_BORROWS = 1 << 4,
// Invalid const for miscellaneous reasons (e.g. not implemented).
const NOT_CONST = 0b100000,
const NOT_CONST = 1 << 5,
// Borrowing the expression won't produce &'static T if any of these
// bits are set, though the value could be copied from static memory
// if `NOT_CONST` isn't set.
const NON_STATIC_BORROWS = MUTABLE_MEM.bits | NEEDS_DROP.bits | NOT_CONST.bits
const NON_STATIC_BORROWS = ConstQualif::MUTABLE_MEM.bits |
ConstQualif::NEEDS_DROP.bits |
ConstQualif::NOT_CONST.bits
}
}
@ -102,7 +104,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
{
let (old_mode, old_qualif) = (self.mode, self.qualif);
self.mode = mode;
self.qualif = PURE_CONST;
self.qualif = ConstQualif::PURE_CONST;
let r = f(self);
self.mode = old_mode;
self.qualif = old_qualif;
@ -126,7 +128,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
Entry::Occupied(entry) => return *entry.get(),
Entry::Vacant(entry) => {
// Prevent infinite recursion on re-entry.
entry.insert(PURE_CONST);
entry.insert(ConstQualif::PURE_CONST);
}
}
self.with_mode(mode, |this| {
@ -271,7 +273,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
fn visit_expr(&mut self, ex: &ast::Expr) {
let mut outer = self.qualif;
self.qualif = PURE_CONST;
self.qualif = ConstQualif::PURE_CONST;
let node_ty = ty::node_id_to_type(self.tcx, ex.id);
check_expr(self, ex, node_ty);
@ -287,7 +289,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
self.visit_expr(&**callee);
// The callee's size doesn't count in the call.
let added = self.qualif - inner;
self.qualif = inner | (added - NON_ZERO_SIZED);
self.qualif = inner | (added - ConstQualif::NON_ZERO_SIZED);
}
ast::ExprRepeat(ref element, _) => {
self.visit_expr(&**element);
@ -298,7 +300,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
};
// [element; 0] is always zero-sized.
if count == 0 {
self.qualif = self.qualif - (NON_ZERO_SIZED | PREFER_IN_PLACE);
self.qualif.remove(ConstQualif::NON_ZERO_SIZED | ConstQualif::PREFER_IN_PLACE);
}
}
ast::ExprMatch(ref discr, ref arms, _) => {
@ -325,7 +327,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
let div_or_rem = op.node == ast::BiDiv || op.node == ast::BiRem;
match node_ty.sty {
ty::ty_uint(_) | ty::ty_int(_) if div_or_rem => {
if !self.qualif.intersects(NOT_CONST) {
if !self.qualif.intersects(ConstQualif::NOT_CONST) {
match const_eval::eval_const_expr_partial(self.tcx, ex, None) {
Ok(_) => {}
Err(msg) => {
@ -348,11 +350,11 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
// Constants cannot be borrowed if they contain interior mutability as
// it means that our "silent insertion of statics" could change
// initializer values (very bad).
// If the type doesn't have interior mutability, then `MUTABLE_MEM` has
// If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
// propagated from another error, so erroring again would be just noise.
let tc = ty::type_contents(self.tcx, node_ty);
if self.qualif.intersects(MUTABLE_MEM) && tc.interior_unsafe() {
outer = outer | NOT_CONST;
if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
outer = outer | ConstQualif::NOT_CONST;
if self.mode != Mode::Var {
self.tcx.sess.span_err(ex.span,
"cannot borrow a constant which contains \
@ -361,32 +363,32 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
}
// If the reference has to be 'static, avoid in-place initialization
// as that will end up pointing to the stack instead.
if !self.qualif.intersects(NON_STATIC_BORROWS) {
self.qualif = self.qualif - PREFER_IN_PLACE;
self.add_qualif(HAS_STATIC_BORROWS);
if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
self.qualif = self.qualif - ConstQualif::PREFER_IN_PLACE;
self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
}
}
Some(ast::MutMutable) => {
// `&mut expr` means expr could be mutated, unless it's zero-sized.
if self.qualif.intersects(NON_ZERO_SIZED) {
if self.qualif.intersects(ConstQualif::NON_ZERO_SIZED) {
if self.mode == Mode::Var {
outer = outer | NOT_CONST;
self.add_qualif(MUTABLE_MEM);
outer = outer | ConstQualif::NOT_CONST;
self.add_qualif(ConstQualif::MUTABLE_MEM);
} else {
span_err!(self.tcx.sess, ex.span, E0017,
"references in {}s may only refer \
to immutable values", self.msg())
}
}
if !self.qualif.intersects(NON_STATIC_BORROWS) {
self.add_qualif(HAS_STATIC_BORROWS);
if !self.qualif.intersects(ConstQualif::NON_STATIC_BORROWS) {
self.add_qualif(ConstQualif::HAS_STATIC_BORROWS);
}
}
None => {}
}
self.tcx.const_qualif_map.borrow_mut().insert(ex.id, self.qualif);
// Don't propagate certain flags.
self.qualif = outer | (self.qualif - HAS_STATIC_BORROWS);
self.qualif = outer | (self.qualif - ConstQualif::HAS_STATIC_BORROWS);
}
}
@ -401,7 +403,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
match node_ty.sty {
ty::ty_struct(did, _) |
ty::ty_enum(did, _) if ty::has_dtor(v.tcx, did) => {
v.add_qualif(NEEDS_DROP);
v.add_qualif(ConstQualif::NEEDS_DROP);
if v.mode != Mode::Var {
v.tcx.sess.span_err(e.span,
&format!("{}s are not allowed to have destructors",
@ -416,7 +418,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
ast::ExprUnary(..) |
ast::ExprBinary(..) |
ast::ExprIndex(..) if v.tcx.method_map.borrow().contains_key(&method_call) => {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0011,
"user-defined operators are not allowed in {}s", v.msg());
@ -424,7 +426,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
ast::ExprBox(..) |
ast::ExprUnary(ast::UnUniq, _) => {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0010,
"allocations are not allowed in {}s", v.msg());
@ -434,7 +436,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
match ty::node_id_to_type(v.tcx, ptr.id).sty {
ty::ty_ptr(_) => {
// This shouldn't be allowed in constants at all.
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
}
_ => {}
}
@ -447,7 +449,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
ty::type_is_unsafe_ptr(toty) ||
(ty::type_is_bare_fn(toty) && ty::type_is_bare_fn_item(fromty));
if !is_legal_cast {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0012,
"can not cast to `{}` in {}s",
@ -455,7 +457,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
}
if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0018,
"can not cast a pointer to an integer in {}s", v.msg());
@ -467,17 +469,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
match def {
Some(def::DefVariant(_, _, _)) => {
// Count the discriminator or function pointer.
v.add_qualif(NON_ZERO_SIZED);
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
Some(def::DefStruct(_)) => {
if let ty::ty_bare_fn(..) = node_ty.sty {
// Count the function pointer.
v.add_qualif(NON_ZERO_SIZED);
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
}
Some(def::DefFn(..)) | Some(def::DefMethod(..)) => {
// Count the function pointer.
v.add_qualif(NON_ZERO_SIZED);
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
Some(def::DefStatic(..)) => {
match v.mode {
@ -487,7 +489,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
"constants cannot refer to other statics, \
insert an intermediate constant instead");
}
Mode::Var => v.add_qualif(NOT_CONST)
Mode::Var => v.add_qualif(ConstQualif::NOT_CONST)
}
}
Some(def::DefConst(did)) |
@ -503,7 +505,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
}
def => {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
debug!("(checking const) found bad def: {:?}", def);
span_err!(v.tcx.sess, e.span, E0014,
@ -530,10 +532,10 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
Some(def::DefStruct(..)) => {}
Some(def::DefVariant(..)) => {
// Count the discriminator.
v.add_qualif(NON_ZERO_SIZED);
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
_ => {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0015,
"function calls in {}s are limited to \
@ -545,7 +547,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
ast::ExprBlock(ref block) => {
// Check all statements in the block
let mut block_span_err = |span| {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, span, E0016,
"blocks in {}s are limited to items and \
@ -574,17 +576,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
ast::ExprStruct(..) => {
let did = v.tcx.def_map.borrow().get(&e.id).map(|def| def.def_id());
if did == v.tcx.lang_items.unsafe_cell_type() {
v.add_qualif(MUTABLE_MEM);
v.add_qualif(ConstQualif::MUTABLE_MEM);
}
}
ast::ExprLit(_) |
ast::ExprAddrOf(..) => {
v.add_qualif(NON_ZERO_SIZED);
v.add_qualif(ConstQualif::NON_ZERO_SIZED);
}
ast::ExprRepeat(..) => {
v.add_qualif(PREFER_IN_PLACE);
v.add_qualif(ConstQualif::PREFER_IN_PLACE);
}
ast::ExprClosure(..) => {
@ -593,7 +595,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
if ty::with_freevars(v.tcx, e.id, |fv| !fv.is_empty()) {
assert!(v.mode == Mode::Var,
"global closures can't capture anything");
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
}
}
@ -631,7 +633,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
ast::ExprAssignOp(..) |
ast::ExprInlineAsm(_) |
ast::ExprMac(_) => {
v.add_qualif(NOT_CONST);
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0019,
"{} contains unimplemented expression type", v.msg());
@ -644,7 +646,7 @@ pub fn check_crate(tcx: &ty::ctxt) {
visit::walk_crate(&mut CheckCrateVisitor {
tcx: tcx,
mode: Mode::Var,
qualif: NOT_CONST,
qualif: ConstQualif::NOT_CONST,
rvalue_borrows: NodeMap()
}, tcx.map.krate());

View File

@ -838,20 +838,20 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
expr_ty: Ty<'tcx>)
-> cmt<'tcx> {
let qualif = self.tcx().const_qualif_map.borrow().get(&id).cloned()
.unwrap_or(check_const::NOT_CONST);
.unwrap_or(check_const::ConstQualif::NOT_CONST);
// Only promote `[T; 0]` before an RFC for rvalue promotions
// is accepted.
let qualif = match expr_ty.sty {
ty::ty_vec(_, Some(0)) => qualif,
_ => check_const::NOT_CONST
_ => check_const::ConstQualif::NOT_CONST
};
// Compute maximum lifetime of this rvalue. This is 'static if
// we can promote to a constant, otherwise equal to enclosing temp
// lifetime.
let re = match qualif & check_const::NON_STATIC_BORROWS {
check_const::PURE_CONST => ty::ReStatic,
let re = match qualif & check_const::ConstQualif::NON_STATIC_BORROWS {
check_const::ConstQualif::PURE_CONST => ty::ReStatic,
_ => self.temporary_scope(id),
};
let ret = self.cat_rvalue(id, span, re, expr_ty);

View File

@ -848,16 +848,18 @@ impl<'tcx> ctxt<'tcx> {
// recursing over the type itself.
bitflags! {
flags TypeFlags: u32 {
const NO_TYPE_FLAGS = 0b0,
const HAS_PARAMS = 0b1,
const HAS_SELF = 0b10,
const HAS_TY_INFER = 0b100,
const HAS_RE_INFER = 0b1000,
const HAS_RE_LATE_BOUND = 0b10000,
const HAS_REGIONS = 0b100000,
const HAS_TY_ERR = 0b1000000,
const HAS_PROJECTION = 0b10000000,
const NEEDS_SUBST = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
const NO_TYPE_FLAGS = 0,
const HAS_PARAMS = 1 << 0,
const HAS_SELF = 1 << 1,
const HAS_TY_INFER = 1 << 2,
const HAS_RE_INFER = 1 << 3,
const HAS_RE_LATE_BOUND = 1 << 4,
const HAS_REGIONS = 1 << 5,
const HAS_TY_ERR = 1 << 6,
const HAS_PROJECTION = 1 << 7,
const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits |
TypeFlags::HAS_SELF.bits |
TypeFlags::HAS_REGIONS.bits,
}
}
@ -890,8 +892,8 @@ macro_rules! sty_debug_print {
ty::ty_err => /* unimportant */ continue,
$(ty::$variant(..) => &mut $variant,)*
};
let region = t.flags.intersects(ty::HAS_RE_INFER);
let ty = t.flags.intersects(ty::HAS_TY_INFER);
let region = t.flags.intersects(ty::TypeFlags::HAS_RE_INFER);
let ty = t.flags.intersects(ty::TypeFlags::HAS_TY_INFER);
variant.total += 1;
total.total += 1;
@ -993,23 +995,23 @@ impl<'tcx> Borrow<sty<'tcx>> for InternedTy<'tcx> {
}
pub fn type_has_params(ty: Ty) -> bool {
ty.flags.intersects(HAS_PARAMS)
ty.flags.intersects(TypeFlags::HAS_PARAMS)
}
pub fn type_has_self(ty: Ty) -> bool {
ty.flags.intersects(HAS_SELF)
ty.flags.intersects(TypeFlags::HAS_SELF)
}
pub fn type_has_ty_infer(ty: Ty) -> bool {
ty.flags.intersects(HAS_TY_INFER)
ty.flags.intersects(TypeFlags::HAS_TY_INFER)
}
pub fn type_needs_infer(ty: Ty) -> bool {
ty.flags.intersects(HAS_TY_INFER | HAS_RE_INFER)
ty.flags.intersects(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
}
pub fn type_has_projection(ty: Ty) -> bool {
ty.flags.intersects(HAS_PROJECTION)
ty.flags.intersects(TypeFlags::HAS_PROJECTION)
}
pub fn type_has_late_bound_regions(ty: Ty) -> bool {
ty.flags.intersects(HAS_RE_LATE_BOUND)
ty.flags.intersects(TypeFlags::HAS_RE_LATE_BOUND)
}
/// An "escaping region" is a bound region whose binder is not part of `t`.
@ -2810,7 +2812,7 @@ struct FlagComputation {
impl FlagComputation {
fn new() -> FlagComputation {
FlagComputation { flags: NO_TYPE_FLAGS, depth: 0 }
FlagComputation { flags: TypeFlags::NO_TYPE_FLAGS, depth: 0 }
}
fn for_sty(st: &sty) -> FlagComputation {
@ -2855,20 +2857,20 @@ impl FlagComputation {
// You might think that we could just return ty_err for
// any type containing ty_err as a component, and get
// rid of the HAS_TY_ERR flag -- likewise for ty_bot (with
// rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
// the exception of function types that return bot).
// But doing so caused sporadic memory corruption, and
// neither I (tjc) nor nmatsakis could figure out why,
// so we're doing it this way.
&ty_err => {
self.add_flags(HAS_TY_ERR)
self.add_flags(TypeFlags::HAS_TY_ERR)
}
&ty_param(ref p) => {
if p.space == subst::SelfSpace {
self.add_flags(HAS_SELF);
self.add_flags(TypeFlags::HAS_SELF);
} else {
self.add_flags(HAS_PARAMS);
self.add_flags(TypeFlags::HAS_PARAMS);
}
}
@ -2877,7 +2879,7 @@ impl FlagComputation {
}
&ty_infer(_) => {
self.add_flags(HAS_TY_INFER)
self.add_flags(TypeFlags::HAS_TY_INFER)
}
&ty_enum(_, substs) | &ty_struct(_, substs) => {
@ -2885,7 +2887,7 @@ impl FlagComputation {
}
&ty_projection(ref data) => {
self.add_flags(HAS_PROJECTION);
self.add_flags(TypeFlags::HAS_PROJECTION);
self.add_projection_ty(data);
}
@ -2949,11 +2951,11 @@ impl FlagComputation {
}
fn add_region(&mut self, r: Region) {
self.add_flags(HAS_REGIONS);
self.add_flags(TypeFlags::HAS_REGIONS);
match r {
ty::ReInfer(_) => { self.add_flags(HAS_RE_INFER); }
ty::ReInfer(_) => { self.add_flags(TypeFlags::HAS_RE_INFER); }
ty::ReLateBound(debruijn, _) => {
self.add_flags(HAS_RE_LATE_BOUND);
self.add_flags(TypeFlags::HAS_RE_LATE_BOUND);
self.add_depth(debruijn.depth);
}
_ => { }
@ -3307,11 +3309,11 @@ pub fn type_is_nil(ty: Ty) -> bool {
}
pub fn type_is_error(ty: Ty) -> bool {
ty.flags.intersects(HAS_TY_ERR)
ty.flags.intersects(TypeFlags::HAS_TY_ERR)
}
pub fn type_needs_subst(ty: Ty) -> bool {
ty.flags.intersects(NEEDS_SUBST)
ty.flags.intersects(TypeFlags::NEEDS_SUBST)
}
pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {

View File

@ -12,6 +12,7 @@
// Do not remove on snapshot creation. Needed for bootstrap. (Issue #22364)
#![cfg_attr(stage0, feature(custom_attribute))]
#![crate_name = "rustc_bitflags"]
#![feature(associated_consts)]
#![feature(staged_api)]
#![staged_api]
#![crate_type = "rlib"]
@ -34,6 +35,7 @@
///
/// ```{.rust}
/// # #![feature(rustc_private)]
/// # #![feature(associated_consts)]
/// #[macro_use] extern crate rustc_bitflags;
///
/// bitflags! {
@ -41,19 +43,19 @@
/// const FLAG_A = 0b00000001,
/// const FLAG_B = 0b00000010,
/// const FLAG_C = 0b00000100,
/// const FLAG_ABC = FLAG_A.bits
/// | FLAG_B.bits
/// | FLAG_C.bits,
/// const FLAG_ABC = Flags::FLAG_A.bits
/// | Flags::FLAG_B.bits
/// | Flags::FLAG_C.bits,
/// }
/// }
///
/// fn main() {
/// let e1 = FLAG_A | FLAG_C;
/// let e2 = FLAG_B | FLAG_C;
/// assert!((e1 | e2) == FLAG_ABC); // union
/// assert!((e1 & e2) == FLAG_C); // intersection
/// assert!((e1 - e2) == FLAG_A); // set difference
/// assert!(!e2 == FLAG_A); // set complement
/// let e1 = Flags::FLAG_A | Flags::FLAG_C;
/// let e2 = Flags::FLAG_B | Flags::FLAG_C;
/// assert!((e1 | e2) == Flags::FLAG_ABC); // union
/// assert!((e1 & e2) == Flags::FLAG_C); // intersection
/// assert!((e1 - e2) == Flags::FLAG_A); // set difference
/// assert!(!e2 == Flags::FLAG_A); // set complement
/// }
/// ```
///
@ -86,7 +88,7 @@
/// }
///
/// fn main() {
/// let mut flags = FLAG_A | FLAG_B;
/// let mut flags = Flags::FLAG_A | Flags::FLAG_B;
/// flags.clear();
/// assert!(flags.is_empty());
/// assert_eq!(format!("{:?}", flags), "hi!");
@ -144,9 +146,9 @@ macro_rules! bitflags {
bits: $T,
}
$($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+
impl $BitFlags {
$($(#[$Flag_attr])* pub const $Flag: $BitFlags = $BitFlags { bits: $value };)+
/// Returns an empty set of flags.
#[inline]
pub fn empty() -> $BitFlags {
@ -314,9 +316,9 @@ mod tests {
#[doc = "* cmr bed"]
#[doc = "* strcat table"]
#[doc = "<strcat> wait what?"]
const FlagABC = FlagA.bits
| FlagB.bits
| FlagC.bits,
const FlagABC = Flags::FlagA.bits
| Flags::FlagB.bits
| Flags::FlagC.bits,
}
}
@ -329,32 +331,32 @@ mod tests {
#[test]
fn test_bits(){
assert_eq!(Flags::empty().bits(), 0b00000000);
assert_eq!(FlagA.bits(), 0b00000001);
assert_eq!(FlagABC.bits(), 0b00000111);
assert_eq!(Flags::FlagA.bits(), 0b00000001);
assert_eq!(Flags::FlagABC.bits(), 0b00000111);
assert_eq!(AnotherSetOfFlags::empty().bits(), 0b00);
assert_eq!(AnotherFlag.bits(), !0);
assert_eq!(AnotherSetOfFlags::AnotherFlag.bits(), !0);
}
#[test]
fn test_from_bits() {
assert!(Flags::from_bits(0) == Some(Flags::empty()));
assert!(Flags::from_bits(0b1) == Some(FlagA));
assert!(Flags::from_bits(0b10) == Some(FlagB));
assert!(Flags::from_bits(0b11) == Some(FlagA | FlagB));
assert!(Flags::from_bits(0b1) == Some(Flags::FlagA));
assert!(Flags::from_bits(0b10) == Some(Flags::FlagB));
assert!(Flags::from_bits(0b11) == Some(Flags::FlagA | Flags::FlagB));
assert!(Flags::from_bits(0b1000) == None);
assert!(AnotherSetOfFlags::from_bits(!0) == Some(AnotherFlag));
assert!(AnotherSetOfFlags::from_bits(!0) == Some(AnotherSetOfFlags::AnotherFlag));
}
#[test]
fn test_from_bits_truncate() {
assert!(Flags::from_bits_truncate(0) == Flags::empty());
assert!(Flags::from_bits_truncate(0b1) == FlagA);
assert!(Flags::from_bits_truncate(0b10) == FlagB);
assert!(Flags::from_bits_truncate(0b11) == (FlagA | FlagB));
assert!(Flags::from_bits_truncate(0b1) == Flags::FlagA);
assert!(Flags::from_bits_truncate(0b10) == Flags::FlagB);
assert!(Flags::from_bits_truncate(0b11) == (Flags::FlagA | Flags::FlagB));
assert!(Flags::from_bits_truncate(0b1000) == Flags::empty());
assert!(Flags::from_bits_truncate(0b1001) == FlagA);
assert!(Flags::from_bits_truncate(0b1001) == Flags::FlagA);
assert!(AnotherSetOfFlags::from_bits_truncate(0) == AnotherSetOfFlags::empty());
}
@ -362,19 +364,19 @@ mod tests {
#[test]
fn test_is_empty(){
assert!(Flags::empty().is_empty());
assert!(!FlagA.is_empty());
assert!(!FlagABC.is_empty());
assert!(!Flags::FlagA.is_empty());
assert!(!Flags::FlagABC.is_empty());
assert!(!AnotherFlag.is_empty());
assert!(!AnotherSetOfFlags::AnotherFlag.is_empty());
}
#[test]
fn test_is_all() {
assert!(Flags::all().is_all());
assert!(!FlagA.is_all());
assert!(FlagABC.is_all());
assert!(!Flags::FlagA.is_all());
assert!(Flags::FlagABC.is_all());
assert!(AnotherFlag.is_all());
assert!(AnotherSetOfFlags::AnotherFlag.is_all());
}
#[test]
@ -383,77 +385,77 @@ mod tests {
let e2 = Flags::empty();
assert!(!e1.intersects(e2));
assert!(AnotherFlag.intersects(AnotherFlag));
assert!(AnotherSetOfFlags::AnotherFlag.intersects(AnotherSetOfFlags::AnotherFlag));
}
#[test]
fn test_empty_does_not_intersect_with_full() {
let e1 = Flags::empty();
let e2 = FlagABC;
let e2 = Flags::FlagABC;
assert!(!e1.intersects(e2));
}
#[test]
fn test_disjoint_intersects() {
let e1 = FlagA;
let e2 = FlagB;
let e1 = Flags::FlagA;
let e2 = Flags::FlagB;
assert!(!e1.intersects(e2));
}
#[test]
fn test_overlapping_intersects() {
let e1 = FlagA;
let e2 = FlagA | FlagB;
let e1 = Flags::FlagA;
let e2 = Flags::FlagA | Flags::FlagB;
assert!(e1.intersects(e2));
}
#[test]
fn test_contains() {
let e1 = FlagA;
let e2 = FlagA | FlagB;
let e1 = Flags::FlagA;
let e2 = Flags::FlagA | Flags::FlagB;
assert!(!e1.contains(e2));
assert!(e2.contains(e1));
assert!(FlagABC.contains(e2));
assert!(Flags::FlagABC.contains(e2));
assert!(AnotherFlag.contains(AnotherFlag));
assert!(AnotherSetOfFlags::AnotherFlag.contains(AnotherSetOfFlags::AnotherFlag));
}
#[test]
fn test_insert(){
let mut e1 = FlagA;
let e2 = FlagA | FlagB;
let mut e1 = Flags::FlagA;
let e2 = Flags::FlagA | Flags::FlagB;
e1.insert(e2);
assert!(e1 == e2);
let mut e3 = AnotherSetOfFlags::empty();
e3.insert(AnotherFlag);
assert!(e3 == AnotherFlag);
e3.insert(AnotherSetOfFlags::AnotherFlag);
assert!(e3 == AnotherSetOfFlags::AnotherFlag);
}
#[test]
fn test_remove(){
let mut e1 = FlagA | FlagB;
let e2 = FlagA | FlagC;
let mut e1 = Flags::FlagA | Flags::FlagB;
let e2 = Flags::FlagA | Flags::FlagC;
e1.remove(e2);
assert!(e1 == FlagB);
assert!(e1 == Flags::FlagB);
let mut e3 = AnotherFlag;
e3.remove(AnotherFlag);
let mut e3 = AnotherSetOfFlags::AnotherFlag;
e3.remove(AnotherSetOfFlags::AnotherFlag);
assert!(e3 == AnotherSetOfFlags::empty());
}
#[test]
fn test_operators() {
let e1 = FlagA | FlagC;
let e2 = FlagB | FlagC;
assert!((e1 | e2) == FlagABC); // union
assert!((e1 & e2) == FlagC); // intersection
assert!((e1 - e2) == FlagA); // set difference
assert!(!e2 == FlagA); // set complement
assert!(e1 ^ e2 == FlagA | FlagB); // toggle
let e1 = Flags::FlagA | Flags::FlagC;
let e2 = Flags::FlagB | Flags::FlagC;
assert!((e1 | e2) == Flags::FlagABC); // union
assert!((e1 & e2) == Flags::FlagC); // intersection
assert!((e1 - e2) == Flags::FlagA); // set difference
assert!(!e2 == Flags::FlagA); // set complement
assert!(e1 ^ e2 == Flags::FlagA | Flags::FlagB); // toggle
let mut e3 = e1;
e3.toggle(e2);
assert!(e3 == FlagA | FlagB);
assert!(e3 == Flags::FlagA | Flags::FlagB);
let mut m4 = AnotherSetOfFlags::empty();
m4.toggle(AnotherSetOfFlags::empty());
@ -466,11 +468,11 @@ mod tests {
let mut b = Flags::empty();
assert!(!(a < b) && !(b < a));
b = FlagB;
b = Flags::FlagB;
assert!(a < b);
a = FlagC;
a = Flags::FlagC;
assert!(!(a < b) && b < a);
b = FlagC | FlagB;
b = Flags::FlagC | Flags::FlagB;
assert!(a < b);
}
@ -480,10 +482,10 @@ mod tests {
let mut b = Flags::empty();
assert!(a <= b && a >= b);
a = FlagA;
a = Flags::FlagA;
assert!(a > b && a >= b);
assert!(b < a && b <= a);
b = FlagB;
b = Flags::FlagB;
assert!(b > a && b >= a);
assert!(a < b && a <= b);
}
@ -494,7 +496,7 @@ mod tests {
let mut y = Flags::empty();
assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
x = Flags::all();
y = FlagABC;
y = Flags::FlagABC;
assert!(hash::hash::<Flags, SipHasher>(&x) == hash::hash::<Flags, SipHasher>(&y));
}
}

View File

@ -25,6 +25,7 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(associated_consts)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(libc)]
@ -124,32 +125,32 @@ pub enum DiagnosticSeverity {
bitflags! {
flags Attribute : u32 {
const ZExtAttribute = 1 << 0,
const SExtAttribute = 1 << 1,
const NoReturnAttribute = 1 << 2,
const InRegAttribute = 1 << 3,
const StructRetAttribute = 1 << 4,
const NoUnwindAttribute = 1 << 5,
const NoAliasAttribute = 1 << 6,
const ByValAttribute = 1 << 7,
const NestAttribute = 1 << 8,
const ReadNoneAttribute = 1 << 9,
const ReadOnlyAttribute = 1 << 10,
const NoInlineAttribute = 1 << 11,
const AlwaysInlineAttribute = 1 << 12,
const ZExtAttribute = 1 << 0,
const SExtAttribute = 1 << 1,
const NoReturnAttribute = 1 << 2,
const InRegAttribute = 1 << 3,
const StructRetAttribute = 1 << 4,
const NoUnwindAttribute = 1 << 5,
const NoAliasAttribute = 1 << 6,
const ByValAttribute = 1 << 7,
const NestAttribute = 1 << 8,
const ReadNoneAttribute = 1 << 9,
const ReadOnlyAttribute = 1 << 10,
const NoInlineAttribute = 1 << 11,
const AlwaysInlineAttribute = 1 << 12,
const OptimizeForSizeAttribute = 1 << 13,
const StackProtectAttribute = 1 << 14,
const StackProtectAttribute = 1 << 14,
const StackProtectReqAttribute = 1 << 15,
const AlignmentAttribute = 31 << 16,
const NoCaptureAttribute = 1 << 21,
const NoRedZoneAttribute = 1 << 22,
const AlignmentAttribute = 1 << 16,
const NoCaptureAttribute = 1 << 21,
const NoRedZoneAttribute = 1 << 22,
const NoImplicitFloatAttribute = 1 << 23,
const NakedAttribute = 1 << 24,
const InlineHintAttribute = 1 << 25,
const StackAttribute = 7 << 26,
const ReturnsTwiceAttribute = 1 << 29,
const UWTableAttribute = 1 << 30,
const NonLazyBindAttribute = 1 << 31,
const NakedAttribute = 1 << 24,
const InlineHintAttribute = 1 << 25,
const StackAttribute = 7 << 26,
const ReturnsTwiceAttribute = 1 << 29,
const UWTableAttribute = 1 << 30,
const NonLazyBindAttribute = 1 << 31,
}
}

View File

@ -13,7 +13,7 @@
//! Here we build the "reduced graph": the graph of the module tree without
//! any imports resolved.
use {DefModifiers, PUBLIC, IMPORTABLE};
use DefModifiers;
use resolve_imports::ImportDirective;
use resolve_imports::ImportDirectiveSubclass::{self, SingleImport, GlobImport};
use resolve_imports::ImportResolution;
@ -262,7 +262,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
let name = item.ident.name;
let sp = item.span;
let is_public = item.vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let modifiers = if is_public {
DefModifiers::PUBLIC
} else {
DefModifiers::empty()
} | DefModifiers::IMPORTABLE;
match item.node {
ItemUse(ref view_path) => {
@ -533,20 +537,20 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
ast::ConstTraitItem(..) => {
let def = DefAssociatedConst(local_def(trait_item.id),
FromTrait(local_def(item.id)));
// NB: not IMPORTABLE
name_bindings.define_value(def, trait_item.span, PUBLIC);
// NB: not DefModifiers::IMPORTABLE
name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
}
ast::MethodTraitItem(..) => {
let def = DefMethod(local_def(trait_item.id),
FromTrait(local_def(item.id)));
// NB: not IMPORTABLE
name_bindings.define_value(def, trait_item.span, PUBLIC);
// NB: not DefModifiers::IMPORTABLE
name_bindings.define_value(def, trait_item.span, DefModifiers::PUBLIC);
}
ast::TypeTraitItem(..) => {
let def = DefAssociatedTy(local_def(item.id),
local_def(trait_item.id));
// NB: not IMPORTABLE
name_bindings.define_type(def, trait_item.span, PUBLIC);
// NB: not DefModifiers::IMPORTABLE
name_bindings.define_type(def, trait_item.span, DefModifiers::PUBLIC);
}
}
@ -584,10 +588,10 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
// used
child.define_value(DefVariant(item_id,
local_def(variant.node.id), is_exported),
variant.span, PUBLIC | IMPORTABLE);
variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
child.define_type(DefVariant(item_id,
local_def(variant.node.id), is_exported),
variant.span, PUBLIC | IMPORTABLE);
variant.span, DefModifiers::PUBLIC | DefModifiers::IMPORTABLE);
}
/// Constructs the reduced graph for one foreign item.
@ -596,7 +600,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
parent: &Rc<Module>) {
let name = foreign_item.ident.name;
let is_public = foreign_item.vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let modifiers = if is_public {
DefModifiers::PUBLIC
} else {
DefModifiers::empty()
} | DefModifiers::IMPORTABLE;
let name_bindings =
self.add_child(name, parent, ForbidDuplicateValues,
foreign_item.span);
@ -644,7 +652,11 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
external crate) building external def {}, priv {:?}",
final_ident, vis);
let is_public = vis == ast::Public;
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let modifiers = if is_public {
DefModifiers::PUBLIC
} else {
DefModifiers::empty()
} | DefModifiers::IMPORTABLE;
let is_exported = is_public && match new_parent.def_id.get() {
None => true,
Some(did) => self.external_exports.contains(&did)
@ -695,7 +707,7 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
final_ident);
// variants are always treated as importable to allow them to be
// glob used
let modifiers = PUBLIC | IMPORTABLE;
let modifiers = DefModifiers::PUBLIC | DefModifiers::IMPORTABLE;
if is_struct {
child_name_bindings.define_type(def, DUMMY_SP, modifiers);
// Not adding fields for variants as they are not accessed with a self receiver
@ -715,11 +727,12 @@ impl<'a, 'b:'a, 'tcx:'b> GraphBuilder<'a, 'b, 'tcx> {
crate) building value (fn/static) {}", final_ident);
// impl methods have already been defined with the correct importability modifier
let mut modifiers = match *child_name_bindings.value_def.borrow() {
Some(ref def) => (modifiers & !IMPORTABLE) | (def.modifiers & IMPORTABLE),
Some(ref def) => (modifiers & !DefModifiers::IMPORTABLE) |
(def.modifiers & DefModifiers::IMPORTABLE),
None => modifiers
};
if new_parent.kind.get() != NormalModuleKind {
modifiers = modifiers & !IMPORTABLE;
modifiers = modifiers & !DefModifiers::IMPORTABLE;
}
child_name_bindings.define_value(def, DUMMY_SP, modifiers);
}

View File

@ -20,6 +20,7 @@
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(alloc)]
#![feature(associated_consts)]
#![feature(collections)]
#![feature(rustc_diagnostic_macros)]
#![feature(rustc_private)]
@ -477,8 +478,8 @@ impl fmt::Debug for Module {
bitflags! {
#[derive(Debug)]
flags DefModifiers: u8 {
const PUBLIC = 0b0000_0001,
const IMPORTABLE = 0b0000_0010,
const PUBLIC = 1 << 0,
const IMPORTABLE = 1 << 1,
}
}
@ -524,7 +525,11 @@ impl NameBindings {
is_public: bool,
sp: Span) {
// Merges the module with the existing type def or creates a new one.
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let modifiers = if is_public {
DefModifiers::PUBLIC
} else {
DefModifiers::empty()
} | DefModifiers::IMPORTABLE;
let module_ = Rc::new(Module::new(parent_link,
def_id,
kind,
@ -559,7 +564,11 @@ impl NameBindings {
external: bool,
is_public: bool,
_sp: Span) {
let modifiers = if is_public { PUBLIC } else { DefModifiers::empty() } | IMPORTABLE;
let modifiers = if is_public {
DefModifiers::PUBLIC
} else {
DefModifiers::empty()
} | DefModifiers::IMPORTABLE;
let type_def = self.type_def.borrow().clone();
match type_def {
None => {
@ -659,7 +668,7 @@ impl NameBindings {
}
fn defined_in_public_namespace(&self, namespace: Namespace) -> bool {
self.defined_in_namespace_with(namespace, PUBLIC)
self.defined_in_namespace_with(namespace, DefModifiers::PUBLIC)
}
fn defined_in_namespace_with(&self, namespace: Namespace, modifiers: DefModifiers) -> bool {
@ -730,11 +739,11 @@ impl NameBindings {
match namespace {
TypeNS => {
let type_def = self.type_def.borrow();
type_def.as_ref().unwrap().modifiers.contains(PUBLIC)
type_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC)
}
ValueNS => {
let value_def = self.value_def.borrow();
value_def.as_ref().unwrap().modifiers.contains(PUBLIC)
value_def.as_ref().unwrap().modifiers.contains(DefModifiers::PUBLIC)
}
}
}
@ -921,7 +930,7 @@ impl<'a, 'tcx> Resolver<'a, 'tcx> {
fn create_name_bindings_from_module(module: Rc<Module>) -> NameBindings {
NameBindings {
type_def: RefCell::new(Some(TypeNsDef {
modifiers: IMPORTABLE,
modifiers: DefModifiers::IMPORTABLE,
module_def: Some(module),
type_def: None,
type_span: None

View File

@ -10,7 +10,7 @@
use self::ImportDirectiveSubclass::*;
use {PUBLIC, IMPORTABLE};
use DefModifiers;
use Module;
use Namespace::{self, TypeNS, ValueNS};
use NameBindings;
@ -848,7 +848,9 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
// Merge the child item into the import resolution.
{
let mut merge_child_item = |namespace| {
if name_bindings.defined_in_namespace_with(namespace, IMPORTABLE | PUBLIC) {
let modifier = DefModifiers::IMPORTABLE | DefModifiers::PUBLIC;
if name_bindings.defined_in_namespace_with(namespace, modifier) {
let namespace_name = match namespace {
TypeNS => "type",
ValueNS => "value",
@ -914,7 +916,7 @@ impl<'a, 'b:'a, 'tcx:'b> ImportResolver<'a, 'b, 'tcx> {
import_span: Span,
name: Name,
namespace: Namespace) {
if !name_bindings.defined_in_namespace_with(namespace, IMPORTABLE) {
if !name_bindings.defined_in_namespace_with(namespace, DefModifiers::IMPORTABLE) {
let msg = format!("`{}` is not directly importable",
token::get_name(name));
span_err!(self.resolver.session, import_span, E0253, "{}", &msg[..]);

View File

@ -39,13 +39,13 @@ pub fn split_stack(val: ValueRef, set: bool) {
pub fn inline(val: ValueRef, inline: InlineAttr) {
use self::InlineAttr::*;
match inline {
Hint => llvm::SetFunctionAttribute(val, llvm::InlineHintAttribute),
Always => llvm::SetFunctionAttribute(val, llvm::AlwaysInlineAttribute),
Never => llvm::SetFunctionAttribute(val, llvm::NoInlineAttribute),
Hint => llvm::SetFunctionAttribute(val, llvm::Attribute::InlineHintAttribute),
Always => llvm::SetFunctionAttribute(val, llvm::Attribute::AlwaysInlineAttribute),
Never => llvm::SetFunctionAttribute(val, llvm::Attribute::NoInlineAttribute),
None => {
let attr = llvm::InlineHintAttribute |
llvm::AlwaysInlineAttribute |
llvm::NoInlineAttribute;
let attr = llvm::Attribute::InlineHintAttribute |
llvm::Attribute::AlwaysInlineAttribute |
llvm::Attribute::NoInlineAttribute;
unsafe {
llvm::LLVMRemoveFunctionAttr(val, attr.bits() as c_ulonglong)
}
@ -57,10 +57,13 @@ pub fn inline(val: ValueRef, inline: InlineAttr) {
#[inline]
pub fn emit_uwtable(val: ValueRef, emit: bool) {
if emit {
llvm::SetFunctionAttribute(val, llvm::UWTableAttribute);
llvm::SetFunctionAttribute(val, llvm::Attribute::UWTableAttribute);
} else {
unsafe {
llvm::LLVMRemoveFunctionAttr(val, llvm::UWTableAttribute.bits() as c_ulonglong);
llvm::LLVMRemoveFunctionAttr(
val,
llvm::Attribute::UWTableAttribute.bits() as c_ulonglong,
);
}
}
}
@ -71,10 +74,13 @@ pub fn emit_uwtable(val: ValueRef, emit: bool) {
pub fn unwind(val: ValueRef, can_unwind: bool) {
if can_unwind {
unsafe {
llvm::LLVMRemoveFunctionAttr(val, llvm::NoUnwindAttribute.bits() as c_ulonglong);
llvm::LLVMRemoveFunctionAttr(
val,
llvm::Attribute::NoUnwindAttribute.bits() as c_ulonglong,
);
}
} else {
llvm::SetFunctionAttribute(val, llvm::NoUnwindAttribute);
llvm::SetFunctionAttribute(val, llvm::Attribute::NoUnwindAttribute);
}
}
@ -83,10 +89,13 @@ pub fn unwind(val: ValueRef, can_unwind: bool) {
#[allow(dead_code)] // possibly useful function
pub fn set_optimize_for_size(val: ValueRef, optimize: bool) {
if optimize {
llvm::SetFunctionAttribute(val, llvm::OptimizeForSizeAttribute);
llvm::SetFunctionAttribute(val, llvm::Attribute::OptimizeForSizeAttribute);
} else {
unsafe {
llvm::LLVMRemoveFunctionAttr(val, llvm::OptimizeForSizeAttribute.bits() as c_ulonglong);
llvm::LLVMRemoveFunctionAttr(
val,
llvm::Attribute::OptimizeForSizeAttribute.bits() as c_ulonglong,
);
}
}
}
@ -107,7 +116,7 @@ pub fn from_fn_attrs(ccx: &CrateContext, attrs: &[ast::Attribute], llfn: ValueRe
llvm::ColdAttribute as u64)
}
} else if attr.check_name("allocator") {
llvm::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
llvm::Attribute::NoAliasAttribute.apply_llfn(llvm::ReturnIndex as c_uint, llfn);
}
}
}
@ -176,9 +185,9 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
// The outptr can be noalias and nocapture because it's entirely
// invisible to the program. We also know it's nonnull as well
// as how many bytes we can dereference
attrs.arg(1, llvm::StructRetAttribute)
.arg(1, llvm::NoAliasAttribute)
.arg(1, llvm::NoCaptureAttribute)
attrs.arg(1, llvm::Attribute::StructRetAttribute)
.arg(1, llvm::Attribute::NoAliasAttribute)
.arg(1, llvm::Attribute::NoCaptureAttribute)
.arg(1, llvm::DereferenceableAttribute(llret_sz));
// Add one more since there's an outptr
@ -190,7 +199,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
// `~` pointer return values never alias because ownership
// is transferred
ty::ty_uniq(it) if common::type_is_sized(ccx.tcx(), it) => {
attrs.ret(llvm::NoAliasAttribute);
attrs.ret(llvm::Attribute::NoAliasAttribute);
}
_ => {}
}
@ -207,7 +216,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
}
if let ty::ty_bool = ret_ty.sty {
attrs.ret(llvm::ZExtAttribute);
attrs.ret(llvm::Attribute::ZExtAttribute);
}
}
}
@ -221,20 +230,20 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
// For non-immediate arguments the callee gets its own copy of
// the value on the stack, so there are no aliases. It's also
// program-invisible so can't possibly capture
attrs.arg(idx, llvm::NoAliasAttribute)
.arg(idx, llvm::NoCaptureAttribute)
attrs.arg(idx, llvm::Attribute::NoAliasAttribute)
.arg(idx, llvm::Attribute::NoCaptureAttribute)
.arg(idx, llvm::DereferenceableAttribute(llarg_sz));
}
ty::ty_bool => {
attrs.arg(idx, llvm::ZExtAttribute);
attrs.arg(idx, llvm::Attribute::ZExtAttribute);
}
// `~` pointer parameters never alias because ownership is transferred
ty::ty_uniq(inner) => {
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, inner));
attrs.arg(idx, llvm::NoAliasAttribute)
attrs.arg(idx, llvm::Attribute::NoAliasAttribute)
.arg(idx, llvm::DereferenceableAttribute(llsz));
}
@ -247,15 +256,15 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
!ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe() => {
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
attrs.arg(idx, llvm::NoAliasAttribute)
attrs.arg(idx, llvm::Attribute::NoAliasAttribute)
.arg(idx, llvm::DereferenceableAttribute(llsz));
if mt.mutbl == ast::MutImmutable {
attrs.arg(idx, llvm::ReadOnlyAttribute);
attrs.arg(idx, llvm::Attribute::ReadOnlyAttribute);
}
if let ReLateBound(_, BrAnon(_)) = *b {
attrs.arg(idx, llvm::NoCaptureAttribute);
attrs.arg(idx, llvm::Attribute::NoCaptureAttribute);
}
}
@ -263,7 +272,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
// reference to escape this function (returned or stored beyond the call by a closure).
ty::ty_rptr(&ReLateBound(_, BrAnon(_)), mt) => {
let llsz = machine::llsize_of_real(ccx, type_of::type_of(ccx, mt.ty));
attrs.arg(idx, llvm::NoCaptureAttribute)
attrs.arg(idx, llvm::Attribute::NoCaptureAttribute)
.arg(idx, llvm::DereferenceableAttribute(llsz));
}

View File

@ -10,8 +10,7 @@
#![allow(non_upper_case_globals)]
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
use llvm::{StructRetAttribute, ZExtAttribute};
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
use trans::cabi::{FnType, ArgType};
use trans::context::CrateContext;
use trans::type_::Type;
@ -164,7 +163,7 @@ fn is_homogenous_aggregate_ty(ty: Type) -> Option<(Type, u64)> {
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ty) {
@ -186,12 +185,12 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
};
return ArgType::direct(ty, Some(llty), None, None);
}
ArgType::indirect(ty, Some(StructRetAttribute))
ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
}
fn classify_arg_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
if let Some((base_ty, members)) = is_homogenous_aggregate_ty(ty) {

View File

@ -10,8 +10,7 @@
#![allow(non_upper_case_globals)]
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
use llvm::{StructRetAttribute, ZExtAttribute};
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
use trans::cabi::{FnType, ArgType};
use trans::context::CrateContext;
use trans::type_::Type;
@ -132,7 +131,7 @@ fn ty_size(ty: Type, align_fn: TyAlignFn) -> usize {
fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
let size = ty_size(ty, align_fn);
@ -146,12 +145,12 @@ fn classify_ret_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType
};
return ArgType::direct(ty, Some(llty), None, None);
}
ArgType::indirect(ty, Some(StructRetAttribute))
ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
}
fn classify_arg_ty(ccx: &CrateContext, ty: Type, align_fn: TyAlignFn) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
return ArgType::direct(ty, None, None, attr);
}
let align = align_fn(ty);

View File

@ -13,8 +13,7 @@
use libc::c_uint;
use std::cmp;
use llvm;
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector};
use llvm::{StructRetAttribute, ZExtAttribute};
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Vector, Attribute};
use trans::cabi::{ArgType, FnType};
use trans::context::CrateContext;
use trans::type_::Type;
@ -89,10 +88,10 @@ fn ty_size(ty: Type) -> usize {
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::indirect(ty, Some(StructRetAttribute))
ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
}
}
@ -106,7 +105,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType
*offset += align_up_to(size, align * 8) / 8;
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::direct(

View File

@ -10,8 +10,7 @@
use libc::c_uint;
use llvm;
use llvm::{Integer, Pointer, Float, Double, Struct, Array};
use llvm::{StructRetAttribute, ZExtAttribute};
use llvm::{Integer, Pointer, Float, Double, Struct, Array, Attribute};
use trans::cabi::{FnType, ArgType};
use trans::context::CrateContext;
use trans::type_::Type;
@ -85,10 +84,10 @@ fn ty_size(ty: Type) -> usize {
fn classify_ret_ty(ccx: &CrateContext, ty: Type) -> ArgType {
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::indirect(ty, Some(StructRetAttribute))
ArgType::indirect(ty, Some(Attribute::StructRetAttribute))
}
}
@ -102,7 +101,7 @@ fn classify_arg_ty(ccx: &CrateContext, ty: Type, offset: &mut usize) -> ArgType
*offset += align_up_to(size, align * 8) / 8;
if is_reg_ty(ty) {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
} else {
ArgType::direct(

View File

@ -52,11 +52,11 @@ pub fn compute_abi_info(ccx: &CrateContext,
ret_ty = ArgType::direct(rty, Some(t), None, None);
}
RetPointer => {
ret_ty = ArgType::indirect(rty, Some(StructRetAttribute));
ret_ty = ArgType::indirect(rty, Some(Attribute::StructRetAttribute));
}
}
} else {
let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ret_ty = ArgType::direct(rty, None, None, attr);
}
@ -67,11 +67,11 @@ pub fn compute_abi_info(ccx: &CrateContext,
if size == 0 {
ArgType::ignore(t)
} else {
ArgType::indirect(t, Some(ByValAttribute))
ArgType::indirect(t, Some(Attribute::ByValAttribute))
}
}
_ => {
let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if t == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(t, None, None, attr)
}
};

View File

@ -16,7 +16,6 @@ use self::RegClass::*;
use llvm::{Integer, Pointer, Float, Double};
use llvm::{Struct, Array, Attribute, Vector};
use llvm::{StructRetAttribute, ByValAttribute, ZExtAttribute};
use trans::cabi::{ArgType, FnType};
use trans::context::CrateContext;
use trans::type_::Type;
@ -407,19 +406,19 @@ pub fn compute_abi_info(ccx: &CrateContext,
None)
}
} else {
let attr = if ty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if ty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(ty, None, None, attr)
}
}
let mut arg_tys = Vec::new();
for t in atys {
let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), ByValAttribute);
let ty = x86_64_ty(ccx, *t, |cls| cls.is_pass_byval(), Attribute::ByValAttribute);
arg_tys.push(ty);
}
let ret_ty = if ret_def {
x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), StructRetAttribute)
x86_64_ty(ccx, rty, |cls| cls.is_ret_bysret(), Attribute::StructRetAttribute)
} else {
ArgType::direct(Type::void(ccx), None, None, None)
};

View File

@ -31,10 +31,10 @@ pub fn compute_abi_info(ccx: &CrateContext,
2 => ArgType::direct(rty, Some(Type::i16(ccx)), None, None),
4 => ArgType::direct(rty, Some(Type::i32(ccx)), None, None),
8 => ArgType::direct(rty, Some(Type::i64(ccx)), None, None),
_ => ArgType::indirect(rty, Some(StructRetAttribute))
_ => ArgType::indirect(rty, Some(Attribute::StructRetAttribute))
};
} else {
let attr = if rty == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if rty == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ret_ty = ArgType::direct(rty, None, None, attr);
}
@ -46,11 +46,11 @@ pub fn compute_abi_info(ccx: &CrateContext,
2 => ArgType::direct(rty, Some(Type::i16(ccx)), None, None),
4 => ArgType::direct(rty, Some(Type::i32(ccx)), None, None),
8 => ArgType::direct(rty, Some(Type::i64(ccx)), None, None),
_ => ArgType::indirect(t, Some(ByValAttribute))
_ => ArgType::indirect(t, Some(Attribute::ByValAttribute))
}
}
_ => {
let attr = if t == Type::i1(ccx) { Some(ZExtAttribute) } else { None };
let attr = if t == Type::i1(ccx) { Some(Attribute::ZExtAttribute) } else { None };
ArgType::direct(t, None, None, attr)
}
};

View File

@ -186,7 +186,7 @@ fn get_const_val(ccx: &CrateContext,
ref_expr: &ast::Expr) -> ValueRef {
let expr = get_const_expr(ccx, def_id, ref_expr);
let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
get_const_expr_as_global(ccx, expr, check_const::PURE_CONST, empty_substs)
get_const_expr_as_global(ccx, expr, check_const::ConstQualif::PURE_CONST, empty_substs)
}
pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@ -215,7 +215,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
Some(&val) => return val,
None => {}
}
let val = if qualif.intersects(check_const::NON_STATIC_BORROWS) {
let val = if qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS) {
// Avoid autorefs as they would create global instead of stack
// references, even when only the latter are correct.
let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,

View File

@ -71,12 +71,12 @@ pub fn declare_fn(ccx: &CrateContext, name: &str, callconv: llvm::CallConv, ty:
llvm::SetUnnamedAddr(llfn, true);
if output == ty::FnDiverging {
llvm::SetFunctionAttribute(llfn, llvm::NoReturnAttribute);
llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoReturnAttribute);
}
if ccx.tcx().sess.opts.cg.no_redzone
.unwrap_or(ccx.tcx().sess.target.target.options.disable_redzone) {
llvm::SetFunctionAttribute(llfn, llvm::NoRedZoneAttribute)
llvm::SetFunctionAttribute(llfn, llvm::Attribute::NoRedZoneAttribute)
}
if ccx.is_split_stack_supported() && !ccx.sess().opts.cg.no_stack_check {

View File

@ -126,8 +126,11 @@ pub fn trans_into<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
}
let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) {
if !qualif.intersects(check_const::PREFER_IN_PLACE) {
if !qualif.intersects(
check_const::ConstQualif::NOT_CONST |
check_const::ConstQualif::NEEDS_DROP
) {
if !qualif.intersects(check_const::ConstQualif::PREFER_IN_PLACE) {
if let SaveIn(lldest) = dest {
let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
bcx.fcx.param_substs);
@ -209,12 +212,15 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let mut bcx = bcx;
let fcx = bcx.fcx;
let qualif = *bcx.tcx().const_qualif_map.borrow().get(&expr.id).unwrap();
let adjusted_global = !qualif.intersects(check_const::NON_STATIC_BORROWS);
let global = if !qualif.intersects(check_const::NOT_CONST | check_const::NEEDS_DROP) {
let adjusted_global = !qualif.intersects(check_const::ConstQualif::NON_STATIC_BORROWS);
let global = if !qualif.intersects(
check_const::ConstQualif::NOT_CONST |
check_const::ConstQualif::NEEDS_DROP
) {
let global = consts::get_const_expr_as_global(bcx.ccx(), expr, qualif,
bcx.fcx.param_substs);
if qualif.intersects(check_const::HAS_STATIC_BORROWS) {
if qualif.intersects(check_const::ConstQualif::HAS_STATIC_BORROWS) {
// Is borrowed as 'static, must return lvalue.
// Cast pointer to global, because constants have different types.

View File

@ -349,8 +349,8 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// The outptr can be noalias and nocapture because it's entirely
// invisible to the program. We also know it's nonnull as well
// as how many bytes we can dereference
attrs.arg(1, llvm::NoAliasAttribute)
.arg(1, llvm::NoCaptureAttribute)
attrs.arg(1, llvm::Attribute::NoAliasAttribute)
.arg(1, llvm::Attribute::NoCaptureAttribute)
.arg(1, llvm::DereferenceableAttribute(llret_sz));
};

View File

@ -107,26 +107,27 @@
#![doc(test(attr(allow(dead_code, deprecated, unused_variables, unused_mut))))]
#![feature(alloc)]
#![feature(allow_internal_unstable)]
#![feature(associated_consts)]
#![feature(box_syntax)]
#![feature(collections)]
#![feature(core)]
#![feature(debug_builders)]
#![feature(into_cow)]
#![feature(lang_items)]
#![feature(libc)]
#![feature(linkage, thread_local, asm)]
#![feature(macro_reexport)]
#![feature(optin_builtin_traits)]
#![feature(rand)]
#![feature(slice_patterns)]
#![feature(staged_api)]
#![feature(std_misc)]
#![feature(str_char)]
#![feature(unboxed_closures)]
#![feature(unicode)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(macro_reexport)]
#![feature(unique)]
#![feature(allow_internal_unstable)]
#![feature(str_char)]
#![feature(into_cow)]
#![feature(std_misc)]
#![feature(slice_patterns)]
#![feature(debug_builders)]
#![feature(unsafe_no_drop_flag, filling_drop)]
#![feature(zero_one)]
#![cfg_attr(test, feature(float_from_str_radix))]
#![cfg_attr(test, feature(test, rustc_private, std_misc))]
@ -307,13 +308,12 @@ mod std {
pub use sync; // used for select!()
pub use error; // used for try!()
pub use fmt; // used for any formatting strings
pub use option; // used for bitflags!{}
pub use option; // used for thread_local!{}
pub use rt; // used for panic!()
pub use vec; // used for vec![]
pub use cell; // used for tls!
pub use thread; // used for thread_local!
pub use marker; // used for tls!
pub use ops; // used for bitflags!
// The test runner calls ::std::env::args() but really wants realstd
#[cfg(test)] pub use realstd::env as env;

View File

@ -25,13 +25,14 @@
html_favicon_url = "http://www.rust-lang.org/favicon.ico",
html_root_url = "http://doc.rust-lang.org/nightly/")]
#![feature(associated_consts)]
#![feature(collections)]
#![feature(core)]
#![feature(libc)]
#![feature(rustc_private)]
#![feature(staged_api)]
#![feature(unicode)]
#![feature(str_char)]
#![feature(unicode)]
extern crate arena;
extern crate fmt_macros;

View File

@ -88,9 +88,9 @@ use std::slice;
bitflags! {
flags Restrictions: u8 {
const UNRESTRICTED = 0b0000,
const RESTRICTION_STMT_EXPR = 0b0001,
const RESTRICTION_NO_STRUCT_LITERAL = 0b0010,
const UNRESTRICTED = 0,
const RESTRICTION_STMT_EXPR = 1 << 0,
const RESTRICTION_NO_STRUCT_LITERAL = 1 << 1,
}
}
@ -339,7 +339,7 @@ impl<'a> Parser<'a> {
buffer_start: 0,
buffer_end: 0,
tokens_consumed: 0,
restrictions: UNRESTRICTED,
restrictions: Restrictions::UNRESTRICTED,
quote_depth: 0,
obsolete_set: HashSet::new(),
mod_path_stack: Vec::new(),
@ -2198,7 +2198,10 @@ impl<'a> Parser<'a> {
if self.check(&token::OpenDelim(token::Brace)) {
// This is a struct literal, unless we're prohibited
// from parsing struct literals here.
if !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL) {
let prohibited = self.restrictions.contains(
Restrictions::RESTRICTION_NO_STRUCT_LITERAL
);
if !prohibited {
// It's a struct literal.
try!(self.bump());
let mut fields = Vec::new();
@ -2759,7 +2762,7 @@ impl<'a> Parser<'a> {
}
pub fn parse_assign_expr_with(&mut self, lhs: P<Expr>) -> PResult<P<Expr>> {
let restrictions = self.restrictions & RESTRICTION_NO_STRUCT_LITERAL;
let restrictions = self.restrictions & Restrictions::RESTRICTION_NO_STRUCT_LITERAL;
let op_span = self.span;
match self.token {
token::Eq => {
@ -2814,7 +2817,7 @@ impl<'a> Parser<'a> {
if self.token.can_begin_expr() {
// parse `for i in 1.. { }` as infinite loop, not as `for i in (1..{})`.
if self.token == token::OpenDelim(token::Brace) {
return !self.restrictions.contains(RESTRICTION_NO_STRUCT_LITERAL);
return !self.restrictions.contains(Restrictions::RESTRICTION_NO_STRUCT_LITERAL);
}
true
} else {
@ -2828,7 +2831,7 @@ impl<'a> Parser<'a> {
return self.parse_if_let_expr();
}
let lo = self.last_span.lo;
let cond = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let thn = try!(self.parse_block());
let mut els: Option<P<Expr>> = None;
let mut hi = thn.span.hi;
@ -2846,7 +2849,7 @@ impl<'a> Parser<'a> {
try!(self.expect_keyword(keywords::Let));
let pat = try!(self.parse_pat_nopanic());
try!(self.expect(&token::Eq));
let expr = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let thn = try!(self.parse_block());
let (hi, els) = if try!(self.eat_keyword(keywords::Else) ){
let expr = try!(self.parse_else_expr());
@ -2905,7 +2908,7 @@ impl<'a> Parser<'a> {
let lo = self.last_span.lo;
let pat = try!(self.parse_pat_nopanic());
try!(self.expect_keyword(keywords::In));
let expr = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let loop_block = try!(self.parse_block());
let hi = self.last_span.hi;
@ -2918,7 +2921,7 @@ impl<'a> Parser<'a> {
return self.parse_while_let_expr(opt_ident);
}
let lo = self.last_span.lo;
let cond = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
let cond = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let body = try!(self.parse_block());
let hi = body.span.hi;
return Ok(self.mk_expr(lo, hi, ExprWhile(cond, body, opt_ident)));
@ -2930,7 +2933,7 @@ impl<'a> Parser<'a> {
try!(self.expect_keyword(keywords::Let));
let pat = try!(self.parse_pat_nopanic());
try!(self.expect(&token::Eq));
let expr = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
let body = try!(self.parse_block());
let hi = body.span.hi;
return Ok(self.mk_expr(lo, hi, ExprWhileLet(pat, expr, body, opt_ident)));
@ -2945,7 +2948,7 @@ impl<'a> Parser<'a> {
fn parse_match_expr(&mut self) -> PResult<P<Expr>> {
let lo = self.last_span.lo;
let discriminant = try!(self.parse_expr_res(RESTRICTION_NO_STRUCT_LITERAL));
let discriminant = try!(self.parse_expr_res(Restrictions::RESTRICTION_NO_STRUCT_LITERAL));
try!(self.commit_expr_expecting(&*discriminant, token::OpenDelim(token::Brace)));
let mut arms: Vec<Arm> = Vec::new();
while self.token != token::CloseDelim(token::Brace) {
@ -2966,7 +2969,7 @@ impl<'a> Parser<'a> {
guard = Some(try!(self.parse_expr_nopanic()));
}
try!(self.expect(&token::FatArrow));
let expr = try!(self.parse_expr_res(RESTRICTION_STMT_EXPR));
let expr = try!(self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR));
let require_comma =
!classify::expr_is_simple_block(&*expr)
@ -2988,7 +2991,7 @@ impl<'a> Parser<'a> {
/// Parse an expression
pub fn parse_expr_nopanic(&mut self) -> PResult<P<Expr>> {
return self.parse_expr_res(UNRESTRICTED);
return self.parse_expr_res(Restrictions::UNRESTRICTED);
}
/// Parse an expression, subject to the given restrictions
@ -3564,7 +3567,7 @@ impl<'a> Parser<'a> {
}
// Remainder are line-expr stmts.
let e = try!(self.parse_expr_res(RESTRICTION_STMT_EXPR));
let e = try!(self.parse_expr_res(Restrictions::RESTRICTION_STMT_EXPR));
spanned(lo, e.span.hi, StmtExpr(e, ast::DUMMY_NODE_ID))
}
}
@ -3573,7 +3576,7 @@ impl<'a> Parser<'a> {
/// Is this expression a successfully-parsed statement?
fn expr_is_complete(&mut self, e: &Expr) -> bool {
self.restrictions.contains(RESTRICTION_STMT_EXPR) &&
self.restrictions.contains(Restrictions::RESTRICTION_STMT_EXPR) &&
!classify::expr_requires_semi_to_be_stmt(e)
}