Skip to content

Commit

Permalink
Auto merge of #24333 - arielb1:implement-rfc401, r=nrc
Browse files Browse the repository at this point in the history
  • Loading branch information
bors committed May 19, 2015
2 parents f34ff7a + e7e1fd2 commit c322dbb
Show file tree
Hide file tree
Showing 42 changed files with 1,071 additions and 484 deletions.
8 changes: 6 additions & 2 deletions src/liballoc/arc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -394,7 +394,9 @@ impl<T: ?Sized> Drop for Arc<T> {
// it's run more than once)
let ptr = *self._ptr;
// if ptr.is_null() { return }
if ptr as usize == 0 || ptr as usize == mem::POST_DROP_USIZE { return }
if ptr as *mut u8 as usize == 0 || ptr as *mut u8 as usize == mem::POST_DROP_USIZE {
return
}

// Because `fetch_sub` is already atomic, we do not need to synchronize
// with other threads unless we are going to delete the object. This
Expand Down Expand Up @@ -524,7 +526,9 @@ impl<T: ?Sized> Drop for Weak<T> {
let ptr = *self._ptr;

// see comments above for why this check is here
if ptr as usize == 0 || ptr as usize == mem::POST_DROP_USIZE { return }
if ptr as *mut u8 as usize == 0 || ptr as *mut u8 as usize == mem::POST_DROP_USIZE {
return
}

// If we find out that we were the last weak pointer, then its time to
// deallocate the data entirely. See the discussion in Arc::drop() about
Expand Down
4 changes: 2 additions & 2 deletions src/liballoc/rc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,7 +543,7 @@ impl<T: ?Sized> Drop for Rc<T> {
unsafe {
let ptr = *self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() &&
ptr as usize != mem::POST_DROP_USIZE {
ptr as *const () as usize != mem::POST_DROP_USIZE {
self.dec_strong();
if self.strong() == 0 {
// destroy the contained object
Expand Down Expand Up @@ -1051,7 +1051,7 @@ impl<T: ?Sized> Drop for Weak<T> {
unsafe {
let ptr = *self._ptr;
if !(*(&ptr as *const _ as *const *const ())).is_null() &&
ptr as usize != mem::POST_DROP_USIZE {
ptr as *const () as usize != mem::POST_DROP_USIZE {
self.dec_weak();
// the weak count starts at 1, and will only go to zero if all
// the strong pointers have disappeared.
Expand Down
1 change: 0 additions & 1 deletion src/librustc/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -801,7 +801,6 @@ struct Foo<T: 'static> {

register_diagnostics! {
E0011,
E0012,
E0014,
E0016,
E0017,
Expand Down
1 change: 1 addition & 0 deletions src/librustc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@ pub mod back {
pub mod middle {
pub mod astconv_util;
pub mod astencode;
pub mod cast;
pub mod cfg;
pub mod check_const;
pub mod check_static_recursion;
Expand Down
1 change: 1 addition & 0 deletions src/librustc/metadata/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ enum_from_u32! {
tag_table_capture_modes = 0x67,
tag_table_object_cast_map = 0x68,
tag_table_const_qualif = 0x69,
tag_table_cast_kinds = 0x6a,
}
}

Expand Down
25 changes: 25 additions & 0 deletions src/librustc/middle/astencode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ use metadata::tydecode;
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter};
use metadata::tydecode::{RegionParameter, ClosureSource};
use metadata::tyencode;
use middle::cast;
use middle::check_const::ConstQualif;
use middle::mem_categorization::Typer;
use middle::privacy::{AllPublic, LastMod};
Expand Down Expand Up @@ -688,6 +689,10 @@ pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
kind.encode(ebml_w).unwrap();
}

pub fn encode_cast_kind(ebml_w: &mut Encoder, kind: cast::CastKind) {
kind.encode(ebml_w).unwrap();
}

pub trait vtable_decoder_helpers<'tcx> {
fn read_vec_per_param_space<T, F>(&mut self, f: F) -> VecPerParamSpace<T> where
F: FnMut(&mut Self) -> T;
Expand Down Expand Up @@ -1248,6 +1253,13 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
})
}

if let Some(cast_kind) = tcx.cast_kinds.borrow().get(&id) {
rbml_w.tag(c::tag_table_cast_kinds, |rbml_w| {
rbml_w.id(id);
encode_cast_kind(rbml_w, *cast_kind)
})
}

for &qualif in tcx.const_qualif_map.borrow().get(&id).iter() {
rbml_w.tag(c::tag_table_const_qualif, |rbml_w| {
rbml_w.id(id);
Expand Down Expand Up @@ -1289,6 +1301,8 @@ trait rbml_decoder_decoder_helpers<'tcx> {
-> subst::Substs<'tcx>;
fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::AutoAdjustment<'tcx>;
fn read_cast_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> cast::CastKind;
fn read_closure_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
-> ty::ClosureKind;
fn read_closure_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
Expand Down Expand Up @@ -1641,6 +1655,12 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
}).unwrap()
}

fn read_cast_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
-> cast::CastKind
{
Decodable::decode(self).unwrap()
}

fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
-> ty::ClosureKind
{
Expand Down Expand Up @@ -1801,6 +1821,11 @@ fn decode_side_tables(dcx: &DecodeContext,
dcx.tcx.closure_kinds.borrow_mut().insert(ast_util::local_def(id),
closure_kind);
}
c::tag_table_cast_kinds => {
let cast_kind =
val_dsr.read_cast_kind(dcx);
dcx.tcx.cast_kinds.borrow_mut().insert(id, cast_kind);
}
c::tag_table_const_qualif => {
let qualif: ConstQualif = Decodable::decode(val_dsr).unwrap();
dcx.tcx.const_qualif_map.borrow_mut().insert(id, qualif);
Expand Down
77 changes: 77 additions & 0 deletions src/librustc/middle/cast.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.

// Helpers for handling cast expressions, used in both
// typeck and trans.

use middle::ty::{self, Ty};

use syntax::ast;

/// Types that are represented as ints.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum IntTy {
U(ast::UintTy),
I,
CEnum,
Bool,
Char
}

// Valid types for the result of a non-coercion cast
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum CastTy<'tcx> {
/// Various types that are represented as ints and handled mostly
/// in the same way, merged for easier matching.
Int(IntTy),
/// Floating-Point types
Float,
/// Function Pointers
FnPtr,
/// Raw pointers
Ptr(&'tcx ty::mt<'tcx>),
/// References
RPtr(&'tcx ty::mt<'tcx>),
}

/// Cast Kind. See RFC 401 (or librustc_typeck/check/cast.rs)
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum CastKind {
CoercionCast,
PtrPtrCast,
PtrAddrCast,
AddrPtrCast,
NumericCast,
EnumCast,
PrimIntCast,
U8CharCast,
ArrayPtrCast,
FnPtrPtrCast,
FnPtrAddrCast
}

impl<'tcx> CastTy<'tcx> {
pub fn from_ty(tcx: &ty::ctxt<'tcx>, t: Ty<'tcx>)
-> Option<CastTy<'tcx>> {
match t.sty {
ty::ty_bool => Some(CastTy::Int(IntTy::Bool)),
ty::ty_char => Some(CastTy::Int(IntTy::Char)),
ty::ty_int(_) => Some(CastTy::Int(IntTy::I)),
ty::ty_uint(u) => Some(CastTy::Int(IntTy::U(u))),
ty::ty_float(_) => Some(CastTy::Float),
ty::ty_enum(..) if ty::type_is_c_like_enum(
tcx, t) => Some(CastTy::Int(IntTy::CEnum)),
ty::ty_ptr(ref mt) => Some(CastTy::Ptr(mt)),
ty::ty_rptr(_, ref mt) => Some(CastTy::RPtr(mt)),
ty::ty_bare_fn(..) => Some(CastTy::FnPtr),
_ => None,
}
}
}
35 changes: 13 additions & 22 deletions src/librustc/middle/check_const.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// - It's not possible to take the address of a static item with unsafe interior. This is enforced
// by borrowck::gather_loans

use middle::cast::{CastKind};
use middle::const_eval;
use middle::def;
use middle::expr_use_visitor as euv;
Expand All @@ -32,11 +33,10 @@ use middle::mem_categorization as mc;
use middle::traits;
use middle::ty::{self, Ty};
use util::nodemap::NodeMap;
use util::ppaux;
use util::ppaux::Repr;

use syntax::ast;
use syntax::codemap::Span;
use syntax::print::pprust;
use syntax::visit::{self, Visitor};

use std::collections::hash_map::Entry;
Expand Down Expand Up @@ -197,7 +197,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {

impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
fn visit_item(&mut self, i: &ast::Item) {
debug!("visit_item(item={})", pprust::item_to_string(i));
debug!("visit_item(item={})", i.repr(self.tcx));
match i.node {
ast::ItemStatic(_, ast::MutImmutable, ref expr) => {
self.check_static_type(&**expr);
Expand Down Expand Up @@ -440,26 +440,17 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
}
}
ast::ExprCast(ref from, _) => {
let toty = ty::expr_ty(v.tcx, e);
let fromty = ty::expr_ty(v.tcx, &**from);
let is_legal_cast =
ty::type_is_numeric(toty) ||
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(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0012,
"can not cast to `{}` in {}s",
ppaux::ty_to_string(v.tcx, toty), v.msg());
}
}
if ty::type_is_unsafe_ptr(fromty) && ty::type_is_numeric(toty) {
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());
debug!("Checking const cast(id={})", from.id);
match v.tcx.cast_kinds.borrow().get(&from.id) {
None => v.tcx.sess.span_bug(e.span, "no kind for cast"),
Some(&CastKind::PtrAddrCast) | Some(&CastKind::FnPtrAddrCast) => {
v.add_qualif(ConstQualif::NOT_CONST);
if v.mode != Mode::Var {
span_err!(v.tcx.sess, e.span, E0018,
"can't cast a pointer to an integer in {}s", v.msg());
}
}
_ => {}
}
}
ast::ExprPath(..) => {
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/const_eval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1002,7 +1002,7 @@ fn cast_const<'tcx>(tcx: &ty::ctxt<'tcx>, val: const_val, ty: Ty) -> CastResult
macro_rules! convert_val {
($intermediate_ty:ty, $const_type:ident, $target_ty:ty) => {
match val {
const_bool(b) => Ok($const_type(b as $intermediate_ty as $target_ty)),
const_bool(b) => Ok($const_type(b as u64 as $intermediate_ty as $target_ty)),
const_uint(u) => Ok($const_type(u as $intermediate_ty as $target_ty)),
const_int(i) => Ok($const_type(i as $intermediate_ty as $target_ty)),
const_float(f) => Ok($const_type(f as $intermediate_ty as $target_ty)),
Expand Down
24 changes: 15 additions & 9 deletions src/librustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ use session::Session;
use lint;
use metadata::csearch;
use middle;
use middle::cast;
use middle::check_const;
use middle::const_eval;
use middle::def::{self, DefMap, ExportMap};
Expand Down Expand Up @@ -288,15 +289,6 @@ pub struct field_ty {
pub origin: ast::DefId, // The DefId of the struct in which the field is declared.
}

// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct creader_cache_key {
pub cnum: CrateNum,
pub pos: usize,
pub len: usize
}

#[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)]
pub struct ItemVariances {
pub types: VecPerParamSpace<Variance>,
Expand Down Expand Up @@ -562,6 +554,15 @@ pub enum vtable_origin<'tcx> {
// expr to the associated trait ref.
pub type ObjectCastMap<'tcx> = RefCell<NodeMap<ty::PolyTraitRef<'tcx>>>;

// Contains information needed to resolve types and (in the future) look up
// the types of AST nodes.
#[derive(Copy, Clone, PartialEq, Eq, Hash)]
pub struct creader_cache_key {
pub cnum: CrateNum,
pub pos: usize,
pub len: usize
}

/// A restriction that certain types must be the same size. The use of
/// `transmute` gives rise to these restrictions. These generally
/// cannot be checked until trans; therefore, each call to `transmute`
Expand Down Expand Up @@ -827,6 +828,10 @@ pub struct ctxt<'tcx> {

/// Caches CoerceUnsized kinds for impls on custom types.
pub custom_coerce_unsized_kinds: RefCell<DefIdMap<CustomCoerceUnsized>>,

/// Maps a cast expression to its kind. This is keyed on the
/// *from* expression of the cast, not the cast itself.
pub cast_kinds: RefCell<NodeMap<cast::CastKind>>,
}

impl<'tcx> ctxt<'tcx> {
Expand Down Expand Up @@ -2817,6 +2822,7 @@ pub fn mk_ctxt<'tcx>(s: Session,
type_impls_sized_cache: RefCell::new(HashMap::new()),
const_qualif_map: RefCell::new(NodeMap()),
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
cast_kinds: RefCell::new(NodeMap()),
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_lint/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ impl LintPass for TypeLimits {
let (min, max) = int_ty_range(int_type);
let negative = self.negated_expr_id == e.id;

if (negative && v > (min.abs() as u64)) ||
if (negative && v > min.wrapping_neg() as u64) ||
(!negative && v > (max.abs() as u64)) {
cx.span_lint(OVERFLOWING_LITERALS, e.span,
&*format!("literal out of range for {:?}", t));
Expand Down
Loading

0 comments on commit c322dbb

Please sign in to comment.