Skip to content

Commit

Permalink
Auto merge of #22838 - petrochenkov:bytelit, r=alexcrichton
Browse files Browse the repository at this point in the history
This patch changes the type of byte string literals from `&[u8]` to `&[u8; N]`.
It also implements some necessary traits (`IntoBytes`, `Seek`, `Read`, `BufRead`) for fixed-size arrays (also related to #21725) and adds test for #17233, which seems to be resolved.

Fixes #18465
[breaking-change]
  • Loading branch information
bors committed Mar 17, 2015
2 parents bfac337 + a7e1c1d commit 4f63ae2
Show file tree
Hide file tree
Showing 20 changed files with 274 additions and 189 deletions.
24 changes: 24 additions & 0 deletions src/libcore/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,34 @@ use marker::{Copy, Sized};
use option::Option;
use slice::{Iter, IterMut, SliceExt};

/// Utility trait implemented only on arrays of fixed size
///
/// This trait can be used to implement other traits on fixed-size arrays
/// without causing much metadata bloat.
#[unstable(feature = "core")]
pub trait FixedSizeArray<T> {
/// Converts the array to immutable slice
fn as_slice(&self) -> &[T];
/// Converts the array to mutable slice
fn as_mut_slice(&mut self) -> &mut [T];
}

// macro for implementing n-ary tuple functions and operations
macro_rules! array_impls {
($($N:expr)+) => {
$(
#[unstable(feature = "core")]
impl<T> FixedSizeArray<T> for [T; $N] {
#[inline]
fn as_slice(&self) -> &[T] {
&self[..]
}
#[inline]
fn as_mut_slice(&mut self) -> &mut [T] {
&mut self[..]
}
}

#[stable(feature = "rust1", since = "1.0.0")]
impl<T:Copy> Clone for [T; $N] {
fn clone(&self) -> [T; $N] {
Expand Down
2 changes: 1 addition & 1 deletion src/libcore/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ pub mod default;
/* Core types and methods on primitives */

pub mod any;
pub mod array;
pub mod atomic;
pub mod cell;
pub mod char;
Expand All @@ -151,7 +152,6 @@ mod bool {

// note: does not need to be public
mod tuple;
mod array;

#[doc(hidden)]
mod core {
Expand Down
3 changes: 2 additions & 1 deletion src/libcore/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -448,7 +448,8 @@ impl<T, E> Result<T, E> {
/// ```
/// use std::old_io::IoResult;
///
/// let mut buffer = &mut b"1\n2\n3\n4\n";
/// let mut buffer: &[u8] = b"1\n2\n3\n4\n";
/// let mut buffer = &mut buffer;
///
/// let mut sum = 0;
///
Expand Down
33 changes: 25 additions & 8 deletions src/librustc_trans/trans/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ use middle::mem_categorization as mc;
use middle::pat_util::*;
use trans::adt;
use trans::base::*;
use trans::build::{AddCase, And, BitCast, Br, CondBr, GEPi, InBoundsGEP, Load};
use trans::build::{AddCase, And, Br, CondBr, GEPi, InBoundsGEP, Load, PointerCast};
use trans::build::{Not, Store, Sub, add_comment};
use trans::build;
use trans::callee;
Expand Down Expand Up @@ -853,14 +853,31 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
ty::ty_str => compare_str(cx, lhs, rhs, rhs_t, debug_loc),
ty::ty_vec(ty, _) => match ty.sty {
ty::ty_uint(ast::TyU8) => {
// NOTE: cast &[u8] to &str and abuse the str_eq lang item,
// NOTE: cast &[u8] and &[u8; N] to &str and abuse the str_eq lang item,
// which calls memcmp().
let t = ty::mk_str_slice(cx.tcx(),
cx.tcx().mk_region(ty::ReStatic),
ast::MutImmutable);
let lhs = BitCast(cx, lhs, type_of::type_of(cx.ccx(), t).ptr_to());
let rhs = BitCast(cx, rhs, type_of::type_of(cx.ccx(), t).ptr_to());
compare_str(cx, lhs, rhs, rhs_t, debug_loc)
let pat_len = val_ty(rhs).element_type().array_length();
let ty_str_slice = ty::mk_str_slice(cx.tcx(),
cx.tcx().mk_region(ty::ReStatic),
ast::MutImmutable);

let rhs_str = alloc_ty(cx, ty_str_slice, "rhs_str");
Store(cx, GEPi(cx, rhs, &[0, 0]), expr::get_dataptr(cx, rhs_str));
Store(cx, C_uint(cx.ccx(), pat_len), expr::get_len(cx, rhs_str));

let lhs_str;
if val_ty(lhs) == val_ty(rhs) {
// Both the discriminant and the pattern are thin pointers
lhs_str = alloc_ty(cx, ty_str_slice, "lhs_str");
Store(cx, GEPi(cx, lhs, &[0, 0]), expr::get_dataptr(cx, lhs_str));
Store(cx, C_uint(cx.ccx(), pat_len), expr::get_len(cx, lhs_str));
}
else {
// The discriminant is a fat pointer
let llty_str_slice = type_of::type_of(cx.ccx(), ty_str_slice).ptr_to();
lhs_str = PointerCast(cx, lhs, llty_str_slice);
}

compare_str(cx, lhs_str, rhs_str, rhs_t, debug_loc)
},
_ => cx.sess().bug("only byte strings supported in compare_values"),
},
Expand Down
9 changes: 1 addition & 8 deletions src/librustc_trans/trans/consts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,14 +75,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
ast::LitBool(b) => C_bool(cx, b),
ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
ast::LitBinary(ref data) => {
let g = addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id);
let base = ptrcast(g, Type::i8p(cx));
let prev_const = cx.const_unsized().borrow_mut()
.insert(base, g);
assert!(prev_const.is_none() || prev_const == Some(g));
assert_eq!(abi::FAT_PTR_ADDR, 0);
assert_eq!(abi::FAT_PTR_EXTRA, 1);
C_struct(cx, &[base, C_uint(cx, data.len())], false)
addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id)
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/trans/debuginfo.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4054,7 +4054,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
if needs_gdb_debug_scripts_section(ccx) {
let empty = CString::new(b"").unwrap();
let empty = CString::new("").unwrap();
let gdb_debug_scripts_section_global =
get_or_insert_gdb_debug_scripts_section_global(ccx);
unsafe {
Expand Down
20 changes: 18 additions & 2 deletions src/librustc_typeck/check/_match.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,23 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
ast::PatLit(ref lt) => {
check_expr(fcx, &**lt);
let expr_ty = fcx.expr_ty(&**lt);
fcx.write_ty(pat.id, expr_ty);

// Byte string patterns behave the same way as array patterns
// They can denote both statically and dynamically sized byte arrays
let mut pat_ty = expr_ty;
if let ast::ExprLit(ref lt) = lt.node {
if let ast::LitBinary(_) = lt.node {
let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
if let ty::ty_rptr(_, mt) = expected_ty.sty {
if let ty::ty_vec(_, None) = mt.ty.sty {
pat_ty = ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic),
ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
}
}
}
}

fcx.write_ty(pat.id, pat_ty);

// somewhat surprising: in this case, the subtyping
// relation goes the opposite way as the other
Expand All @@ -62,7 +78,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
// &'static str <: expected
//
// that's equivalent to there existing a LUB.
demand::suptype(fcx, pat.span, expected, expr_ty);
demand::suptype(fcx, pat.span, expected, pat_ty);
}
ast::PatRange(ref begin, ref end) => {
check_expr(fcx, &**begin);
Expand Down
9 changes: 5 additions & 4 deletions src/librustc_typeck/check/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2505,10 +2505,11 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,

match lit.node {
ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
ast::LitBinary(..) => {
ty::mk_slice(tcx,
tcx.mk_region(ty::ReStatic),
ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
ast::LitBinary(ref v) => {
ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
mutbl: ast::MutImmutable,
})
}
ast::LitByte(_) => tcx.types.u8,
ast::LitChar(_) => tcx.types.char,
Expand Down
8 changes: 4 additions & 4 deletions src/libstd/ffi/c_str.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use vec::Vec;
/// fn my_printer(s: *const libc::c_char);
/// }
///
/// let to_print = b"Hello, world!";
/// let to_print = &b"Hello, world!"[..];
/// let c_to_print = CString::new(to_print).unwrap();
/// unsafe {
/// my_printer(c_to_print.as_ptr());
Expand Down Expand Up @@ -469,14 +469,14 @@ mod tests {

#[test]
fn simple() {
let s = CString::new(b"1234").unwrap();
let s = CString::new("1234").unwrap();
assert_eq!(s.as_bytes(), b"1234");
assert_eq!(s.as_bytes_with_nul(), b"1234\0");
}

#[test]
fn build_with_zero1() {
assert!(CString::new(b"\0").is_err());
assert!(CString::new(&b"\0"[..]).is_err());
}
#[test]
fn build_with_zero2() {
Expand All @@ -493,7 +493,7 @@ mod tests {

#[test]
fn formatted() {
let s = CString::new(b"12").unwrap();
let s = CString::new(&b"12"[..]).unwrap();
assert_eq!(format!("{:?}", s), "\"12\"");
}

Expand Down
4 changes: 2 additions & 2 deletions src/libstd/io/buffered.rs
Original file line number Diff line number Diff line change
Expand Up @@ -622,7 +622,7 @@ mod tests {

#[test]
fn test_read_line() {
let in_buf = b"a\nb\nc";
let in_buf: &[u8] = b"a\nb\nc";
let mut reader = BufReader::with_capacity(2, in_buf);
let mut s = String::new();
reader.read_line(&mut s).unwrap();
Expand All @@ -640,7 +640,7 @@ mod tests {

#[test]
fn test_lines() {
let in_buf = b"a\nb\nc";
let in_buf: &[u8] = b"a\nb\nc";
let reader = BufReader::with_capacity(2, in_buf);
let mut it = reader.lines();
assert_eq!(it.next(), Some(Ok("a".to_string())));
Expand Down
4 changes: 2 additions & 2 deletions src/libstd/io/cursor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ mod tests {

#[test]
fn test_read_char() {
let b = b"Vi\xE1\xBB\x87t";
let b = &b"Vi\xE1\xBB\x87t"[..];
let mut c = Cursor::new(b).chars();
assert_eq!(c.next(), Some(Ok('V')));
assert_eq!(c.next(), Some(Ok('i')));
Expand All @@ -339,7 +339,7 @@ mod tests {

#[test]
fn test_read_bad_char() {
let b = b"\x80";
let b = &b"\x80"[..];
let mut c = Cursor::new(b).chars();
assert!(c.next().unwrap().is_err());
}
Expand Down
26 changes: 13 additions & 13 deletions src/libstd/io/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -933,12 +933,12 @@ mod tests {

#[test]
fn read_until() {
let mut buf = Cursor::new(b"12");
let mut buf = Cursor::new(&b"12"[..]);
let mut v = Vec::new();
assert_eq!(buf.read_until(b'3', &mut v), Ok(2));
assert_eq!(v, b"12");

let mut buf = Cursor::new(b"1233");
let mut buf = Cursor::new(&b"1233"[..]);
let mut v = Vec::new();
assert_eq!(buf.read_until(b'3', &mut v), Ok(3));
assert_eq!(v, b"123");
Expand All @@ -952,12 +952,12 @@ mod tests {

#[test]
fn split() {
let buf = Cursor::new(b"12");
let buf = Cursor::new(&b"12"[..]);
let mut s = buf.split(b'3');
assert_eq!(s.next(), Some(Ok(vec![b'1', b'2'])));
assert_eq!(s.next(), None);

let buf = Cursor::new(b"1233");
let buf = Cursor::new(&b"1233"[..]);
let mut s = buf.split(b'3');
assert_eq!(s.next(), Some(Ok(vec![b'1', b'2'])));
assert_eq!(s.next(), Some(Ok(vec![])));
Expand All @@ -966,12 +966,12 @@ mod tests {

#[test]
fn read_line() {
let mut buf = Cursor::new(b"12");
let mut buf = Cursor::new(&b"12"[..]);
let mut v = String::new();
assert_eq!(buf.read_line(&mut v), Ok(2));
assert_eq!(v, "12");

let mut buf = Cursor::new(b"12\n\n");
let mut buf = Cursor::new(&b"12\n\n"[..]);
let mut v = String::new();
assert_eq!(buf.read_line(&mut v), Ok(3));
assert_eq!(v, "12\n");
Expand All @@ -985,12 +985,12 @@ mod tests {

#[test]
fn lines() {
let buf = Cursor::new(b"12");
let buf = Cursor::new(&b"12"[..]);
let mut s = buf.lines();
assert_eq!(s.next(), Some(Ok("12".to_string())));
assert_eq!(s.next(), None);

let buf = Cursor::new(b"12\n\n");
let buf = Cursor::new(&b"12\n\n"[..]);
let mut s = buf.lines();
assert_eq!(s.next(), Some(Ok("12".to_string())));
assert_eq!(s.next(), Some(Ok(String::new())));
Expand All @@ -999,30 +999,30 @@ mod tests {

#[test]
fn read_to_end() {
let mut c = Cursor::new(b"");
let mut c = Cursor::new(&b""[..]);
let mut v = Vec::new();
assert_eq!(c.read_to_end(&mut v), Ok(0));
assert_eq!(v, []);

let mut c = Cursor::new(b"1");
let mut c = Cursor::new(&b"1"[..]);
let mut v = Vec::new();
assert_eq!(c.read_to_end(&mut v), Ok(1));
assert_eq!(v, b"1");
}

#[test]
fn read_to_string() {
let mut c = Cursor::new(b"");
let mut c = Cursor::new(&b""[..]);
let mut v = String::new();
assert_eq!(c.read_to_string(&mut v), Ok(0));
assert_eq!(v, "");

let mut c = Cursor::new(b"1");
let mut c = Cursor::new(&b"1"[..]);
let mut v = String::new();
assert_eq!(c.read_to_string(&mut v), Ok(1));
assert_eq!(v, "1");

let mut c = Cursor::new(b"\xff");
let mut c = Cursor::new(&b"\xff"[..]);
let mut v = String::new();
assert!(c.read_to_string(&mut v).is_err());
}
Expand Down
3 changes: 2 additions & 1 deletion src/libstd/old_io/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -445,7 +445,8 @@ mod test {

#[test]
fn limit_reader_buffer() {
let r = &mut b"0123456789\n0123456789\n";
let mut r: &[u8] = b"0123456789\n0123456789\n";
let r = &mut r;
{
let mut r = LimitReader::new(r.by_ref(), 3);
assert_eq!(r.read_line(), Ok("012".to_string()));
Expand Down
6 changes: 3 additions & 3 deletions src/libstd/old_path/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
/// # #[cfg(windows)] fn foo() {}
/// # #[cfg(unix)] fn foo() {
/// let p = Path::new("abc/def/ghi");
/// assert_eq!(p.filename(), Some(b"ghi"));
/// assert_eq!(p.filename(), Some(&b"ghi"[..]));
/// # }
/// ```
fn filename<'a>(&'a self) -> Option<&'a [u8]>;
Expand Down Expand Up @@ -345,7 +345,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
/// # #[cfg(windows)] fn foo() {}
/// # #[cfg(unix)] fn foo() {
/// let p = Path::new("/abc/def.txt");
/// assert_eq!(p.filestem(), Some(b"def"));
/// assert_eq!(p.filestem(), Some(&b"def"[..]));
/// # }
/// ```
fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
Expand Down Expand Up @@ -392,7 +392,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
/// # #[cfg(windows)] fn foo() {}
/// # #[cfg(unix)] fn foo() {
/// let p = Path::new("abc/def.txt");
/// assert_eq!(p.extension(), Some(b"txt"));
/// assert_eq!(p.extension(), Some(&b"txt"[..]));
/// # }
/// ```
fn extension<'a>(&'a self) -> Option<&'a [u8]> {
Expand Down
Loading

0 comments on commit 4f63ae2

Please sign in to comment.