Skip to content

Commit 4f63ae2

Browse files
committed
Auto merge of #22838 - petrochenkov:bytelit, r=alexcrichton
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]
2 parents bfac337 + a7e1c1d commit 4f63ae2

File tree

20 files changed

+274
-189
lines changed

20 files changed

+274
-189
lines changed

src/libcore/array.rs

+24
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,34 @@ use marker::{Copy, Sized};
2323
use option::Option;
2424
use slice::{Iter, IterMut, SliceExt};
2525

26+
/// Utility trait implemented only on arrays of fixed size
27+
///
28+
/// This trait can be used to implement other traits on fixed-size arrays
29+
/// without causing much metadata bloat.
30+
#[unstable(feature = "core")]
31+
pub trait FixedSizeArray<T> {
32+
/// Converts the array to immutable slice
33+
fn as_slice(&self) -> &[T];
34+
/// Converts the array to mutable slice
35+
fn as_mut_slice(&mut self) -> &mut [T];
36+
}
37+
2638
// macro for implementing n-ary tuple functions and operations
2739
macro_rules! array_impls {
2840
($($N:expr)+) => {
2941
$(
42+
#[unstable(feature = "core")]
43+
impl<T> FixedSizeArray<T> for [T; $N] {
44+
#[inline]
45+
fn as_slice(&self) -> &[T] {
46+
&self[..]
47+
}
48+
#[inline]
49+
fn as_mut_slice(&mut self) -> &mut [T] {
50+
&mut self[..]
51+
}
52+
}
53+
3054
#[stable(feature = "rust1", since = "1.0.0")]
3155
impl<T:Copy> Clone for [T; $N] {
3256
fn clone(&self) -> [T; $N] {

src/libcore/lib.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,7 @@ pub mod default;
129129
/* Core types and methods on primitives */
130130

131131
pub mod any;
132+
pub mod array;
132133
pub mod atomic;
133134
pub mod cell;
134135
pub mod char;
@@ -151,7 +152,6 @@ mod bool {
151152

152153
// note: does not need to be public
153154
mod tuple;
154-
mod array;
155155

156156
#[doc(hidden)]
157157
mod core {

src/libcore/result.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,8 @@ impl<T, E> Result<T, E> {
448448
/// ```
449449
/// use std::old_io::IoResult;
450450
///
451-
/// let mut buffer = &mut b"1\n2\n3\n4\n";
451+
/// let mut buffer: &[u8] = b"1\n2\n3\n4\n";
452+
/// let mut buffer = &mut buffer;
452453
///
453454
/// let mut sum = 0;
454455
///

src/librustc_trans/trans/_match.rs

+25-8
Original file line numberDiff line numberDiff line change
@@ -200,7 +200,7 @@ use middle::mem_categorization as mc;
200200
use middle::pat_util::*;
201201
use trans::adt;
202202
use trans::base::*;
203-
use trans::build::{AddCase, And, BitCast, Br, CondBr, GEPi, InBoundsGEP, Load};
203+
use trans::build::{AddCase, And, Br, CondBr, GEPi, InBoundsGEP, Load, PointerCast};
204204
use trans::build::{Not, Store, Sub, add_comment};
205205
use trans::build;
206206
use trans::callee;
@@ -853,14 +853,31 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
853853
ty::ty_str => compare_str(cx, lhs, rhs, rhs_t, debug_loc),
854854
ty::ty_vec(ty, _) => match ty.sty {
855855
ty::ty_uint(ast::TyU8) => {
856-
// NOTE: cast &[u8] to &str and abuse the str_eq lang item,
856+
// NOTE: cast &[u8] and &[u8; N] to &str and abuse the str_eq lang item,
857857
// which calls memcmp().
858-
let t = ty::mk_str_slice(cx.tcx(),
859-
cx.tcx().mk_region(ty::ReStatic),
860-
ast::MutImmutable);
861-
let lhs = BitCast(cx, lhs, type_of::type_of(cx.ccx(), t).ptr_to());
862-
let rhs = BitCast(cx, rhs, type_of::type_of(cx.ccx(), t).ptr_to());
863-
compare_str(cx, lhs, rhs, rhs_t, debug_loc)
858+
let pat_len = val_ty(rhs).element_type().array_length();
859+
let ty_str_slice = ty::mk_str_slice(cx.tcx(),
860+
cx.tcx().mk_region(ty::ReStatic),
861+
ast::MutImmutable);
862+
863+
let rhs_str = alloc_ty(cx, ty_str_slice, "rhs_str");
864+
Store(cx, GEPi(cx, rhs, &[0, 0]), expr::get_dataptr(cx, rhs_str));
865+
Store(cx, C_uint(cx.ccx(), pat_len), expr::get_len(cx, rhs_str));
866+
867+
let lhs_str;
868+
if val_ty(lhs) == val_ty(rhs) {
869+
// Both the discriminant and the pattern are thin pointers
870+
lhs_str = alloc_ty(cx, ty_str_slice, "lhs_str");
871+
Store(cx, GEPi(cx, lhs, &[0, 0]), expr::get_dataptr(cx, lhs_str));
872+
Store(cx, C_uint(cx.ccx(), pat_len), expr::get_len(cx, lhs_str));
873+
}
874+
else {
875+
// The discriminant is a fat pointer
876+
let llty_str_slice = type_of::type_of(cx.ccx(), ty_str_slice).ptr_to();
877+
lhs_str = PointerCast(cx, lhs, llty_str_slice);
878+
}
879+
880+
compare_str(cx, lhs_str, rhs_str, rhs_t, debug_loc)
864881
},
865882
_ => cx.sess().bug("only byte strings supported in compare_values"),
866883
},

src/librustc_trans/trans/consts.rs

+1-8
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
7575
ast::LitBool(b) => C_bool(cx, b),
7676
ast::LitStr(ref s, _) => C_str_slice(cx, (*s).clone()),
7777
ast::LitBinary(ref data) => {
78-
let g = addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id);
79-
let base = ptrcast(g, Type::i8p(cx));
80-
let prev_const = cx.const_unsized().borrow_mut()
81-
.insert(base, g);
82-
assert!(prev_const.is_none() || prev_const == Some(g));
83-
assert_eq!(abi::FAT_PTR_ADDR, 0);
84-
assert_eq!(abi::FAT_PTR_EXTRA, 1);
85-
C_struct(cx, &[base, C_uint(cx, data.len())], false)
78+
addr_of(cx, C_bytes(cx, &data[..]), "binary", e.id)
8679
}
8780
}
8881
}

src/librustc_trans/trans/debuginfo.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -4054,7 +4054,7 @@ fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTree
40544054
/// .debug_gdb_scripts global is referenced, so it isn't removed by the linker.
40554055
pub fn insert_reference_to_gdb_debug_scripts_section_global(ccx: &CrateContext) {
40564056
if needs_gdb_debug_scripts_section(ccx) {
4057-
let empty = CString::new(b"").unwrap();
4057+
let empty = CString::new("").unwrap();
40584058
let gdb_debug_scripts_section_global =
40594059
get_or_insert_gdb_debug_scripts_section_global(ccx);
40604060
unsafe {

src/librustc_typeck/check/_match.rs

+18-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,23 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
4848
ast::PatLit(ref lt) => {
4949
check_expr(fcx, &**lt);
5050
let expr_ty = fcx.expr_ty(&**lt);
51-
fcx.write_ty(pat.id, expr_ty);
51+
52+
// Byte string patterns behave the same way as array patterns
53+
// They can denote both statically and dynamically sized byte arrays
54+
let mut pat_ty = expr_ty;
55+
if let ast::ExprLit(ref lt) = lt.node {
56+
if let ast::LitBinary(_) = lt.node {
57+
let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
58+
if let ty::ty_rptr(_, mt) = expected_ty.sty {
59+
if let ty::ty_vec(_, None) = mt.ty.sty {
60+
pat_ty = ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic),
61+
ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
62+
}
63+
}
64+
}
65+
}
66+
67+
fcx.write_ty(pat.id, pat_ty);
5268

5369
// somewhat surprising: in this case, the subtyping
5470
// relation goes the opposite way as the other
@@ -62,7 +78,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
6278
// &'static str <: expected
6379
//
6480
// that's equivalent to there existing a LUB.
65-
demand::suptype(fcx, pat.span, expected, expr_ty);
81+
demand::suptype(fcx, pat.span, expected, pat_ty);
6682
}
6783
ast::PatRange(ref begin, ref end) => {
6884
check_expr(fcx, &**begin);

src/librustc_typeck/check/mod.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -2505,10 +2505,11 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
25052505

25062506
match lit.node {
25072507
ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
2508-
ast::LitBinary(..) => {
2509-
ty::mk_slice(tcx,
2510-
tcx.mk_region(ty::ReStatic),
2511-
ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
2508+
ast::LitBinary(ref v) => {
2509+
ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
2510+
ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
2511+
mutbl: ast::MutImmutable,
2512+
})
25122513
}
25132514
ast::LitByte(_) => tcx.types.u8,
25142515
ast::LitChar(_) => tcx.types.char,

src/libstd/ffi/c_str.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ use vec::Vec;
5858
/// fn my_printer(s: *const libc::c_char);
5959
/// }
6060
///
61-
/// let to_print = b"Hello, world!";
61+
/// let to_print = &b"Hello, world!"[..];
6262
/// let c_to_print = CString::new(to_print).unwrap();
6363
/// unsafe {
6464
/// my_printer(c_to_print.as_ptr());
@@ -469,14 +469,14 @@ mod tests {
469469

470470
#[test]
471471
fn simple() {
472-
let s = CString::new(b"1234").unwrap();
472+
let s = CString::new("1234").unwrap();
473473
assert_eq!(s.as_bytes(), b"1234");
474474
assert_eq!(s.as_bytes_with_nul(), b"1234\0");
475475
}
476476

477477
#[test]
478478
fn build_with_zero1() {
479-
assert!(CString::new(b"\0").is_err());
479+
assert!(CString::new(&b"\0"[..]).is_err());
480480
}
481481
#[test]
482482
fn build_with_zero2() {
@@ -493,7 +493,7 @@ mod tests {
493493

494494
#[test]
495495
fn formatted() {
496-
let s = CString::new(b"12").unwrap();
496+
let s = CString::new(&b"12"[..]).unwrap();
497497
assert_eq!(format!("{:?}", s), "\"12\"");
498498
}
499499

src/libstd/io/buffered.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -622,7 +622,7 @@ mod tests {
622622

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

641641
#[test]
642642
fn test_lines() {
643-
let in_buf = b"a\nb\nc";
643+
let in_buf: &[u8] = b"a\nb\nc";
644644
let reader = BufReader::with_capacity(2, in_buf);
645645
let mut it = reader.lines();
646646
assert_eq!(it.next(), Some(Ok("a".to_string())));

src/libstd/io/cursor.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ mod tests {
328328

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

340340
#[test]
341341
fn test_read_bad_char() {
342-
let b = b"\x80";
342+
let b = &b"\x80"[..];
343343
let mut c = Cursor::new(b).chars();
344344
assert!(c.next().unwrap().is_err());
345345
}

src/libstd/io/mod.rs

+13-13
Original file line numberDiff line numberDiff line change
@@ -933,12 +933,12 @@ mod tests {
933933

934934
#[test]
935935
fn read_until() {
936-
let mut buf = Cursor::new(b"12");
936+
let mut buf = Cursor::new(&b"12"[..]);
937937
let mut v = Vec::new();
938938
assert_eq!(buf.read_until(b'3', &mut v), Ok(2));
939939
assert_eq!(v, b"12");
940940

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

953953
#[test]
954954
fn split() {
955-
let buf = Cursor::new(b"12");
955+
let buf = Cursor::new(&b"12"[..]);
956956
let mut s = buf.split(b'3');
957957
assert_eq!(s.next(), Some(Ok(vec![b'1', b'2'])));
958958
assert_eq!(s.next(), None);
959959

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

967967
#[test]
968968
fn read_line() {
969-
let mut buf = Cursor::new(b"12");
969+
let mut buf = Cursor::new(&b"12"[..]);
970970
let mut v = String::new();
971971
assert_eq!(buf.read_line(&mut v), Ok(2));
972972
assert_eq!(v, "12");
973973

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

986986
#[test]
987987
fn lines() {
988-
let buf = Cursor::new(b"12");
988+
let buf = Cursor::new(&b"12"[..]);
989989
let mut s = buf.lines();
990990
assert_eq!(s.next(), Some(Ok("12".to_string())));
991991
assert_eq!(s.next(), None);
992992

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

10001000
#[test]
10011001
fn read_to_end() {
1002-
let mut c = Cursor::new(b"");
1002+
let mut c = Cursor::new(&b""[..]);
10031003
let mut v = Vec::new();
10041004
assert_eq!(c.read_to_end(&mut v), Ok(0));
10051005
assert_eq!(v, []);
10061006

1007-
let mut c = Cursor::new(b"1");
1007+
let mut c = Cursor::new(&b"1"[..]);
10081008
let mut v = Vec::new();
10091009
assert_eq!(c.read_to_end(&mut v), Ok(1));
10101010
assert_eq!(v, b"1");
10111011
}
10121012

10131013
#[test]
10141014
fn read_to_string() {
1015-
let mut c = Cursor::new(b"");
1015+
let mut c = Cursor::new(&b""[..]);
10161016
let mut v = String::new();
10171017
assert_eq!(c.read_to_string(&mut v), Ok(0));
10181018
assert_eq!(v, "");
10191019

1020-
let mut c = Cursor::new(b"1");
1020+
let mut c = Cursor::new(&b"1"[..]);
10211021
let mut v = String::new();
10221022
assert_eq!(c.read_to_string(&mut v), Ok(1));
10231023
assert_eq!(v, "1");
10241024

1025-
let mut c = Cursor::new(b"\xff");
1025+
let mut c = Cursor::new(&b"\xff"[..]);
10261026
let mut v = String::new();
10271027
assert!(c.read_to_string(&mut v).is_err());
10281028
}

src/libstd/old_io/util.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,8 @@ mod test {
445445

446446
#[test]
447447
fn limit_reader_buffer() {
448-
let r = &mut b"0123456789\n0123456789\n";
448+
let mut r: &[u8] = b"0123456789\n0123456789\n";
449+
let r = &mut r;
449450
{
450451
let mut r = LimitReader::new(r.by_ref(), 3);
451452
assert_eq!(r.read_line(), Ok("012".to_string()));

src/libstd/old_path/mod.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -311,7 +311,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
311311
/// # #[cfg(windows)] fn foo() {}
312312
/// # #[cfg(unix)] fn foo() {
313313
/// let p = Path::new("abc/def/ghi");
314-
/// assert_eq!(p.filename(), Some(b"ghi"));
314+
/// assert_eq!(p.filename(), Some(&b"ghi"[..]));
315315
/// # }
316316
/// ```
317317
fn filename<'a>(&'a self) -> Option<&'a [u8]>;
@@ -345,7 +345,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
345345
/// # #[cfg(windows)] fn foo() {}
346346
/// # #[cfg(unix)] fn foo() {
347347
/// let p = Path::new("/abc/def.txt");
348-
/// assert_eq!(p.filestem(), Some(b"def"));
348+
/// assert_eq!(p.filestem(), Some(&b"def"[..]));
349349
/// # }
350350
/// ```
351351
fn filestem<'a>(&'a self) -> Option<&'a [u8]> {
@@ -392,7 +392,7 @@ pub trait GenericPath: Clone + GenericPathUnsafe {
392392
/// # #[cfg(windows)] fn foo() {}
393393
/// # #[cfg(unix)] fn foo() {
394394
/// let p = Path::new("abc/def.txt");
395-
/// assert_eq!(p.extension(), Some(b"txt"));
395+
/// assert_eq!(p.extension(), Some(&b"txt"[..]));
396396
/// # }
397397
/// ```
398398
fn extension<'a>(&'a self) -> Option<&'a [u8]> {

0 commit comments

Comments
 (0)