mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-23 07:14:28 +00:00
rollup merge of #24921: tamird/bitflags-associated-const
Conflicts: src/librustc/lib.rs
This commit is contained in:
commit
2edb6438cb
@ -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)]
|
||||
|
@ -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());
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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 {
|
||||
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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[..]);
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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(
|
||||
|
@ -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(
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
@ -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)
|
||||
};
|
||||
|
@ -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)
|
||||
}
|
||||
};
|
||||
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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.
|
||||
|
@ -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));
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user