From 3e626375d8d2226a203bf6ea6e98dab14774c59f Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Mon, 4 Aug 2014 14:20:11 +0200 Subject: DST coercions and DST structs [breaking-change] 1. The internal layout for traits has changed from (vtable, data) to (data, vtable). If you were relying on this in unsafe transmutes, you might get some very weird and apparently unrelated errors. You should not be doing this! Prefer not to do this at all, but if you must, you should use raw::TraitObject rather than hardcoding rustc's internal representation into your code. 2. The minimal type of reference-to-vec-literals (e.g., `&[1, 2, 3]`) is now a fixed size vec (e.g., `&[int, ..3]`) where it used to be an unsized vec (e.g., `&[int]`). If you want the unszied type, you must explicitly give the type (e.g., `let x: &[_] = &[1, 2, 3]`). Note in particular where multiple blocks must have the same type (e.g., if and else clauses, vec elements), the compiler will not coerce to the unsized type without a hint. E.g., `[&[1], &[1, 2]]` used to be a valid expression of type '[&[int]]'. It no longer type checks since the first element now has type `&[int, ..1]` and the second has type &[int, ..2]` which are incompatible. 3. The type of blocks (including functions) must be coercible to the expected type (used to be a subtype). Mostly this makes things more flexible and not less (in particular, in the case of coercing function bodies to the return type). However, in some rare cases, this is less flexible. TBH, I'm not exactly sure of the exact effects. I think the change causes us to resolve inferred type variables slightly earlier which might make us slightly more restrictive. Possibly it only affects blocks with unreachable code. E.g., `if ... { fail!(); "Hello" }` used to type check, it no longer does. The fix is to add a semicolon after the string. --- src/libsyntax/parse/mod.rs | 3 +- src/libsyntax/parse/parser.rs | 78 ++++++++++++++----------------------------- 2 files changed, 27 insertions(+), 54 deletions(-) (limited to 'src/libsyntax/parse') diff --git a/src/libsyntax/parse/mod.rs b/src/libsyntax/parse/mod.rs index 17a27a5a39e..585b98925cc 100644 --- a/src/libsyntax/parse/mod.rs +++ b/src/libsyntax/parse/mod.rs @@ -1137,7 +1137,8 @@ mod test { let item = parse_item_from_source_str(name.clone(), source, Vec::new(), &sess).unwrap(); let docs = item.attrs.iter().filter(|a| a.name().get() == "doc") .map(|a| a.value_str().unwrap().get().to_string()).collect::>(); - assert_eq!(docs.as_slice(), &["/// doc comment".to_string(), "/// line 2".to_string()]); + let b: &[_] = &["/// doc comment".to_string(), "/// line 2".to_string()]; + assert_eq!(docs.as_slice(), b); let source = "/** doc comment\r\n * with CRLF */\r\nfn foo() {}".to_string(); let item = parse_item_from_source_str(name, source, Vec::new(), &sess).unwrap(); diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 2409912abe4..00513f7f67c 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -27,9 +27,8 @@ use ast::{ExprField, ExprFnBlock, ExprIf, ExprIndex}; use ast::{ExprLit, ExprLoop, ExprMac}; use ast::{ExprMethodCall, ExprParen, ExprPath, ExprProc}; use ast::{ExprRepeat, ExprRet, ExprStruct, ExprTup, ExprUnary, ExprUnboxedFn}; -use ast::{ExprVec, ExprVstore, ExprVstoreSlice}; -use ast::{ExprVstoreMutSlice, ExprWhile, ExprForLoop, Field, FnDecl}; -use ast::{ExprVstoreUniq, Once, Many}; +use ast::{ExprVec, ExprWhile, ExprForLoop, Field, FnDecl}; +use ast::{Once, Many}; use ast::{FnUnboxedClosureKind, FnMutUnboxedClosureKind}; use ast::{FnOnceUnboxedClosureKind}; use ast::{ForeignItem, ForeignItemStatic, ForeignItemFn, ForeignMod}; @@ -1428,13 +1427,16 @@ impl<'a> Parser<'a> { } else if self.token == token::TILDE { // OWNED POINTER self.bump(); - let last_span = self.last_span; + let span = self.last_span; match self.token { - token::LBRACKET => - self.obsolete(last_span, ObsoleteOwnedVector), - _ => self.obsolete(last_span, ObsoleteOwnedType), - }; - TyUniq(self.parse_ty(true)) + token::IDENT(ref ident, _) + if "str" == token::get_ident(*ident).get() => { + // This is OK (for now). + } + token::LBRACKET => {} // Also OK. + _ => self.obsolete(span, ObsoleteOwnedType) + } + TyUniq(self.parse_ty(false)) } else if self.token == token::BINOP(token::STAR) { // STAR POINTER (bare pointer?) self.bump(); @@ -2549,16 +2551,7 @@ impl<'a> Parser<'a> { let m = self.parse_mutability(); let e = self.parse_prefix_expr(); hi = e.span.hi; - // HACK: turn &[...] into a &-vec - ex = match e.node { - ExprVec(..) if m == MutImmutable => { - ExprVstore(e, ExprVstoreSlice) - } - ExprVec(..) if m == MutMutable => { - ExprVstore(e, ExprVstoreMutSlice) - } - _ => ExprAddrOf(m, e) - }; + ex = ExprAddrOf(m, e); } token::AT => { self.bump(); @@ -2570,25 +2563,18 @@ impl<'a> Parser<'a> { } token::TILDE => { self.bump(); + let span = self.last_span; + match self.token { + token::LIT_STR(_) => { + // This is OK (for now). + } + token::LBRACKET => {} // Also OK. + _ => self.obsolete(span, ObsoleteOwnedExpr) + } let e = self.parse_prefix_expr(); hi = e.span.hi; - // HACK: turn ~[...] into a ~-vec - let last_span = self.last_span; - ex = match e.node { - ExprVec(..) | ExprRepeat(..) => { - self.obsolete(last_span, ObsoleteOwnedVector); - ExprVstore(e, ExprVstoreUniq) - } - ExprLit(lit) if lit_is_str(lit) => { - self.obsolete(last_span, ObsoleteOwnedExpr); - ExprVstore(e, ExprVstoreUniq) - } - _ => { - self.obsolete(last_span, ObsoleteOwnedExpr); - self.mk_unary(UnUniq, e) - } - }; + ex = self.mk_unary(UnUniq, e); } token::IDENT(_, _) => { if self.is_keyword(keywords::Box) { @@ -2607,24 +2593,10 @@ impl<'a> Parser<'a> { } } - // Otherwise, we use the unique pointer default. - let subexpression = self.parse_prefix_expr(); - hi = subexpression.span.hi; - // HACK: turn `box [...]` into a boxed-vec - ex = match subexpression.node { - ExprVec(..) | ExprRepeat(..) => { - let last_span = self.last_span; - self.obsolete(last_span, ObsoleteOwnedVector); - ExprVstore(subexpression, ExprVstoreUniq) - } - ExprLit(lit) if lit_is_str(lit) => { - ExprVstore(subexpression, ExprVstoreUniq) - } - _ => self.mk_unary(UnUniq, subexpression) - }; - } else { - return self.parse_dot_or_call_expr() - } + // Otherwise, we use the unique pointer default. + let subexpression = self.parse_prefix_expr(); + hi = subexpression.span.hi; + ex = self.mk_unary(UnUniq, subexpression); } _ => return self.parse_dot_or_call_expr() } -- cgit 1.4.1-3-g733a5 From 52ef46251ede1ff51e5d5621d5fe2614e950f963 Mon Sep 17 00:00:00 2001 From: Nick Cameron Date: Wed, 6 Aug 2014 11:59:40 +0200 Subject: Rebasing changes --- src/libcollections/ringbuf.rs | 6 +- src/libcollections/str.rs | 13 +- src/libcollections/string.rs | 6 +- src/libcore/cmp.rs | 5 +- src/libcore/option.rs | 5 +- src/libcore/raw.rs | 4 +- src/libcore/slice.rs | 21 +++ src/libcoretest/iter.rs | 4 +- src/libdebug/reflect.rs | 2 +- src/libdebug/repr.rs | 2 +- src/liblibc/lib.rs | 2 +- src/librbml/io.rs | 18 +- src/librlibc/lib.rs | 2 +- src/librustc/diagnostics.rs | 6 - src/librustc/front/test.rs | 4 +- src/librustc/lint/builtin.rs | 3 + src/librustc/middle/astencode.rs | 12 +- src/librustc/middle/check_const.rs | 2 +- src/librustc/middle/intrinsicck.rs | 5 +- src/librustc/middle/mem_categorization.rs | 2 +- src/librustc/middle/subst.rs | 2 +- src/librustc/middle/trans/_match.rs | 2 +- src/librustc/middle/trans/adt.rs | 76 +++++--- src/librustc/middle/trans/base.rs | 61 ++++-- src/librustc/middle/trans/callee.rs | 1 + src/librustc/middle/trans/common.rs | 3 + src/librustc/middle/trans/consts.rs | 10 +- src/librustc/middle/trans/controlflow.rs | 4 +- src/librustc/middle/trans/datum.rs | 7 +- src/librustc/middle/trans/debuginfo.rs | 36 ++-- src/librustc/middle/trans/expr.rs | 114 ++++++----- src/librustc/middle/trans/glue.rs | 208 ++++++++++++++++++--- src/librustc/middle/trans/intrinsic.rs | 18 +- src/librustc/middle/trans/meth.rs | 19 +- src/librustc/middle/trans/reflect.rs | 32 ++-- src/librustc/middle/trans/tvec.rs | 51 ++++- src/librustc/middle/trans/type_of.rs | 24 ++- src/librustc/middle/ty.rs | 61 +++--- src/librustc/middle/ty_fold.rs | 18 +- src/librustc/middle/typeck/check/method.rs | 4 +- src/librustc/middle/typeck/check/mod.rs | 131 ++++++------- src/librustc/middle/typeck/check/vtable.rs | 21 +-- src/librustc/middle/typeck/infer/coercion.rs | 15 +- src/librustc/util/ppaux.rs | 2 +- src/libserialize/serialize.rs | 1 - src/libsyntax/parse/parser.rs | 31 +-- src/libtime/lib.rs | 37 +--- src/libunicode/u_str.rs | 9 +- src/liburl/lib.rs | 6 +- src/rt/rust_builtin.c | 42 +---- .../compile-fail/const-cast-different-types.rs | 6 +- src/test/compile-fail/dst-bad-assign-2.rs | 2 +- src/test/compile-fail/dst-bad-assign.rs | 4 +- src/test/compile-fail/dst-bad-coerce1.rs | 4 +- src/test/compile-fail/dst-bad-coerce2.rs | 2 +- src/test/compile-fail/dst-bad-coerce3.rs | 2 +- src/test/compile-fail/dst-bad-coerce4.rs | 4 +- src/test/compile-fail/dst-bad-deep.rs | 2 +- src/test/compile-fail/issue-3907-2.rs | 4 +- src/test/compile-fail/issue-4972.rs | 2 +- src/test/compile-fail/issue-5035-2.rs | 4 +- src/test/compile-fail/issue-5883.rs | 2 +- src/test/compile-fail/issue-7013.rs | 2 +- src/test/compile-fail/tuple-arity-mismatch.rs | 2 +- src/test/pretty/issue-4264.pp | 6 +- .../graphviz-flowgraph/f15.dot-expected.dot | 2 +- .../graphviz-flowgraph/f16.dot-expected.dot | 2 +- src/test/run-pass/dst-dtor-1.rs | 34 ++++ src/test/run-pass/dst-dtor-2.rs | 31 +++ src/test/run-pass/dst-struct-reflect.rs | 4 +- src/test/run-pass/dst-struct-sole.rs | 2 +- src/test/run-pass/dst-struct.rs | 2 +- src/test/run-pass/dst-trait.rs | 2 +- src/test/run-pass/gc-vec.rs | 4 +- src/test/run-pass/issue-14936.rs | 3 +- src/test/run-pass/issue-15080.rs | 2 +- src/test/run-pass/match-vec-alternatives.rs | 22 ++- src/test/run-pass/order-drop-with-match.rs | 3 +- src/test/run-pass/vec-matching.rs | 3 +- src/test/run-pass/vec-to_str.rs | 4 +- 80 files changed, 851 insertions(+), 487 deletions(-) create mode 100644 src/test/run-pass/dst-dtor-1.rs create mode 100644 src/test/run-pass/dst-dtor-2.rs (limited to 'src/libsyntax/parse') diff --git a/src/libcollections/ringbuf.rs b/src/libcollections/ringbuf.rs index d2cfb510bc0..2f0fbfadb17 100644 --- a/src/libcollections/ringbuf.rs +++ b/src/libcollections/ringbuf.rs @@ -243,7 +243,8 @@ impl RingBuf { /// buf.push(5i); /// buf.push(3); /// buf.push(4); - /// assert_eq!(buf.iter().collect::>().as_slice(), &[&5, &3, &4]); + /// let b: &[_] = &[&5, &3, &4]; + /// assert_eq!(buf.iter().collect::>().as_slice(), b); /// ``` pub fn iter<'a>(&'a self) -> Items<'a, T> { Items{index: 0, rindex: self.nelts, lo: self.lo, elts: self.elts.as_slice()} @@ -263,7 +264,8 @@ impl RingBuf { /// for num in buf.mut_iter() { /// *num = *num - 2; /// } - /// assert_eq!(buf.mut_iter().collect::>().as_slice(), &[&mut 3, &mut 1, &mut 2]); + /// let b: &[_] = &[&mut 3, &mut 1, &mut 2]; + /// assert_eq!(buf.mut_iter().collect::>().as_slice(), b); /// ``` pub fn mut_iter<'a>(&'a mut self) -> MutItems<'a, T> { let start_index = raw_index(self.lo, self.elts.len(), 0); diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 1145e1f3573..3f9a179872e 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1971,7 +1971,7 @@ mod tests { use std::iter::order; // official Unicode test data // from http://www.unicode.org/Public/UCD/latest/ucd/auxiliary/GraphemeBreakTest.txt - let test_same = [ + let test_same: [(_, &[_]), .. 325] = [ ("\u0020\u0020", &["\u0020", "\u0020"]), ("\u0020\u0308\u0020", &["\u0020\u0308", "\u0020"]), ("\u0020\u000D", &["\u0020", "\u000D"]), ("\u0020\u0308\u000D", &["\u0020\u0308", "\u000D"]), ("\u0020\u000A", &["\u0020", "\u000A"]), @@ -2180,7 +2180,7 @@ mod tests { ("\u0646\u200D\u0020", &["\u0646\u200D", "\u0020"]), ]; - let test_diff = [ + let test_diff: [(_, &[_], &[_]), .. 23] = [ ("\u0020\u0903", &["\u0020\u0903"], &["\u0020", "\u0903"]), ("\u0020\u0308\u0903", &["\u0020\u0308\u0903"], &["\u0020\u0308", "\u0903"]), ("\u000D\u0308\u0903", &["\u000D", "\u0308\u0903"], &["\u000D", "\u0308", "\u0903"]), ("\u000A\u0308\u0903", @@ -2229,9 +2229,11 @@ mod tests { // test the indices iterators let s = "a̐éö̲\r\n"; let gr_inds = s.grapheme_indices(true).collect::>(); - assert_eq!(gr_inds.as_slice(), &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]); + let b: &[_] = &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + assert_eq!(gr_inds.as_slice(), b); let gr_inds = s.grapheme_indices(true).rev().collect::>(); - assert_eq!(gr_inds.as_slice(), &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0u, "a̐")]); + let b: &[_] = &[(11, "\r\n"), (6, "ö̲"), (3, "é"), (0u, "a̐")]; + assert_eq!(gr_inds.as_slice(), b); let mut gr_inds = s.grapheme_indices(true); let e1 = gr_inds.size_hint(); assert_eq!(e1, (1, Some(13))); @@ -2243,7 +2245,8 @@ mod tests { // make sure the reverse iterator does the right thing with "\n" at beginning of string let s = "\n\r\n\r"; let gr = s.graphemes(true).rev().collect::>(); - assert_eq!(gr.as_slice(), &["\r", "\r\n", "\n"]); + let b: &[_] = &["\r", "\r\n", "\n"]; + assert_eq!(gr.as_slice(), b); } #[test] diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 89fdc4d42fb..05d91a75041 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -531,7 +531,8 @@ impl String { /// /// ``` /// let s = String::from_str("hello"); - /// assert_eq!(s.as_bytes(), &[104, 101, 108, 108, 111]); + /// let b: &[_] = &[104, 101, 108, 108, 111]; + /// assert_eq!(s.as_bytes(), b); /// ``` #[inline] pub fn as_bytes<'a>(&'a self) -> &'a [u8] { @@ -552,7 +553,8 @@ impl String { /// bytes[1] = 51; /// bytes[4] = 48; /// } - /// assert_eq!(s.as_bytes(), &[104, 51, 108, 108, 48]); + /// let b: &[_] = &[104, 51, 108, 108, 48]; + /// assert_eq!(s.as_bytes(), b); /// assert_eq!(s.as_slice(), "h3ll0") /// ``` #[inline] diff --git a/src/libcore/cmp.rs b/src/libcore/cmp.rs index bfd10c835e2..b90c6daf9eb 100644 --- a/src/libcore/cmp.rs +++ b/src/libcore/cmp.rs @@ -112,12 +112,13 @@ impl Ordering { /// assert_eq!(Greater.reverse(), Less); /// /// - /// let mut data = &mut [2u, 10, 5, 8]; + /// let mut data: &mut [_] = &mut [2u, 10, 5, 8]; /// /// // sort the array from largest to smallest. /// data.sort_by(|a, b| a.cmp(b).reverse()); /// - /// assert_eq!(data, &mut [10u, 8, 5, 2]); + /// let b: &mut [_] = &mut [10u, 8, 5, 2]; + /// assert!(data == b); /// ``` #[inline] #[experimental] diff --git a/src/libcore/option.rs b/src/libcore/option.rs index 47df8ae68cd..7773e03416e 100644 --- a/src/libcore/option.rs +++ b/src/libcore/option.rs @@ -530,7 +530,10 @@ impl Slice for Option { fn as_slice<'a>(&'a self) -> &'a [T] { match *self { Some(ref x) => slice::ref_slice(x), - None => &[] + None => { + let result: &[_] = &[]; + result + } } } } diff --git a/src/libcore/raw.rs b/src/libcore/raw.rs index aa8a4976867..5daa693c774 100644 --- a/src/libcore/raw.rs +++ b/src/libcore/raw.rs @@ -58,8 +58,8 @@ pub struct TraitObject { } #[cfg(not(stage0))] pub struct TraitObject { - pub data: *(), - pub vtable: *(), + pub data: *mut (), + pub vtable: *mut (), } /// This trait is meant to map equivalences between raw structs and their diff --git a/src/libcore/slice.rs b/src/libcore/slice.rs index 8c55662f163..475c2e94ec7 100644 --- a/src/libcore/slice.rs +++ b/src/libcore/slice.rs @@ -1648,6 +1648,27 @@ impl<'a,T:PartialEq, V: Slice> Equiv for &'a [T] { fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } } +#[unstable = "waiting for DST"] +impl<'a,T:PartialEq> PartialEq for &'a mut [T] { + fn eq(&self, other: & &'a mut [T]) -> bool { + self.len() == other.len() && + order::eq(self.iter(), other.iter()) + } + fn ne(&self, other: & &'a mut [T]) -> bool { + self.len() != other.len() || + order::ne(self.iter(), other.iter()) + } +} + +#[unstable = "waiting for DST"] +impl<'a,T:Eq> Eq for &'a mut [T] {} + +#[unstable = "waiting for DST"] +impl<'a,T:PartialEq, V: Slice> Equiv for &'a mut [T] { + #[inline] + fn equiv(&self, other: &V) -> bool { self.as_slice() == other.as_slice() } +} + #[unstable = "waiting for DST"] impl<'a,T:Ord> Ord for &'a [T] { fn cmp(&self, other: & &'a [T]) -> Ordering { diff --git a/src/libcoretest/iter.rs b/src/libcoretest/iter.rs index d25ffb5b84c..99ac7cfed02 100644 --- a/src/libcoretest/iter.rs +++ b/src/libcoretest/iter.rs @@ -368,7 +368,7 @@ fn test_collect() { #[test] fn test_all() { - let v: Box<&[int]> = box &[1i, 2, 3, 4, 5]; + let v: Box<[int]> = box [1i, 2, 3, 4, 5]; assert!(v.iter().all(|&x| x < 10)); assert!(!v.iter().all(|&x| x % 2 == 0)); assert!(!v.iter().all(|&x| x > 100)); @@ -377,7 +377,7 @@ fn test_all() { #[test] fn test_any() { - let v: Box<&[int]> = box &[1i, 2, 3, 4, 5]; + let v: Box<[int]> = box [1i, 2, 3, 4, 5]; assert!(v.iter().any(|&x| x < 10)); assert!(v.iter().any(|&x| x % 2 == 0)); assert!(!v.iter().any(|&x| x > 100)); diff --git a/src/libdebug/reflect.rs b/src/libdebug/reflect.rs index 0d7209b5999..b89ea4d373d 100644 --- a/src/libdebug/reflect.rs +++ b/src/libdebug/reflect.rs @@ -251,7 +251,7 @@ impl TyVisitor for MovePtrAdaptor { } #[cfg(not(stage0))] fn visit_evec_fixed(&mut self, n: uint, sz: uint, align: uint, - inner: *TyDesc) -> bool { + inner: *const TyDesc) -> bool { self.align(align); if ! self.inner.visit_evec_fixed(n, sz, align, inner) { return false; diff --git a/src/libdebug/repr.rs b/src/libdebug/repr.rs index c810e1f6473..20f96d24a5f 100644 --- a/src/libdebug/repr.rs +++ b/src/libdebug/repr.rs @@ -342,7 +342,7 @@ impl<'a> TyVisitor for ReprVisitor<'a> { #[cfg(not(stage0))] fn visit_evec_fixed(&mut self, n: uint, sz: uint, _align: uint, - inner: *TyDesc) -> bool { + inner: *const TyDesc) -> bool { let assumed_size = if sz == 0 { n } else { sz }; self.get::<()>(|this, b| { this.write_vec_range(b, assumed_size, inner) diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 265d1e37ec3..949dd08eaa3 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -302,7 +302,7 @@ extern {} /// A wrapper for a nullable pointer. Don't use this except for interacting /// with libc. Basically Option, but without the dependence on libstd. // If/when libprim happens, this can be removed in favor of that -pub enum Nullable { +pub enum Nullable { Null, NotNull(T) } diff --git a/src/librbml/io.rs b/src/librbml/io.rs index 9ab163c5f47..443bf4d34ff 100644 --- a/src/librbml/io.rs +++ b/src/librbml/io.rs @@ -96,7 +96,8 @@ impl Writer for SeekableMemWriter { let (left, right) = if cap <= buf.len() { (buf.slice_to(cap), buf.slice_from(cap)) } else { - (buf, &[]) + let result: (_, &[_]) = (buf, &[]); + result }; // Do the necessary writes @@ -142,24 +143,29 @@ mod tests { writer.write([1, 2, 3]).unwrap(); writer.write([4, 5, 6, 7]).unwrap(); assert_eq!(writer.tell(), Ok(8)); - assert_eq!(writer.get_ref(), &[0, 1, 2, 3, 4, 5, 6, 7]); + let b: &[_] = &[0, 1, 2, 3, 4, 5, 6, 7]; + assert_eq!(writer.get_ref(), b); writer.seek(0, io::SeekSet).unwrap(); assert_eq!(writer.tell(), Ok(0)); writer.write([3, 4]).unwrap(); - assert_eq!(writer.get_ref(), &[3, 4, 2, 3, 4, 5, 6, 7]); + let b: &[_] = &[3, 4, 2, 3, 4, 5, 6, 7]; + assert_eq!(writer.get_ref(), b); writer.seek(1, io::SeekCur).unwrap(); writer.write([0, 1]).unwrap(); - assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 7]); + let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 7]; + assert_eq!(writer.get_ref(), b); writer.seek(-1, io::SeekEnd).unwrap(); writer.write([1, 2]).unwrap(); - assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2]); + let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2]; + assert_eq!(writer.get_ref(), b); writer.seek(1, io::SeekEnd).unwrap(); writer.write([1]).unwrap(); - assert_eq!(writer.get_ref(), &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]); + let b: &[_] = &[3, 4, 2, 0, 1, 5, 6, 1, 2, 0, 1]; + assert_eq!(writer.get_ref(), b); } #[test] diff --git a/src/librlibc/lib.rs b/src/librlibc/lib.rs index b43ad1eabf9..739ec2cf43f 100644 --- a/src/librlibc/lib.rs +++ b/src/librlibc/lib.rs @@ -49,7 +49,7 @@ // implementations below. If pointer arithmetic is done through integers the // optimizations start to break down. extern "rust-intrinsic" { - fn offset(dst: *const T, offset: int) -> *const T; + fn offset(dst: *const T, offset: int) -> *const T; } #[no_mangle] diff --git a/src/librustc/diagnostics.rs b/src/librustc/diagnostics.rs index a789049d4de..77e73c46c40 100644 --- a/src/librustc/diagnostics.rs +++ b/src/librustc/diagnostics.rs @@ -34,7 +34,6 @@ register_diagnostics!( E0015, E0016, E0017, - E0018, E0019, E0020, E0021, @@ -53,7 +52,6 @@ register_diagnostics!( E0034, E0035, E0036, - E0037, E0038, E0039, E0040, @@ -80,8 +78,6 @@ register_diagnostics!( E0061, E0062, E0063, - E0064, - E0065, E0066, E0067, E0068, @@ -127,8 +123,6 @@ register_diagnostics!( E0108, E0109, E0110, - E0111, - E0112, E0113, E0114, E0115, diff --git a/src/librustc/front/test.rs b/src/librustc/front/test.rs index 9984aba8d08..5f26a966f97 100644 --- a/src/librustc/front/test.rs +++ b/src/librustc/front/test.rs @@ -477,10 +477,10 @@ fn mk_test_descs(cx: &TestCtxt) -> Gc { box(GC) ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprAddrOf(box(GC) ast::MutImmutable, + node: ast::ExprAddrOf(ast::MutImmutable, box(GC) ast::Expr { id: ast::DUMMY_NODE_ID, - node: ast::ExprVec(cx.testfns.borrow().iter().map(|test| { + node: ast::ExprVec(cx.testfns.iter().map(|test| { mk_test_desc_and_fn_rec(cx, test) }).collect()), span: DUMMY_SP, diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs index 6cc1c6a7b37..214401b17a1 100644 --- a/src/librustc/lint/builtin.rs +++ b/src/librustc/lint/builtin.rs @@ -1556,6 +1556,9 @@ declare_lint!(pub UNKNOWN_CRATE_TYPE, Deny, declare_lint!(pub VARIANT_SIZE_DIFFERENCE, Allow, "detects enums with widely varying variant sizes") +declare_lint!(pub TRANSMUTE_FAT_PTR, Allow, + "detects transmutes of fat pointers") + /// Does nothing as a lint pass, but registers some `Lint`s /// which are used by other parts of the compiler. pub struct HardwiredLints; diff --git a/src/librustc/middle/astencode.rs b/src/librustc/middle/astencode.rs index 260e38f2070..6a8ee267542 100644 --- a/src/librustc/middle/astencode.rs +++ b/src/librustc/middle/astencode.rs @@ -1029,6 +1029,8 @@ impl<'a> rbml_writer_helpers for Encoder<'a> { } fn emit_autoref(&mut self, ecx: &e::EncodeContext, autoref: &ty::AutoRef) { + use serialize::Encoder; + self.emit_enum("AutoRef", |this| { match autoref { &ty::AutoPtr(r, m, None) => { @@ -1067,6 +1069,8 @@ impl<'a> rbml_writer_helpers for Encoder<'a> { } fn emit_auto_deref_ref(&mut self, ecx: &e::EncodeContext, auto_deref_ref: &ty::AutoDerefRef) { + use serialize::Encoder; + self.emit_struct("AutoDerefRef", 2, |this| { this.emit_struct_field("autoderefs", 0, |this| auto_deref_ref.autoderefs.encode(this)); this.emit_struct_field("autoref", 1, |this| { @@ -1081,6 +1085,8 @@ impl<'a> rbml_writer_helpers for Encoder<'a> { } fn emit_unsize_kind(&mut self, ecx: &e::EncodeContext, uk: &ty::UnsizeKind) { + use serialize::Encoder; + self.emit_enum("UnsizeKind", |this| { match *uk { ty::UnsizeLength(len) => { @@ -1286,7 +1292,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, _ if ty::adjust_is_object(adjustment) => { let method_call = MethodCall::autoobject(id); for &method in tcx.method_map.borrow().find(&method_call).iter() { - rbml_w.tag(c::tag_table_method_map, |ebml_w| { + rbml_w.tag(c::tag_table_method_map, |rbml_w| { rbml_w.id(id); rbml_w.tag(c::tag_table_val, |rbml_w| { encode_method_callee(ecx, rbml_w, method_call.adjustment, method) @@ -1297,7 +1303,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, for &dr in tcx.vtable_map.borrow().find(&method_call).iter() { rbml_w.tag(c::tag_table_vtable_map, |rbml_w| { rbml_w.id(id); - rbml_w.tag(c::tag_table_val, |ebml_w| { + rbml_w.tag(c::tag_table_val, |rbml_w| { encode_vtable_res_with_key(ecx, rbml_w, method_call.adjustment, dr); }) }) @@ -1336,7 +1342,7 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext, rbml_w.tag(c::tag_table_adjustments, |rbml_w| { rbml_w.id(id); rbml_w.tag(c::tag_table_val, |rbml_w| { - rbml_w.emit_auto_adjustment(ecx, adj); + rbml_w.emit_auto_adjustment(ecx, adjustment); }) }) } diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index b0b2fe89c3f..629aba8092c 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -182,7 +182,7 @@ fn check_expr(v: &mut CheckCrateVisitor, e: &Expr, is_const: bool) { // Mutable slices are allowed. ExprVec(_) => {} _ => span_err!(v.tcx.sess, e.span, E0017, - "references in constants may only refer to immutable values"); + "references in constants may only refer to immutable values") } }, diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 6669147b0dc..639f89dc3cc 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -92,7 +92,7 @@ impl<'a> IntrinsicCheckingVisitor<'a> { } } - fn check_transmute(&self, span: Span, from: ty::t, to: ty::t) { + fn check_transmute(&self, span: Span, from: ty::t, to: ty::t, id: ast::NodeId) { if type_size_is_affected_by_type_parameters(self.tcx, from) { span_err!(self.tcx.sess, span, E0139, "cannot transmute from a type that contains type parameters"); @@ -106,6 +106,7 @@ impl<'a> IntrinsicCheckingVisitor<'a> { span: span, from: from, to: to, + id: id, }; self.tcx.transmute_restrictions.borrow_mut().push(restriction); } @@ -123,7 +124,7 @@ impl<'a> Visitor<()> for IntrinsicCheckingVisitor<'a> { if bare_fn_ty.abi == RustIntrinsic => { let from = *bare_fn_ty.sig.inputs.get(0); let to = bare_fn_ty.sig.output; - self.check_transmute(expr.span, from, to); + self.check_transmute(expr.span, from, to, expr.id); } _ => { self.tcx diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 155b69d0a84..2d052feb672 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -214,7 +214,7 @@ pub fn opt_deref_kind(t: ty::t) -> Option { } pub fn deref_kind(tcx: &ty::ctxt, t: ty::t) -> deref_kind { - debug!("deref_kind {}", ty_to_str(tcx, t)); + debug!("deref_kind {}", ty_to_string(tcx, t)); match opt_deref_kind(t) { Some(k) => k, None => { diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs index 673872103af..ccc4dbb21e0 100644 --- a/src/librustc/middle/subst.rs +++ b/src/librustc/middle/subst.rs @@ -403,7 +403,7 @@ impl VecPerParamSpace { self.content.slice(start, limit) } - fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] { + pub fn get_mut_slice<'a>(&'a mut self, space: ParamSpace) -> &'a mut [T] { let (start, limit) = self.limits(space); self.content.mut_slice(start, limit) } diff --git a/src/librustc/middle/trans/_match.rs b/src/librustc/middle/trans/_match.rs index 4a26d4f8002..28f396c8bf7 100644 --- a/src/librustc/middle/trans/_match.rs +++ b/src/librustc/middle/trans/_match.rs @@ -280,7 +280,7 @@ fn trans_opt<'a>(mut bcx: &'a Block<'a>, o: &Opt) -> opt_result<'a> { match *o { lit(lit_expr) => { let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id); - let (llval, _) = consts::const_expr(ccx, &*lit_expr, true); + let (llval, _, _) = consts::const_expr(ccx, &*lit_expr, true); let lit_datum = immediate_rvalue(llval, lit_ty); let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx)); return single_result(Result::new(bcx, lit_datum.val)); diff --git a/src/librustc/middle/trans/adt.rs b/src/librustc/middle/trans/adt.rs index 3bcefe7ec9d..f3f4a88fdee 100644 --- a/src/librustc/middle/trans/adt.rs +++ b/src/librustc/middle/trans/adt.rs @@ -127,11 +127,11 @@ pub enum Repr { /// For structs, and struct-like parts of anything fancier. pub struct Struct { - // If the struct is DST, then we will not know its size. We must be careful - // never to use such a struct when a fixed size is required (e.g., stack - // allocation). - pub size: Option, - pub align: Option, + // If the struct is DST, then the size and alignment do not take into + // account the unsized fields of the struct. + pub size: u64, + pub align: u64, + pub sized: bool, pub packed: bool, pub fields: Vec } @@ -269,7 +269,7 @@ fn represent_type_uncached(cx: &CrateContext, t: ty::t) -> Repr { }).collect(), dtor); } _ => cx.sess().bug(format!("adt::represent_type called on non-ADT type: {}", - ty_to_str(cx.tcx(), t)).as_slice()) + ty_to_string(cx.tcx(), t)).as_slice()) } } @@ -288,7 +288,7 @@ pub enum PointerField { impl Case { fn is_zerolen(&self, cx: &CrateContext) -> bool { - mk_struct(cx, self.tys.as_slice(), false).size.unwrap() == 0 + mk_struct(cx, self.tys.as_slice(), false).size == 0 } fn find_ptr(&self) -> Option { @@ -310,7 +310,7 @@ impl Case { // Box could either be a thin or fat pointer depending on T ty::ty_uniq(t) => match ty::get(t).sty { - ty::ty_vec(_, None) | return Some(FatPointer(i, slice_elt_base)), + ty::ty_vec(_, None) => return Some(FatPointer(i, slice_elt_base)), // Box is a pair of pointers: the actual object and a vtable ty::ty_trait(..) => return Some(FatPointer(i, trt_field_box)), @@ -351,18 +351,24 @@ fn mk_struct(cx: &CrateContext, tys: &[ty::t], packed: bool) -> Struct { let lltys = tys.iter().map(|&ty| type_of::sizing_type_of(cx, ty)).collect::>(); let llty_rec = Type::struct_(cx, lltys.as_slice(), packed); Struct { - size: Some(machine::llsize_of_alloc(cx, llty_rec) /*bad*/as u64), - align: Some(machine::llalign_of_min(cx, llty_rec) /*bad*/as u64), + size: machine::llsize_of_alloc(cx, llty_rec), + align: machine::llalign_of_min(cx, llty_rec), + sized: true, packed: packed, fields: Vec::from_slice(tys), } } else { + // Ignore any dynamically sized fields. + let lltys = tys.iter().filter(|&ty| ty::type_is_sized(cx.tcx(), *ty)) + .map(|&ty| type_of::sizing_type_of(cx, ty)).collect::>(); + let llty_rec = Type::struct_(cx, lltys.as_slice(), packed); Struct { - size: None, - align: None, + size: machine::llsize_of_alloc(cx, llty_rec), + align: machine::llalign_of_min(cx, llty_rec), + sized: false, packed: packed, fields: Vec::from_slice(tys), - } + } } } @@ -467,31 +473,38 @@ pub fn ty_of_inttype(ity: IntType) -> ty::t { * unbounded recursion; see also the comments in `trans::type_of`. */ pub fn type_of(cx: &CrateContext, r: &Repr) -> Type { - generic_type_of(cx, r, None, false) + generic_type_of(cx, r, None, false, false) } -pub fn sizing_type_of(cx: &CrateContext, r: &Repr) -> Type { - generic_type_of(cx, r, None, true) +// Pass dst=true if the type you are passing is a DST. Yes, we could figure +// this out, but if you call this on an unsized type without realising it, you +// are going to get the wrong type (it will not include the unsized parts of it). +pub fn sizing_type_of(cx: &CrateContext, r: &Repr, dst: bool) -> Type { + generic_type_of(cx, r, None, true, dst) } pub fn incomplete_type_of(cx: &CrateContext, r: &Repr, name: &str) -> Type { - generic_type_of(cx, r, Some(name), false) + generic_type_of(cx, r, Some(name), false, false) } pub fn finish_type_of(cx: &CrateContext, r: &Repr, llty: &mut Type) { match *r { CEnum(..) | General(..) | RawNullablePointer { .. } => { } Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => - llty.set_struct_body(struct_llfields(cx, st, false).as_slice(), + llty.set_struct_body(struct_llfields(cx, st, false, false).as_slice(), st.packed) } } -fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool) -> Type { +fn generic_type_of(cx: &CrateContext, + r: &Repr, + name: Option<&str>, + sizing: bool, + dst: bool) -> Type { match *r { CEnum(ity, _, _) => ll_inttype(cx, ity), RawNullablePointer { nnty, .. } => type_of::sizing_type_of(cx, nnty), Univariant(ref st, _) | StructWrappedNullablePointer { nonnull: ref st, .. } => { match name { None => { - Type::struct_(cx, struct_llfields(cx, st, sizing).as_slice(), + Type::struct_(cx, struct_llfields(cx, st, sizing, dst).as_slice(), st.packed) } Some(name) => { assert_eq!(sizing, false); Type::named_struct(cx, name) } @@ -510,9 +523,9 @@ fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool // of the size. // // FIXME #10604: this breaks when vector types are present. - let size = sts.iter().map(|st| st.size.unwrap()).max().unwrap(); - let most_aligned = sts.iter().max_by(|st| st.align.unwrap()).unwrap(); - let align = most_aligned.align.unwrap(); + let size = sts.iter().map(|st| st.size).max().unwrap(); + let most_aligned = sts.iter().max_by(|st| st.align).unwrap(); + let align = most_aligned.align; let discr_ty = ll_inttype(cx, ity); let discr_size = machine::llsize_of_alloc(cx, discr_ty) as u64; let align_units = (size + align - 1) / align - 1; @@ -543,9 +556,10 @@ fn generic_type_of(cx: &CrateContext, r: &Repr, name: Option<&str>, sizing: bool } } -fn struct_llfields(cx: &CrateContext, st: &Struct, sizing: bool) -> Vec { +fn struct_llfields(cx: &CrateContext, st: &Struct, sizing: bool, dst: bool) -> Vec { if sizing { - st.fields.iter().map(|&ty| type_of::sizing_type_of(cx, ty)).collect() + st.fields.iter().filter(|&ty| !dst || ty::type_is_sized(cx.tcx(), *ty)) + .map(|&ty| type_of::sizing_type_of(cx, ty)).collect() } else { st.fields.iter().map(|&ty| type_of::type_of(cx, ty)).collect() } @@ -906,12 +920,12 @@ pub fn trans_const(ccx: &CrateContext, r: &Repr, discr: Disr, } General(ity, ref cases, _) => { let case = cases.get(discr as uint); - let max_sz = cases.iter().map(|x| x.size.unwrap()).max().unwrap(); + let max_sz = cases.iter().map(|x| x.size).max().unwrap(); let lldiscr = C_integral(ll_inttype(ccx, ity), discr as u64, true); let contents = build_const_struct(ccx, case, (vec!(lldiscr)).append(vals).as_slice()); - C_struct(ccx, contents.append([padding(ccx, max_sz - case.size.unwrap())]).as_slice(), + C_struct(ccx, contents.append([padding(ccx, max_sz - case.size)]).as_slice(), false) } Univariant(ref st, _dro) => { @@ -958,7 +972,7 @@ fn compute_struct_field_offsets(ccx: &CrateContext, st: &Struct) -> Vec { for &ty in st.fields.iter() { let llty = type_of::sizing_type_of(ccx, ty); if !st.packed { - let type_align = machine::llalign_of_min(ccx, llty) as u64; + let type_align = type_of::align_of(ccx, ty) as u64; offset = roundup(offset, type_align); } offsets.push(offset); @@ -1002,9 +1016,9 @@ fn build_const_struct(ccx: &CrateContext, st: &Struct, vals: &[ValueRef]) offset += machine::llsize_of_alloc(ccx, val_ty(val)) as u64; } - assert!(offset <= st.size.unwrap()); - if offset != st.size.unwrap() { - cfields.push(padding(ccx, st.size.unwrap() - offset)); + assert!(st.sized && offset <= st.size); + if offset != st.size { + cfields.push(padding(ccx, st.size - offset)); } cfields diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index b27afdb864b..8968c8cc259 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -65,7 +65,7 @@ use middle::trans::glue; use middle::trans::inline; use middle::trans::intrinsic; use middle::trans::machine; -use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_real}; +use middle::trans::machine::{llsize_of, llsize_of_real}; use middle::trans::meth; use middle::trans::monomorphize; use middle::trans::tvec; @@ -394,7 +394,7 @@ pub fn malloc_raw_dyn_managed<'a>( // Grab the TypeRef type of box_ptr_ty. let box_ptr_ty = ty::mk_box(bcx.tcx(), t); let llty = type_of(ccx, box_ptr_ty); - let llalign = C_uint(ccx, llalign_of_min(ccx, llty) as uint); + let llalign = C_uint(ccx, type_of::align_of(ccx, box_ptr_ty) as uint); // Allocate space: let drop_glue = glue::get_drop_glue(ccx, t); @@ -710,14 +710,33 @@ pub fn iter_structural_ty<'r, return cx; } + let (data_ptr, info) = if ty::type_is_sized(cx.tcx(), t) { + (av, None) + } else { + let data = GEPi(cx, av, [0, abi::slice_elt_base]); + let info = GEPi(cx, av, [0, abi::slice_elt_len]); + (Load(cx, data), Some(Load(cx, info))) + }; + let mut cx = cx; match ty::get(t).sty { ty::ty_struct(..) => { let repr = adt::represent_type(cx.ccx(), t); expr::with_field_tys(cx.tcx(), t, None, |discr, field_tys| { for (i, field_ty) in field_tys.iter().enumerate() { - let llfld_a = adt::trans_field_ptr(cx, &*repr, av, discr, i); - cx = f(cx, llfld_a, field_ty.mt.ty); + let field_ty = field_ty.mt.ty; + let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, discr, i); + + let val = if ty::type_is_sized(cx.tcx(), field_ty) { + llfld_a + } else { + let boxed_ty = ty::mk_open(cx.tcx(), field_ty); + let scratch = datum::rvalue_scratch_datum(cx, boxed_ty, "__fat_ptr_iter"); + Store(cx, llfld_a, GEPi(cx, scratch.val, [0, abi::slice_elt_base])); + Store(cx, info.unwrap(), GEPi(cx, scratch.val, [0, abi::slice_elt_len])); + scratch.val + }; + cx = f(cx, val, field_ty); } }) } @@ -725,19 +744,19 @@ pub fn iter_structural_ty<'r, let repr = adt::represent_type(cx.ccx(), t); let upvars = ty::unboxed_closure_upvars(cx.tcx(), def_id); for (i, upvar) in upvars.iter().enumerate() { - let llupvar = adt::trans_field_ptr(cx, &*repr, av, 0, i); + let llupvar = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i); cx = f(cx, llupvar, upvar.ty); } } ty::ty_vec(_, Some(n)) => { - let (base, len) = tvec::get_fixed_base_and_len(cx, av, n); + let (base, len) = tvec::get_fixed_base_and_len(cx, data_ptr, n); let unit_ty = ty::sequence_element_type(cx.tcx(), t); cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f); } ty::ty_tup(ref args) => { let repr = adt::represent_type(cx.ccx(), t); for (i, arg) in args.iter().enumerate() { - let llfld_a = adt::trans_field_ptr(cx, &*repr, av, 0, i); + let llfld_a = adt::trans_field_ptr(cx, &*repr, data_ptr, 0, i); cx = f(cx, llfld_a, *arg); } } @@ -781,7 +800,7 @@ pub fn iter_structural_ty<'r, let variant_cx = iter_variant(variant_cx, &*repr, - av, + data_ptr, &**variant, substs, |x,y,z| f(x,y,z)); @@ -968,7 +987,7 @@ pub fn invoke<'a>( // FIXME(15064) Lang item methods may (in the reflect case) not have proper // types, so doing an attribute lookup will fail. let attributes = if is_lang_item { - Vec::new() + llvm::AttrBuilder::new() } else { get_fn_llvm_attributes(bcx.ccx(), fn_ty) }; @@ -1158,7 +1177,7 @@ pub fn memcpy_ty(bcx: &Block, dst: ValueRef, src: ValueRef, t: ty::t) { if ty::type_is_structural(t) { let llty = type_of::type_of(ccx, t); let llsz = llsize_of(ccx, llty); - let llalign = llalign_of_min(ccx, llty); + let llalign = type_of::align_of(ccx, t); call_memcpy(bcx, dst, src, llsz, llalign as u32); } else { store_ty(bcx, Load(bcx, src), dst, t); @@ -1169,9 +1188,7 @@ pub fn zero_mem(cx: &Block, llptr: ValueRef, t: ty::t) { if cx.unreachable.get() { return; } let _icx = push_ctxt("zero_mem"); let bcx = cx; - let ccx = cx.ccx(); - let llty = type_of::type_of(ccx, t); - memzero(&B(bcx), llptr, llty); + memzero(&B(bcx), llptr, t); } // Always use this function instead of storing a zero constant to the memory @@ -1179,10 +1196,12 @@ pub fn zero_mem(cx: &Block, llptr: ValueRef, t: ty::t) { // allocation for large data structures, and the generated code will be // awful. (A telltale sign of this is large quantities of // `mov [byte ptr foo],0` in the generated code.) -fn memzero(b: &Builder, llptr: ValueRef, ty: Type) { +fn memzero(b: &Builder, llptr: ValueRef, ty: ty::t) { let _icx = push_ctxt("memzero"); let ccx = b.ccx; + let llty = type_of::type_of(ccx, ty); + let intrinsic_key = match ccx.sess().targ_cfg.arch { X86 | Arm | Mips | Mipsel => "llvm.memset.p0i8.i32", X86_64 => "llvm.memset.p0i8.i64" @@ -1191,8 +1210,8 @@ fn memzero(b: &Builder, llptr: ValueRef, ty: Type) { let llintrinsicfn = ccx.get_intrinsic(&intrinsic_key); let llptr = b.pointercast(llptr, Type::i8(ccx).ptr_to()); let llzeroval = C_u8(ccx, 0); - let size = machine::llsize_of(ccx, ty); - let align = C_i32(ccx, llalign_of_min(ccx, ty) as i32); + let size = machine::llsize_of(ccx, llty); + let align = C_i32(ccx, type_of::align_of(ccx, ty) as i32); let volatile = C_bool(ccx, false); b.call(llintrinsicfn, [llptr, llzeroval, size, align, volatile], None); } @@ -1223,13 +1242,14 @@ pub fn alloca_no_lifetime(cx: &Block, ty: Type, name: &str) -> ValueRef { Alloca(cx, ty, name) } -pub fn alloca_zeroed(cx: &Block, ty: Type, name: &str) -> ValueRef { +pub fn alloca_zeroed(cx: &Block, ty: ty::t, name: &str) -> ValueRef { + let llty = type_of::type_of(cx.ccx(), ty); if cx.unreachable.get() { unsafe { - return llvm::LLVMGetUndef(ty.ptr_to().to_ref()); + return llvm::LLVMGetUndef(llty.ptr_to().to_ref()); } } - let p = alloca_no_lifetime(cx, ty, name); + let p = alloca_no_lifetime(cx, llty, name); let b = cx.fcx.ccx.builder(); b.position_before(cx.fcx.alloca_insert_pt.get().unwrap()); memzero(&b, p, ty); @@ -1648,7 +1668,8 @@ fn copy_unboxed_closure_args_to_allocas<'a>( for j in range(0, args.len()) { let tuple_element_type = untupled_arg_types[j]; let tuple_element_datum = - tuple_datum.get_element(tuple_element_type, + tuple_datum.get_element(bcx, + tuple_element_type, |llval| GEPi(bcx, llval, [0, j])); let tuple_element_datum = tuple_element_datum.to_expr_datum(); let tuple_element_datum = diff --git a/src/librustc/middle/trans/callee.rs b/src/librustc/middle/trans/callee.rs index 1283cc19528..7566cfbac56 100644 --- a/src/librustc/middle/trans/callee.rs +++ b/src/librustc/middle/trans/callee.rs @@ -970,6 +970,7 @@ fn trans_args_under_call_abi<'a>( let repr_ptr = &*repr; for i in range(0, field_types.len()) { let arg_datum = tuple_lvalue_datum.get_element( + bcx, *field_types.get(i), |srcval| { adt::trans_field_ptr(bcx, repr_ptr, srcval, 0, i) diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index f0876442ff5..05528d2b3d8 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -74,6 +74,9 @@ pub fn type_is_immediate(ccx: &CrateContext, ty: ty::t) -> bool { if simple && !ty::type_is_fat_ptr(tcx, ty) { return true; } + if !ty::type_is_sized(tcx, ty) { + return false; + } match ty::get(ty).sty { ty::ty_bot => true, ty::ty_struct(..) | ty::ty_enum(..) | ty::ty_tup(..) | diff --git a/src/librustc/middle/trans/consts.rs b/src/librustc/middle/trans/consts.rs index e65a10b3bb2..b3798c9f84d 100644 --- a/src/librustc/middle/trans/consts.rs +++ b/src/librustc/middle/trans/consts.rs @@ -116,7 +116,7 @@ fn const_vec(cx: &CrateContext, e: &ast::Expr, (v, llunitty, inlineable.iter().fold(true, |a, &b| a && b)) } -pub fn const_addr_of(cx: &CrateContext, cv: ValueRef) -> ValueRef { +pub fn const_addr_of(cx: &CrateContext, cv: ValueRef, mutbl: ast::Mutability) -> ValueRef { unsafe { let gv = "const".with_c_str(|name| { llvm::LLVMAddGlobal(cx.llmod, val_ty(cv).to_ref(), name) @@ -279,7 +279,7 @@ pub fn const_expr(cx: &CrateContext, e: &ast::Expr, is_local: bool) -> (ValueRef } _ => cx.sess().span_bug(e.span, format!("unimplemented type in const unsize: {}", - ty_to_str(cx.tcx(), ty)).as_slice()) + ty_to_string(cx.tcx(), ty)).as_slice()) } } _ => { @@ -455,7 +455,7 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr, _ => cx.sess().span_bug(base.span, format!("index-expr base must be a vector \ or string type, found {}", - ty_to_str(cx.tcx(), bt)).as_slice()) + ty_to_string(cx.tcx(), bt)).as_slice()) }, ty::ty_rptr(_, mt) => match ty::get(mt.ty).sty { ty::ty_vec(_, Some(u)) => { @@ -464,12 +464,12 @@ fn const_expr_unadjusted(cx: &CrateContext, e: &ast::Expr, _ => cx.sess().span_bug(base.span, format!("index-expr base must be a vector \ or string type, found {}", - ty_to_str(cx.tcx(), bt)).as_slice()) + ty_to_string(cx.tcx(), bt)).as_slice()) }, _ => cx.sess().span_bug(base.span, format!("index-expr base must be a vector \ or string type, found {}", - ty_to_str(cx.tcx(), bt)).as_slice()) + ty_to_string(cx.tcx(), bt)).as_slice()) }; let len = llvm::LLVMConstIntGetZExtValue(len) as u64; diff --git a/src/librustc/middle/trans/controlflow.rs b/src/librustc/middle/trans/controlflow.rs index 7a1864448e2..9ec52341348 100644 --- a/src/librustc/middle/trans/controlflow.rs +++ b/src/librustc/middle/trans/controlflow.rs @@ -497,7 +497,7 @@ pub fn trans_fail<'a>( let filename = C_str_slice(ccx, filename); let line = C_int(ccx, loc.line as int); let expr_file_line_const = C_struct(ccx, &[v_str, filename, line], false); - let expr_file_line = consts::const_addr_of(ccx, expr_file_line_const); + let expr_file_line = consts::const_addr_of(ccx, expr_file_line_const, ast::MutImmutable); let args = vec!(expr_file_line); let did = langcall(bcx, Some(sp), "", FailFnLangItem); let bcx = callee::trans_lang_call(bcx, @@ -525,7 +525,7 @@ pub fn trans_fail_bounds_check<'a>( let filename = C_str_slice(ccx, filename); let line = C_int(ccx, loc.line as int); let file_line_const = C_struct(ccx, &[filename, line], false); - let file_line = consts::const_addr_of(ccx, file_line_const); + let file_line = consts::const_addr_of(ccx, file_line_const, ast::MutImmutable); let args = vec!(file_line, index, len); let did = langcall(bcx, Some(sp), "", FailBoundsCheckFnLangItem); let bcx = callee::trans_lang_call(bcx, diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index b7803d404b5..2882eaf10be 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -15,6 +15,7 @@ use llvm::ValueRef; use middle::trans::base::*; +use middle::trans::build::Load; use middle::trans::common::*; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; @@ -119,10 +120,10 @@ pub fn lvalue_scratch_datum<'a, A>(bcx: &'a Block<'a>, * does not dominate the end of `scope`. */ - let llty = type_of::type_of(bcx.ccx(), ty); let scratch = if zero { - alloca_zeroed(bcx, llty, name) + alloca_zeroed(bcx, ty, name) } else { + let llty = type_of::type_of(bcx.ccx(), ty); alloca(bcx, llty, name) }; @@ -524,7 +525,7 @@ impl Datum { } _ => bcx.tcx().sess.bug( format!("Unexpected unsized type in get_element: {}", - bcx.ty_to_str(self.ty)).as_slice()) + bcx.ty_to_string(self.ty)).as_slice()) }; Datum { val: val, diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index 31b31224464..566f71220b0 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -56,10 +56,11 @@ This file consists of three conceptual sections: ## Recursive Types Some kinds of types, such as structs and enums can be recursive. That means that -the type definition of some type X refers to some other type which in turn (transitively) -refers to X. This introduces cycles into the type referral graph. A naive algorithm doing -an on-demand, depth-first traversal of this graph when describing types, can get trapped -in an endless loop when it reaches such a cycle. +the type definition of some type X refers to some other type which in turn +(transitively) refers to X. This introduces cycles into the type referral graph. +A naive algorithm doing an on-demand, depth-first traversal of this graph when +describing types, can get trapped in an endless loop when it reaches such a +cycle. For example, the following simple type for a singly-linked list... @@ -2798,25 +2799,33 @@ fn subroutine_type_metadata(cx: &CrateContext, false); } +// FIXME(1563) This is all a bit of a hack because 'trait pointer' is an ill- +// defined concept. For the case of an actual trait pointer (i.e., Box, +// &Trait), trait_object_type should be the whole thing (e.g, Box) and +// trait_type should be the actual trait (e.g., Trait). Where the trait is part +// of a DST struct, there is no trait_object_type and the results of this +// function will be a little bit weird. fn trait_pointer_metadata(cx: &CrateContext, - trait_object_type: ty::t, + trait_type: ty::t, + trait_object_type: Option, unique_type_id: UniqueTypeId) -> DIType { // The implementation provided here is a stub. It makes sure that the trait // type is assigned the correct name, size, namespace, and source location. // But it does not describe the trait's methods. - let def_id = match ty::get(trait_object_type).sty { + let def_id = match ty::get(trait_type).sty { ty::ty_trait(box ty::TyTrait { def_id, .. }) => def_id, _ => { - let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_object_type); + let pp_type_name = ppaux::ty_to_string(cx.tcx(), trait_type); cx.sess().bug(format!("debuginfo: Unexpected trait-object type in \ trait_pointer_metadata(): {}", pp_type_name.as_slice()).as_slice()); } }; - let trait_pointer_type_name = + let trait_object_type = trait_object_type.unwrap_or(trait_type); + let trait_type_name = compute_debuginfo_type_name(cx, trait_object_type, false); let (containing_scope, _) = get_namespace_and_span_for_item(cx, def_id); @@ -2824,8 +2833,8 @@ fn trait_pointer_metadata(cx: &CrateContext, let trait_llvm_type = type_of::type_of(cx, trait_object_type); composite_type_metadata(cx, - trait_pointer_llvm_type, - trait_pointer_type_name.as_slice(), + trait_llvm_type, + trait_type_name.as_slice(), unique_type_id, [], containing_scope, @@ -2897,7 +2906,7 @@ fn type_metadata(cx: &CrateContext, ty::ty_str => fixed_vec_metadata(cx, unique_type_id, ty::mk_i8(), 0, usage_site_span), ty::ty_trait(..) => { MetadataCreationResult::new( - trait_pointer_metadata(cx, t, unique_type_id), + trait_pointer_metadata(cx, t, None, unique_type_id), false) } ty::ty_uniq(ty) | ty::ty_ptr(ty::mt{ty, ..}) | ty::ty_rptr(_, ty::mt{ty, ..}) => { @@ -2910,7 +2919,7 @@ fn type_metadata(cx: &CrateContext, } ty::ty_trait(..) => { MetadataCreationResult::new( - trait_pointer_metadata(cx, ty, unique_type_id), + trait_pointer_metadata(cx, ty, Some(t), unique_type_id), false) } _ => { @@ -3698,7 +3707,7 @@ fn push_debuginfo_type_name(cx: &CrateContext, push_debuginfo_type_name(cx, inner_type, true, output); }, - ty::ty_vec(ty::mt { ty: inner_type, .. }, optional_length) => { + ty::ty_vec(inner_type, optional_length) => { output.push_char('['); push_debuginfo_type_name(cx, inner_type, true, output); @@ -3811,6 +3820,7 @@ fn push_debuginfo_type_name(cx: &CrateContext, } ty::ty_err | ty::ty_infer(_) | + ty::ty_open(_) | ty::ty_param(_) => { cx.sess().bug(format!("debuginfo: Trying to create type name for \ unexpected type: {}", ppaux::ty_to_string(cx.tcx(), t)).as_slice()); diff --git a/src/librustc/middle/trans/expr.rs b/src/librustc/middle/trans/expr.rs index 657cd72c255..5f9788d707a 100644 --- a/src/librustc/middle/trans/expr.rs +++ b/src/librustc/middle/trans/expr.rs @@ -71,7 +71,7 @@ use middle::typeck::MethodCall; use util::common::indenter; use util::ppaux::Repr; use util::nodemap::NodeMap; -use middle::trans::machine::{llalign_of_min, llsize_of, llsize_of_alloc}; +use middle::trans::machine::{llsize_of, llsize_of_alloc}; use middle::trans::type_::Type; use syntax::ast; @@ -202,8 +202,11 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, }; if autoderefs > 0 { + let lval = unpack_datum!(bcx, + datum.to_lvalue_datum(bcx, "auto_deref", expr.id)); + datum = unpack_datum!( - bcx, deref_multiple(bcx, expr, datum, autoderefs)); + bcx, deref_multiple(bcx, expr, lval.to_expr_datum(), autoderefs)); } match adj.autoref { @@ -266,35 +269,42 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, -> DatumBlock<'a, Expr> { if !ty::type_is_sized(bcx.tcx(), datum.ty) { debug!("Taking address of unsized type {}", - bcx.ty_to_str(datum.ty)); + bcx.ty_to_string(datum.ty)); ref_fat_ptr(bcx, expr, datum) } else { debug!("Taking address of sized type {}", - bcx.ty_to_str(datum.ty)); + bcx.ty_to_string(datum.ty)); auto_ref(bcx, datum, expr) } } // Retrieve the information we are losing (making dynamic) in an unsizing // adjustment. + // When making a dtor, we need to do different things depending on the + // ownership of the object.. mk_ty is a function for turning unsized_type + // into a type to be destructed. If we want to end up with a Box pointer, + // then mk_ty should make a Box pointer (T -> Box), if we want a + // borrowed reference then it should be T -> &T. fn unsized_info<'a>(bcx: &'a Block<'a>, kind: &ty::UnsizeKind, id: ast::NodeId, - sized_ty: ty::t) -> ValueRef { + unsized_ty: ty::t, + mk_ty: |ty::t| -> ty::t) -> ValueRef { match kind { &ty::UnsizeLength(len) => C_uint(bcx.ccx(), len), - &ty::UnsizeStruct(box ref k, tp_index) => match ty::get(sized_ty).sty { + &ty::UnsizeStruct(box ref k, tp_index) => match ty::get(unsized_ty).sty { ty::ty_struct(_, ref substs) => { - let ty_substs = substs.types.get_vec(subst::TypeSpace); - let sized_ty = ty_substs.get(tp_index); - unsized_info(bcx, k, id, *sized_ty) + let ty_substs = substs.types.get_slice(subst::TypeSpace); + // The dtor for a field treats it like a value, so mk_ty + // should just be the identity function. + unsized_info(bcx, k, id, ty_substs[tp_index], |t| t) } _ => bcx.sess().bug(format!("UnsizeStruct with bad sty: {}", - bcx.ty_to_str(sized_ty)).as_slice()) + bcx.ty_to_string(unsized_ty)).as_slice()) }, &ty::UnsizeVtable(..) => PointerCast(bcx, - meth::vtable_ptr(bcx, id, sized_ty), + meth::vtable_ptr(bcx, id, mk_ty(unsized_ty)), Type::vtable_ptr(bcx.ccx())) } } @@ -320,7 +330,16 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, &ty::UnsizeVtable(..) => |_bcx, val| PointerCast(bcx, val, Type::i8p(bcx.ccx())) }; - let info = |bcx, _val| unsized_info(bcx, k, expr.id, datum_ty); + let info = |bcx, _val| unsized_info(bcx, + k, + expr.id, + ty::deref_or_dont(datum_ty), + |t| ty::mk_rptr(tcx, + ty::ReStatic, + ty::mt{ + ty: t, + mutbl: ast::MutImmutable + })); into_fat_ptr(bcx, expr, datum, dest_ty, base, info) } @@ -415,21 +434,26 @@ fn apply_adjustments<'a>(bcx: &'a Block<'a>, let unboxed_ty = match ty::get(datum_ty).sty { ty::ty_uniq(t) => t, _ => bcx.sess().bug(format!("Expected ty_uniq, found {}", - bcx.ty_to_str(datum_ty)).as_slice()) + bcx.ty_to_string(datum_ty)).as_slice()) }; let result_ty = ty::mk_uniq(tcx, ty::unsize_ty(tcx, unboxed_ty, k, expr.span)); let lval = unpack_datum!(bcx, datum.to_lvalue_datum(bcx, "unsize_unique_expr", expr.id)); - let scratch = rvalue_scratch_datum(bcx, result_ty, "__fat_ptr"); + let scratch = rvalue_scratch_datum(bcx, result_ty, "__uniq_fat_ptr"); let llbox_ty = type_of::type_of(bcx.ccx(), datum_ty); let base = PointerCast(bcx, get_dataptr(bcx, scratch.val), llbox_ty.ptr_to()); bcx = lval.store_to(bcx, base); - let info = unsized_info(bcx, k, expr.id, unboxed_ty); + let info = unsized_info(bcx, k, expr.id, unboxed_ty, |t| ty::mk_uniq(tcx, t)); Store(bcx, info, get_len(bcx, scratch.val)); + let scratch = unpack_datum!(bcx, + scratch.to_expr_datum().to_lvalue_datum(bcx, + "fresh_uniq_fat_ptr", + expr.id)); + DatumBlock::new(bcx, scratch.to_expr_datum()) } @@ -550,8 +574,8 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>, ast::ExprField(ref base, ident, _) => { trans_rec_field(bcx, &**base, ident.node) } - ast::ExprIndex(base, idx) => { - trans_index(bcx, expr.span, &**base, &**idx, MethodCall::expr(expr.id)) + ast::ExprIndex(ref base, ref idx) => { + trans_index(bcx, expr, &**base, &**idx, MethodCall::expr(expr.id)) } ast::ExprBox(_, ref contents) => { // Special case for `Box` and `Gc` @@ -559,18 +583,24 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>, let contents_ty = expr_ty(bcx, &**contents); match ty::get(box_ty).sty { ty::ty_uniq(..) => { - match contents.node { - ast::ExprRepeat(..) | ast::ExprVec(..) => { - // Special case for owned vectors. - fcx.push_ast_cleanup_scope(contents.id); - let datum = unpack_datum!( - bcx, tvec::trans_uniq_vec(bcx, expr, &**contents)); - bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id); - DatumBlock::new(bcx, datum) - } - _ => { - trans_uniq_expr(bcx, box_ty, &**contents, contents_ty) - } + let is_vec = match contents.node { + ast::ExprRepeat(..) | ast::ExprVec(..) => true, + ast::ExprLit(lit) => match lit.node { + ast::LitStr(..) => true, + _ => false + }, + _ => false + }; + + if is_vec { + // Special case for owned vectors. + fcx.push_ast_cleanup_scope(contents.id); + let datum = unpack_datum!( + bcx, tvec::trans_uniq_vec(bcx, expr, &**contents)); + bcx = fcx.pop_and_trans_ast_cleanup_scope(bcx, contents.id); + DatumBlock::new(bcx, datum) + } else { + trans_uniq_expr(bcx, box_ty, &**contents, contents_ty) } } ty::ty_box(..) => { @@ -639,7 +669,6 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>, if ty::type_is_sized(bcx.tcx(), d.ty) { DatumBlock { datum: d.to_expr_datum(), bcx: bcx } } else { - debug!("nrc: {}", bcx.ty_to_str(d.ty)) let scratch = rvalue_scratch_datum(bcx, ty::mk_open(bcx.tcx(), d.ty), ""); Store(bcx, d.val, get_dataptr(bcx, scratch.val)); let info = Load(bcx, get_len(bcx, base_datum.val)); @@ -652,7 +681,7 @@ fn trans_rec_field<'a>(bcx: &'a Block<'a>, } fn trans_index<'a>(bcx: &'a Block<'a>, - sp: codemap::Span, + index_expr: &ast::Expr, base: &ast::Expr, idx: &ast::Expr, method_call: MethodCall) @@ -1326,7 +1355,8 @@ pub fn trans_adt<'a>(mut bcx: &'a Block<'a>, let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base")); for &(i, t) in base.fields.iter() { let datum = base_datum.get_element( - t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i)); + bcx, t, |srcval| adt::trans_field_ptr(bcx, &*repr, srcval, discr, i)); + assert!(ty::type_is_sized(bcx.tcx(), datum.ty)); let dest = adt::trans_field_ptr(bcx, &*repr, addr, discr, i); bcx = datum.store_to(bcx, dest); } @@ -1348,21 +1378,6 @@ pub fn trans_adt<'a>(mut bcx: &'a Block<'a>, fcx.schedule_drop_mem(scope, dest, e_ty); } - for base in optbase.iter() { - // FIXME #6573: is it sound to use the destination's repr on the base? - // And, would it ever be reasonable to be here with discr != 0? - let base_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &*base.expr, "base")); - for &(i, t) in base.fields.iter() { - let datum = base_datum.get_element( - bcx, - t, - |srcval| adt::trans_field_ptr(bcx, repr, srcval, discr, i)); - assert!(ty::type_is_sized(bcx.tcx(), datum.ty)); - let dest = adt::trans_field_ptr(bcx, repr, addr, discr, i); - bcx = datum.store_to(bcx, dest); - } - } - adt::trans_set_discr(bcx, &*repr, addr, discr); fcx.pop_custom_cleanup_scope(custom_cleanup_scope); @@ -1448,9 +1463,10 @@ fn trans_uniq_expr<'a>(bcx: &'a Block<'a>, -> DatumBlock<'a, Expr> { let _icx = push_ctxt("trans_uniq_expr"); let fcx = bcx.fcx; + assert!(ty::type_is_sized(bcx.tcx(), contents_ty)); let llty = type_of::type_of(bcx.ccx(), contents_ty); let size = llsize_of(bcx.ccx(), llty); - let align = C_uint(bcx.ccx(), llalign_of_min(bcx.ccx(), llty) as uint); + let align = C_uint(bcx.ccx(), type_of::align_of(bcx.ccx(), contents_ty) as uint); let llty_ptr = llty.ptr_to(); let Result { bcx, val } = malloc_raw_dyn(bcx, llty_ptr, box_ty, size, align); // Unique boxes do not allocate for zero-size types. The standard library @@ -1499,7 +1515,7 @@ fn trans_addr_of<'a>(bcx: &'a Block<'a>, match ty::get(sub_datum.ty).sty { ty::ty_open(_) => { // Opened DST value, close to a fat pointer - debug!("Closing fat pointer {}", bcx.ty_to_str(sub_datum.ty)); + debug!("Closing fat pointer {}", bcx.ty_to_string(sub_datum.ty)); let scratch = rvalue_scratch_datum(bcx, ty::close_type(bcx.tcx(), sub_datum.ty), diff --git a/src/librustc/middle/trans/glue.rs b/src/librustc/middle/trans/glue.rs index 2994378f91c..56841cd4044 100644 --- a/src/librustc/middle/trans/glue.rs +++ b/src/librustc/middle/trans/glue.rs @@ -19,6 +19,7 @@ use llvm::{ValueRef, True, get_param}; use llvm; use middle::lang_items::{FreeFnLangItem, ExchangeFreeFnLangItem}; use middle::subst; +use middle::subst::Subst; use middle::trans::adt; use middle::trans::base::*; use middle::trans::build::*; @@ -26,12 +27,13 @@ use middle::trans::callee; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; use middle::trans::common::*; +use middle::trans::datum; use middle::trans::expr; use middle::trans::machine::*; use middle::trans::reflect; use middle::trans::tvec; use middle::trans::type_::Type; -use middle::trans::type_of::{type_of, sizing_type_of}; +use middle::trans::type_of::{type_of, sizing_type_of, align_of}; use middle::ty; use util::ppaux::ty_to_short_str; use util::ppaux; @@ -51,24 +53,33 @@ pub fn trans_free<'a>(cx: &'a Block<'a>, v: ValueRef) -> &'a Block<'a> { Some(expr::Ignore)).bcx } -pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64, - align: u64) -> &'a Block<'a> { +fn trans_exchange_free_internal<'a>(cx: &'a Block<'a>, v: ValueRef, size: ValueRef, + align: ValueRef) -> &'a Block<'a> { let _icx = push_ctxt("trans_exchange_free"); let ccx = cx.ccx(); callee::trans_lang_call(cx, langcall(cx, None, "", ExchangeFreeFnLangItem), - [PointerCast(cx, v, Type::i8p(ccx)), C_uint(ccx, size as uint), C_uint(ccx, align as uint)], + [PointerCast(cx, v, Type::i8p(ccx)), size, align], Some(expr::Ignore)).bcx } +pub fn trans_exchange_free<'a>(cx: &'a Block<'a>, v: ValueRef, size: u64, + align: u64) -> &'a Block<'a> { + trans_exchange_free_internal(cx, + v, + C_uint(cx.ccx(), size as uint), + C_uint(cx.ccx(), align as uint)) +} + pub fn trans_exchange_free_ty<'a>(bcx: &'a Block<'a>, ptr: ValueRef, content_ty: ty::t) -> &'a Block<'a> { + assert!(ty::type_is_sized(bcx.ccx().tcx(), content_ty)); let sizing_type = sizing_type_of(bcx.ccx(), content_ty); let content_size = llsize_of_alloc(bcx.ccx(), sizing_type); // `Box` does not allocate. if content_size != 0 { - let content_align = llalign_of_min(bcx.ccx(), sizing_type); + let content_align = align_of(bcx.ccx(), content_ty); trans_exchange_free(bcx, ptr, content_size, content_align) } else { bcx @@ -91,6 +102,11 @@ pub fn take_ty<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) pub fn get_drop_glue_type(ccx: &CrateContext, t: ty::t) -> ty::t { let tcx = ccx.tcx(); + // Even if there is no dtor for t, there might be one deeper down and we + // might need to pass in the vtable ptr. + if !ty::type_is_sized(tcx, t) { + return t + } if !ty::type_needs_drop(tcx, t) { return ty::mk_i8(); } @@ -139,13 +155,21 @@ pub fn drop_ty_immediate<'a>(bcx: &'a Block<'a>, v: ValueRef, t: ty::t) } pub fn get_drop_glue(ccx: &CrateContext, t: ty::t) -> ValueRef { + debug!("make drop glue for {}", ppaux::ty_to_string(ccx.tcx(), t)); let t = get_drop_glue_type(ccx, t); + debug!("drop glue type {}", ppaux::ty_to_string(ccx.tcx(), t)); match ccx.drop_glues.borrow().find(&t) { Some(&glue) => return glue, _ => { } } - let llfnty = Type::glue_fn(ccx, type_of(ccx, t).ptr_to()); + let llty = if ty::type_is_sized(ccx.tcx(), t) { + type_of(ccx, t).ptr_to() + } else { + type_of(ccx, ty::mk_uniq(ccx.tcx(), t)).ptr_to() + }; + + let llfnty = Type::glue_fn(ccx, llty); let glue = declare_generic_glue(ccx, t, llfnty, "drop"); ccx.drop_glues.borrow_mut().insert(t, glue); @@ -208,7 +232,13 @@ fn trans_struct_drop_flag<'a>(mut bcx: &'a Block<'a>, substs: &subst::Substs) -> &'a Block<'a> { let repr = adt::represent_type(bcx.ccx(), t); - let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, v0)); + let struct_data = if ty::type_is_sized(bcx.tcx(), t) { + v0 + } else { + let llval = GEPi(bcx, v0, [0, abi::slice_elt_base]); + Load(bcx, llval) + }; + let drop_flag = unpack_datum!(bcx, adt::trans_drop_flag_ptr(bcx, &*repr, struct_data)); with_cond(bcx, load_ty(bcx, drop_flag.val, ty::mk_bool()), |cx| { trans_struct_drop(cx, t, v0, dtor_did, class_did, substs) }) @@ -227,13 +257,31 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>, let dtor_addr = get_res_dtor(bcx.ccx(), dtor_did, t, class_did, substs); - // The second argument is the "self" argument for drop + // The first argument is the "self" argument for drop let params = unsafe { let ty = Type::from_ref(llvm::LLVMTypeOf(dtor_addr)); ty.element_type().func_params() }; - adt::fold_variants(bcx, &*repr, v0, |variant_cx, st, value| { + let fty = ty::lookup_item_type(bcx.tcx(), dtor_did).ty.subst(bcx.tcx(), substs); + let self_ty = match ty::get(fty).sty { + ty::ty_bare_fn(ref f) => { + assert!(f.sig.inputs.len() == 1); + f.sig.inputs[0] + } + _ => bcx.sess().bug(format!("Expected function type, found {}", + bcx.ty_to_string(fty)).as_slice()) + }; + + let (struct_data, info) = if ty::type_is_sized(bcx.tcx(), t) { + (v0, None) + } else { + let data = GEPi(bcx, v0, [0, abi::slice_elt_base]); + let info = GEPi(bcx, v0, [0, abi::slice_elt_len]); + (Load(bcx, data), Some(Load(bcx, info))) + }; + + adt::fold_variants(bcx, &*repr, struct_data, |variant_cx, st, value| { // Be sure to put all of the fields into a scope so we can use an invoke // instruction to call the user destructor but still call the field // destructors if the user destructor fails. @@ -242,7 +290,22 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>, // Class dtors have no explicit args, so the params should // just consist of the environment (self). assert_eq!(params.len(), 1); - let self_arg = PointerCast(variant_cx, value, *params.get(0)); + let self_arg = if ty::type_is_fat_ptr(bcx.tcx(), self_ty) { + // The dtor expects a fat pointer, so make one, even if we have to fake it. + let boxed_ty = ty::mk_open(bcx.tcx(), t); + let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_self"); + Store(bcx, value, GEPi(bcx, scratch.val, [0, abi::slice_elt_base])); + Store(bcx, + // If we just had a thin pointer, make a fat pointer by sticking + // null where we put the unsizing info. This works because t + // is a sized type, so we will only unpack the fat pointer, never + // use the fake info. + info.unwrap_or(C_null(Type::i8p(bcx.ccx()))), + GEPi(bcx, scratch.val, [0, abi::slice_elt_len])); + PointerCast(variant_cx, scratch.val, *params.get(0)) + } else { + PointerCast(variant_cx, value, *params.get(0)) + }; let args = vec!(self_arg); // Add all the fields as a value which needs to be cleaned at the end of @@ -250,19 +313,84 @@ fn trans_struct_drop<'a>(bcx: &'a Block<'a>, // the order in which fields get dropped. for (i, ty) in st.fields.iter().enumerate().rev() { let llfld_a = adt::struct_field_ptr(variant_cx, &*st, value, i, false); + + let val = if ty::type_is_sized(bcx.tcx(), *ty) { + llfld_a + } else { + let boxed_ty = ty::mk_open(bcx.tcx(), *ty); + let scratch = datum::rvalue_scratch_datum(bcx, boxed_ty, "__fat_ptr_drop_field"); + Store(bcx, llfld_a, GEPi(bcx, scratch.val, [0, abi::slice_elt_base])); + Store(bcx, info.unwrap(), GEPi(bcx, scratch.val, [0, abi::slice_elt_len])); + scratch.val + }; variant_cx.fcx.schedule_drop_mem(cleanup::CustomScope(field_scope), - llfld_a, *ty); + val, *ty); } let dtor_ty = ty::mk_ctor_fn(variant_cx.tcx(), ast::DUMMY_NODE_ID, [get_drop_glue_type(bcx.ccx(), t)], ty::mk_nil()); - let (_, variant_cx) = invoke(variant_cx, dtor_addr, args, dtor_ty, None); + let (_, variant_cx) = invoke(variant_cx, dtor_addr, args, dtor_ty, None, false); variant_cx.fcx.pop_and_trans_custom_cleanup_scope(variant_cx, field_scope); variant_cx }) } +fn size_and_align_of_dst<'a>(bcx: &'a Block<'a>, t :ty::t, info: ValueRef) -> (ValueRef, ValueRef) { + debug!("calculate size of DST: {}; with lost info: {}", + bcx.ty_to_string(t), bcx.val_to_string(info)); + if ty::type_is_sized(bcx.tcx(), t) { + let sizing_type = sizing_type_of(bcx.ccx(), t); + let size = C_uint(bcx.ccx(), llsize_of_alloc(bcx.ccx(), sizing_type) as uint); + let align = C_uint(bcx.ccx(), align_of(bcx.ccx(), t) as uint); + return (size, align); + } + match ty::get(t).sty { + ty::ty_struct(id, ref substs) => { + let ccx = bcx.ccx(); + // First get the size of all statically known fields. + // Don't use type_of::sizing_type_of because that expects t to be sized. + assert!(!ty::type_is_simd(bcx.tcx(), t)); + let repr = adt::represent_type(ccx, t); + let sizing_type = adt::sizing_type_of(ccx, &*repr, true); + let sized_size = C_uint(ccx, llsize_of_alloc(ccx, sizing_type) as uint); + let sized_align = C_uint(ccx, llalign_of_min(ccx, sizing_type) as uint); + + // Recurse to get the size of the dynamically sized field (must be + // the last field). + let fields = ty::struct_fields(bcx.tcx(), id, substs); + let last_field = fields[fields.len()-1]; + let field_ty = last_field.mt.ty; + let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info); + + // Return the sum of sizes and max of aligns. + let size = Add(bcx, sized_size, unsized_size); + let align = Select(bcx, + ICmp(bcx, llvm::IntULT, sized_align, unsized_align), + sized_align, + unsized_align); + (size, align) + } + ty::ty_trait(..) => { + // info points to the vtable and the second entry in the vtable is the + // dynamic size of the object. + let info = PointerCast(bcx, info, Type::int(bcx.ccx()).ptr_to()); + let size_ptr = GEPi(bcx, info, [1u]); + let align_ptr = GEPi(bcx, info, [2u]); + (Load(bcx, size_ptr), Load(bcx, align_ptr)) + } + ty::ty_vec(unit_ty, None) => { + // The info in this case is the length of the vec, so the size is that + // times the unit size. + let llunit_ty = sizing_type_of(bcx.ccx(), unit_ty); + let unit_size = llsize_of_alloc(bcx.ccx(), llunit_ty); + (Mul(bcx, info, C_uint(bcx.ccx(), unit_size as uint)), C_uint(bcx.ccx(), 8)) + } + _ => bcx.sess().bug(format!("Unexpected unsized type, found {}", + bcx.ty_to_string(t)).as_slice()) + } +} + fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<'a> { // NB: v0 is an *alias* of type t here, not a direct value. let _icx = push_ctxt("make_drop_glue"); @@ -282,7 +410,8 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' ty::ty_trait(..) => { let lluniquevalue = GEPi(bcx, v0, [0, abi::trt_field_box]); // Only drop the value when it is non-null - with_cond(bcx, IsNotNull(bcx, Load(bcx, lluniquevalue)), |bcx| { + let concrete_ptr = Load(bcx, lluniquevalue); + with_cond(bcx, IsNotNull(bcx, concrete_ptr), |bcx| { let dtor_ptr = Load(bcx, GEPi(bcx, v0, [0, abi::trt_field_vtable])); let dtor = Load(bcx, dtor_ptr); Call(bcx, @@ -292,13 +421,21 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' bcx }) } + ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), content_ty) => { + let llval = GEPi(bcx, v0, [0, abi::slice_elt_base]); + let llbox = Load(bcx, llval); + let not_null = IsNotNull(bcx, llbox); + with_cond(bcx, not_null, |bcx| { + let bcx = drop_ty(bcx, v0, content_ty); + let info = GEPi(bcx, v0, [0, abi::slice_elt_len]); + let info = Load(bcx, info); + let (llsize, llalign) = size_and_align_of_dst(bcx, content_ty, info); + trans_exchange_free_internal(bcx, llbox, llsize, llalign) + }) + } _ => { - let llval = if ty::type_is_sized(bcx.tcx(), content_ty) { - v0 - } else { - // The Box is a fat pointer - GEPi(bcx, v0, [0, abi::trt_field_box]) - }; + assert!(ty::type_is_sized(bcx.tcx(), content_ty)); + let llval = v0; let llbox = Load(bcx, llval); let not_null = IsNotNull(bcx, llbox); with_cond(bcx, not_null, |bcx| { @@ -312,7 +449,21 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' let tcx = bcx.tcx(); match ty::ty_dtor(tcx, did) { ty::TraitDtor(dtor, true) => { - trans_struct_drop_flag(bcx, t, v0, dtor, did, substs) + // FIXME(16758) Since the struct is unsized, it is hard to + // find the drop flag (which is at the end of the struct). + // Lets just ignore the flag and pretend everything will be + // OK. + if ty::type_is_sized(bcx.tcx(), t) { + trans_struct_drop_flag(bcx, t, v0, dtor, did, substs) + } else { + // Give the user a heads up that we are doing something + // stupid and dangerous. + bcx.sess().warn(format!("Ignoring drop flag in destructor for {}\ + because the struct is unsized. See issue\ + #16758", + bcx.ty_to_string(t)).as_slice()); + trans_struct_drop(bcx, t, v0, dtor, did, substs) + } } ty::TraitDtor(dtor, false) => { trans_struct_drop(bcx, t, v0, dtor, did, substs) @@ -340,7 +491,23 @@ fn make_drop_glue<'a>(bcx: &'a Block<'a>, v0: ValueRef, t: ty::t) -> &'a Block<' trans_exchange_free(bcx, env, 0, 8) }) } + ty::ty_trait(..) => { + // No need to do a null check here (as opposed to the Box tvec::make_drop_glue_unboxed(bcx, v0, ty), _ => { + assert!(ty::type_is_sized(bcx.tcx(), t)); if ty::type_needs_drop(bcx.tcx(), t) && ty::type_is_structural(t) { iter_structural_ty(bcx, v0, t, drop_ty) @@ -439,7 +606,6 @@ fn declare_generic_glue(ccx: &CrateContext, t: ty::t, llfnty: Type, ccx, t, format!("glue_{}", name).as_slice()); - debug!("{} is for type {}", fn_nm, ppaux::ty_to_string(ccx.tcx(), t)); let llfn = decl_cdecl_fn(ccx, fn_nm.as_slice(), llfnty, ty::mk_nil()); note_unique_llvm_symbol(ccx, fn_nm); return llfn; diff --git a/src/librustc/middle/trans/intrinsic.rs b/src/librustc/middle/trans/intrinsic.rs index 359c8d24f72..7d8e4679ae3 100644 --- a/src/librustc/middle/trans/intrinsic.rs +++ b/src/librustc/middle/trans/intrinsic.rs @@ -119,6 +119,17 @@ pub fn check_intrinsics(ccx: &CrateContext) { "s" }).as_slice()); } + if ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.to) || + ty::type_is_fat_ptr(ccx.tcx(), transmute_restriction.from) { + ccx.sess() + .add_lint(::lint::builtin::TRANSMUTE_FAT_PTR, + transmute_restriction.id, + transmute_restriction.span, + format!("Transmuting fat pointer types; {} to {}.\ + Beware of relying on the compiler's representation", + ty_to_string(ccx.tcx(), transmute_restriction.from), + ty_to_string(ccx.tcx(), transmute_restriction.to))); + } } ccx.sess().abort_if_errors(); } @@ -227,8 +238,7 @@ pub fn trans_intrinsic_call<'a>(mut bcx: &'a Block<'a>, node: ast::NodeId, } (_, "min_align_of") => { let tp_ty = *substs.types.get(FnSpace, 0); - let lltp_ty = type_of::type_of(ccx, tp_ty); - C_uint(ccx, machine::llalign_of_min(ccx, lltp_ty) as uint) + C_uint(ccx, type_of::align_of(ccx, tp_ty) as uint) } (_, "pref_align_of") => { let tp_ty = *substs.types.get(FnSpace, 0); @@ -542,7 +552,7 @@ fn copy_intrinsic(bcx: &Block, allow_overlap: bool, volatile: bool, tp_ty: ty::t, dst: ValueRef, src: ValueRef, count: ValueRef) -> ValueRef { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); - let align = C_i32(ccx, machine::llalign_of_min(ccx, lltp_ty) as i32); + let align = C_i32(ccx, type_of::align_of(ccx, tp_ty) as i32); let size = machine::llsize_of(ccx, lltp_ty); let int_size = machine::llbitsize_of_real(ccx, ccx.int_type); let name = if allow_overlap { @@ -571,7 +581,7 @@ fn memset_intrinsic(bcx: &Block, volatile: bool, tp_ty: ty::t, dst: ValueRef, val: ValueRef, count: ValueRef) -> ValueRef { let ccx = bcx.ccx(); let lltp_ty = type_of::type_of(ccx, tp_ty); - let align = C_i32(ccx, machine::llalign_of_min(ccx, lltp_ty) as i32); + let align = C_i32(ccx, type_of::align_of(ccx, tp_ty) as i32); let size = machine::llsize_of(ccx, lltp_ty); let name = if machine::llbitsize_of_real(ccx, ccx.int_type) == 32 { "llvm.memset.p0i8.i32" diff --git a/src/librustc/middle/trans/meth.rs b/src/librustc/middle/trans/meth.rs index 3dc09040419..83bdcc9dead 100644 --- a/src/librustc/middle/trans/meth.rs +++ b/src/librustc/middle/trans/meth.rs @@ -25,6 +25,7 @@ use middle::trans::datum::*; use middle::trans::expr::{SaveIn, Ignore}; use middle::trans::expr; use middle::trans::glue; +use middle::trans::machine; use middle::trans::monomorphize; use middle::trans::type_::Type; use middle::trans::type_of::*; @@ -40,6 +41,9 @@ use syntax::parse::token; use syntax::{ast, ast_map, visit}; use syntax::ast_util::PostExpansionMethod; +// drop_glue pointer, size, align. +static VTABLE_OFFSET: uint = 3; + /** The main "translation" pass for methods. Generates code for non-monomorphized methods only. Other methods will @@ -450,7 +454,7 @@ pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>, GEPi(bcx, llpair, [0u, abi::trt_field_vtable]), Type::vtable(ccx).ptr_to().ptr_to())); - let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + 1])); + let mptr = Load(bcx, GEPi(bcx, llvtable, [0u, n_method + VTABLE_OFFSET])); let mptr = PointerCast(bcx, mptr, llcallee_ty.ptr_to()); return Callee { @@ -580,9 +584,15 @@ fn get_vtable(bcx: &Block, } }); + let size_ty = sizing_type_of(ccx, self_ty); + let size = machine::llsize_of_alloc(ccx, size_ty); + let ll_size = C_uint(ccx, size as uint); + let align = align_of(ccx, self_ty); + let ll_align = C_uint(ccx, align as uint); + // Generate a destructor for the vtable. let drop_glue = glue::get_drop_glue(ccx, self_ty); - let vtable = make_vtable(ccx, drop_glue, methods); + let vtable = make_vtable(ccx, drop_glue, ll_size, ll_align, methods); ccx.vtables.borrow_mut().insert(hash_id, vtable); vtable @@ -591,11 +601,14 @@ fn get_vtable(bcx: &Block, /// Helper function to declare and initialize the vtable. pub fn make_vtable>(ccx: &CrateContext, drop_glue: ValueRef, + size: ValueRef, + align: ValueRef, ptrs: I) -> ValueRef { let _icx = push_ctxt("meth::make_vtable"); - let components: Vec<_> = Some(drop_glue).move_iter().chain(ptrs).collect(); + let head = vec![drop_glue, size, align]; + let components: Vec<_> = head.move_iter().chain(ptrs).collect(); unsafe { let tbl = C_struct(ccx, components.as_slice(), false); diff --git a/src/librustc/middle/trans/reflect.rs b/src/librustc/middle/trans/reflect.rs index 7b6d3430ae0..11c641f2d75 100644 --- a/src/librustc/middle/trans/reflect.rs +++ b/src/librustc/middle/trans/reflect.rs @@ -66,7 +66,7 @@ impl<'a, 'b> Reflector<'a, 'b> { pub fn c_size_and_align(&mut self, t: ty::t) -> Vec { let tr = type_of(self.bcx.ccx(), t); let s = machine::llsize_of_real(self.bcx.ccx(), tr); - let a = machine::llalign_of_min(self.bcx.ccx(), tr); + let a = align_of(self.bcx.ccx(), t); return vec!(self.c_uint(s as uint), self.c_uint(a as uint)); } @@ -94,7 +94,7 @@ impl<'a, 'b> Reflector<'a, 'b> { ty::MethodTraitItem(ref method) => (*method).clone(), }; let mth_ty = ty::mk_bare_fn(tcx, method.fty.clone()); - debug!("Emit call visit method: visit_{}: {}", ty_name, ty_to_str(tcx, mth_ty)); + debug!("Emit call visit method: visit_{}: {}", ty_name, ty_to_string(tcx, mth_ty)); let v = self.visitor_val; debug!("passing {} args:", args.len()); let mut bcx = self.bcx; @@ -154,8 +154,11 @@ impl<'a, 'b> Reflector<'a, 'b> { // Unfortunately we can't do anything here because at runtime we // pass around the value by pointer (*u8). But unsized pointers are // fat and so we can't just cast them to *u8 and back. So we have - // to work with the pointer directly (see ty_rptr/ty_uniq). See - // ty_struct for where this causes issues. + // to work with the pointer directly (see ty_rptr/ty_uniq). + fail!("Can't reflect unsized type") + } + // FIXME(15049) Reflection for unsized structs. + ty::ty_struct(..) if !ty::type_is_sized(bcx.tcx(), t) => { fail!("Can't reflect unsized type") } @@ -278,12 +281,7 @@ impl<'a, 'b> Reflector<'a, 'b> { // because we cannot reflect unsized types (see note above). We // just pretend the unsized field does not exist and print nothing. // This is sub-optimal. - let len = if ty::type_is_sized(tcx, t) { - fields.len() - } else { - assert!(fields.len() > 0); - fields.len() - 1 - }; + let len = fields.len(); let extra = (vec!( self.c_slice( @@ -294,14 +292,12 @@ impl<'a, 'b> Reflector<'a, 'b> { )).append(self.c_size_and_align(t).as_slice()); self.bracketed("class", extra.as_slice(), |this| { for (i, field) in fields.iter().enumerate() { - if ty::type_is_sized(tcx, field.mt.ty) { - let extra = (vec!( - this.c_uint(i), - this.c_slice(token::get_ident(field.ident)), - this.c_bool(named_fields) - )).append(this.c_mt(&field.mt).as_slice()); - this.visit("class_field", extra.as_slice()); - } + let extra = (vec!( + this.c_uint(i), + this.c_slice(token::get_ident(field.ident)), + this.c_bool(named_fields) + )).append(this.c_mt(&field.mt).as_slice()); + this.visit("class_field", extra.as_slice()); } }) } diff --git a/src/librustc/middle/trans/tvec.rs b/src/librustc/middle/trans/tvec.rs index 0ec18977139..94ca520c533 100644 --- a/src/librustc/middle/trans/tvec.rs +++ b/src/librustc/middle/trans/tvec.rs @@ -17,6 +17,7 @@ use middle::lang_items::StrDupUniqFnLangItem; use middle::trans::base::*; use middle::trans::base; use middle::trans::build::*; +use middle::trans::callee; use middle::trans::cleanup; use middle::trans::cleanup::CleanupMethods; use middle::trans::common::*; @@ -162,7 +163,7 @@ pub fn trans_slice_vec<'a>(bcx: &'a Block<'a>, // Handle the &[...] case: let vt = vec_types_from_expr(bcx, content_expr); let count = elements_required(bcx, content_expr); - debug!(" vt={}, count={:?}", vt.to_str(ccx), count); + debug!(" vt={}, count={:?}", vt.to_string(ccx), count); let llcount = C_uint(ccx, count); let fixed_ty = ty::mk_vec(bcx.tcx(), @@ -173,7 +174,8 @@ pub fn trans_slice_vec<'a>(bcx: &'a Block<'a>, let llfixed = if count == 0 { // Just create a zero-sized alloca to preserve // the non-null invariant of the inner slice ptr - base::arrayalloca(bcx, vt.llunit_ty, llcount) + let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount); + BitCast(bcx, llfixed, llfixed_ty) } else { // Make a fixed-length backing array and allocate it on the stack. let llfixed = base::arrayalloca(bcx, vt.llunit_ty, llcount); @@ -231,26 +233,55 @@ pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>, content_expr: &ast::Expr) -> DatumBlock<'a, Expr> { /*! - * ~[...] and "...".to_string() allocate boxes in the exchange heap and write + * Box<[...]> and "...".to_string() allocate boxes in the exchange heap and write * the array elements into them. */ - debug!("trans_uniq_vec(vstore_expr={})", bcx.expr_to_string(uniq_expr)); + debug!("trans_uniq_vec(uniq_expr={})", bcx.expr_to_string(uniq_expr)); let fcx = bcx.fcx; let ccx = fcx.ccx; + // Handle "".to_string(). + match content_expr.node { + ast::ExprLit(lit) => { + match lit.node { + ast::LitStr(ref s, _) => { + let llptrval = C_cstr(ccx, (*s).clone(), false); + let llptrval = PointerCast(bcx, llptrval, Type::i8p(ccx)); + let llsizeval = C_uint(ccx, s.get().len()); + let typ = ty::mk_uniq(bcx.tcx(), ty::mk_str(bcx.tcx())); + let lldestval = rvalue_scratch_datum(bcx, + typ, + ""); + let alloc_fn = langcall(bcx, + Some(lit.span), + "", + StrDupUniqFnLangItem); + let bcx = callee::trans_lang_call( + bcx, + alloc_fn, + [ llptrval, llsizeval ], + Some(expr::SaveIn(lldestval.val))).bcx; + return DatumBlock::new(bcx, lldestval).to_expr_datumblock(); + } + _ => {} + } + } + _ => {} + } + let vt = vec_types_from_expr(bcx, content_expr); let count = elements_required(bcx, content_expr); - debug!(" vt={}, count={:?}", vt.to_str(ccx), count); + debug!(" vt={}, count={:?}", vt.to_string(ccx), count); let vec_ty = node_id_type(bcx, uniq_expr.id); let unit_sz = nonzero_llsize_of(ccx, type_of::type_of(ccx, vt.unit_ty)); - let fill = Mul(bcx, C_uint(ccx, count), unit_sz); - let alloc = if count < 4u { - Mul(bcx, C_int(ccx, 4), unit_sz) + let llcount = if count < 4u { + C_int(ccx, 4) } else { - fill + C_uint(ccx, count) }; + let alloc = Mul(bcx, llcount, unit_sz); let llty_ptr = type_of::type_of(ccx, vt.unit_ty).ptr_to(); let align = C_uint(ccx, 8); let Result { bcx: bcx, val: dataptr } = malloc_raw_dyn(bcx, @@ -268,7 +299,7 @@ pub fn trans_uniq_vec<'a>(bcx: &'a Block<'a>, dataptr, cleanup::HeapExchange, vt.unit_ty); debug!(" alloc_uniq_vec() returned dataptr={}, len={}", - bcx.val_to_str(dataptr), count); + bcx.val_to_string(dataptr), count); let bcx = write_content(bcx, &vt, uniq_expr, content_expr, SaveIn(dataptr)); diff --git a/src/librustc/middle/trans/type_of.rs b/src/librustc/middle/trans/type_of.rs index 9608672928d..83c792ecf87 100644 --- a/src/librustc/middle/trans/type_of.rs +++ b/src/librustc/middle/trans/type_of.rs @@ -14,6 +14,7 @@ use middle::subst; use middle::trans::adt; use middle::trans::common::*; use middle::trans::foreign; +use middle::trans::machine; use middle::ty; use util::ppaux; use util::ppaux::Repr; @@ -163,7 +164,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { let llsizingty = match ty::get(t).sty { _ if !ty::lltype_is_sized(cx.tcx(), t) => { cx.sess().bug(format!("trying to take the sizing type of {}, an unsized type", - ppaux::ty_to_str(cx.tcx(), t)).as_slice()) + ppaux::ty_to_string(cx.tcx(), t)).as_slice()) } ty::ty_nil | ty::ty_bot => Type::nil(cx), @@ -192,7 +193,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { ty::ty_tup(..) | ty::ty_enum(..) | ty::ty_unboxed_closure(..) => { let repr = adt::represent_type(cx, t); - adt::sizing_type_of(cx, &*repr) + adt::sizing_type_of(cx, &*repr, false) } ty::ty_struct(..) => { @@ -202,7 +203,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { Type::vector(&type_of(cx, et), n as u64) } else { let repr = adt::represent_type(cx, t); - adt::sizing_type_of(cx, &*repr) + adt::sizing_type_of(cx, &*repr, false) } } @@ -212,7 +213,7 @@ pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type { ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => { cx.sess().bug(format!("fictitious type {} in sizing_type_of()", - ppaux::ty_to_str(cx.tcx(), t)).as_slice()) + ppaux::ty_to_string(cx.tcx(), t)).as_slice()) } ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => fail!("unreachable") }; @@ -232,6 +233,14 @@ pub fn arg_type_of(cx: &CrateContext, t: ty::t) -> Type { // NB: If you update this, be sure to update `sizing_type_of()` as well. pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { fn type_of_unsize_info(cx: &CrateContext, t: ty::t) -> Type { + // It is possible to end up here with a sized type. This happens with a + // struct which might be unsized, but is monomorphised to a sized type. + // In this case we'll fake a fat pointer with no unsize info (we use 0). + // However, its still a fat pointer, so we need some type use. + if ty::type_is_sized(cx.tcx(), t) { + return Type::i8p(cx); + } + match ty::get(ty::unsized_part_of_type(cx.tcx(), t)).sty { ty::ty_str | ty::ty_vec(..) => Type::uint_from_ty(cx, ast::TyU), ty::ty_trait(_) => Type::vtable_ptr(cx), @@ -367,7 +376,7 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { } ty::ty_trait(..) => Type::opaque_trait(cx), _ => cx.sess().bug(format!("ty_open with sized type: {}", - ppaux::ty_to_str(cx.tcx(), t)).as_slice()) + ppaux::ty_to_string(cx.tcx(), t)).as_slice()) }, ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"), @@ -395,6 +404,11 @@ pub fn type_of(cx: &CrateContext, t: ty::t) -> Type { return llty; } +pub fn align_of(cx: &CrateContext, t: ty::t) -> u64 { + let llty = sizing_type_of(cx, t); + machine::llalign_of_min(cx, llty) +} + // Want refinements! (Or case classes, I guess pub enum named_ty { a_struct, diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs index 486ed714574..2d3096d13ea 100644 --- a/src/librustc/middle/ty.rs +++ b/src/librustc/middle/ty.rs @@ -302,26 +302,23 @@ pub enum AutoRef { AutoUnsafe(ast::Mutability), } -// Ugly little helper function. The bool in the returned tuple is true if there -// is an 'unsize to trait object' adjustment at the bottom of the adjustment. If -// that is surrounded by an AutoPtr, then we also return the region of the -// AutoPtr (in the third argument). The second bool is true if the adjustment is -// unique. +// Ugly little helper function. The first bool in the returned tuple is true if +// there is an 'unsize to trait object' adjustment at the bottom of the +// adjustment. If that is surrounded by an AutoPtr, then we also return the +// region of the AutoPtr (in the third argument). The second bool is true if the +// adjustment is unique. fn autoref_object_region(autoref: &AutoRef) -> (bool, bool, Option) { - fn unsize_kind_region(k: &UnsizeKind) -> (bool, bool, Option) { + fn unsize_kind_is_object(k: &UnsizeKind) -> bool { match k { - &UnsizeVtable(..) => (true, false, None), - &UnsizeStruct(box ref k, _) => unsize_kind_region(k), - _ => (false, false, None) + &UnsizeVtable(..) => true, + &UnsizeStruct(box ref k, _) => unsize_kind_is_object(k), + _ => false } } match autoref { - &AutoUnsize(ref k) => unsize_kind_region(k), - &AutoUnsizeUniq(ref k) => match k { - &UnsizeVtable(..) => (true, true, None), - _ => (false, false, None) - }, + &AutoUnsize(ref k) => (unsize_kind_is_object(k), false, None), + &AutoUnsizeUniq(ref k) => (unsize_kind_is_object(k), true, None), &AutoPtr(adj_r, _, Some(box ref autoref)) => { let (b, u, r) = autoref_object_region(autoref); if r.is_some() || u { @@ -407,6 +404,8 @@ pub struct TransmuteRestriction { pub from: t, /// The type being transmuted to. pub to: t, + /// NodeIf of the transmute intrinsic. + pub id: ast::NodeId, } /// The data structure to keep track of all the information that typechecker @@ -1765,7 +1764,7 @@ pub fn maybe_walk_ty(ty: t, f: |t| -> bool) { } match get(ty).sty { ty_nil | ty_bot | ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) | - ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_) | ty_err => {} + ty_str | ty_infer(_) | ty_param(_) | ty_unboxed_closure(_, _) | ty_err => {} ty_box(ty) | ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f), ty_ptr(ref tm) | ty_rptr(_, ref tm) => { maybe_walk_ty(tm.ty, f); @@ -2941,12 +2940,12 @@ pub fn unsized_part_of_type(cx: &ctxt, ty: t) -> t { ty_str | ty_trait(..) | ty_vec(..) => ty, ty_struct(_, ref substs) => { // Exactly one of the type parameters must be unsized. - for tp in substs.types.get_vec(subst::TypeSpace).iter() { + for tp in substs.types.get_slice(subst::TypeSpace).iter() { if !type_is_sized(cx, *tp) { return unsized_part_of_type(cx, *tp); } } - fail!("Unsized struct type with no unsized type params?"); + fail!("Unsized struct type with no unsized type params? {}", ty_to_string(cx, ty)); } _ => { assert!(type_is_sized(cx, ty), @@ -2990,11 +2989,21 @@ pub fn deref(t: t, explicit: bool) -> Option { } } +pub fn deref_or_dont(t: t) -> t { + match get(t).sty { + ty_box(ty) | ty_uniq(ty) => { + ty + }, + ty_rptr(_, mt) | ty_ptr(mt) => mt.ty, + _ => t + } +} + pub fn close_type(cx: &ctxt, t: t) -> t { match get(t).sty { ty_open(t) => mk_rptr(cx, ReStatic, mt {ty: t, mutbl:ast::MutImmutable}), _ => cx.sess.bug(format!("Trying to close a non-open type {}", - ty_to_str(cx, t)).as_slice()) + ty_to_string(cx, t)).as_slice()) } } @@ -3027,9 +3036,9 @@ pub fn index(ty: t) -> Option { // This is exactly the same as the above, except it supports strings, // which can't actually be indexed. pub fn array_element_ty(t: t) -> Option { - match get(ty).sty { + match get(t).sty { ty_vec(t, _) => Some(t), - ty_str => Some(ty: mk_u8()), + ty_str => Some(mk_u8()), _ => None } } @@ -3361,20 +3370,19 @@ pub fn unsize_ty(cx: &ctxt, } _ => cx.sess.span_bug(span, format!("UnsizeLength with bad sty: {}", - ty_to_str(cx, ty)).as_slice()) + ty_to_string(cx, ty)).as_slice()) }, &UnsizeStruct(box ref k, tp_index) => match get(ty).sty { ty_struct(did, ref substs) => { - let ty_substs = substs.types.get_vec(subst::TypeSpace); - let old_ty = ty_substs.get(tp_index); - let new_ty = unsize_ty(cx, *old_ty, k, span); + let ty_substs = substs.types.get_slice(subst::TypeSpace); + let new_ty = unsize_ty(cx, ty_substs[tp_index], k, span); let mut unsized_substs = substs.clone(); - *unsized_substs.types.get_mut_vec(subst::TypeSpace).get_mut(tp_index) = new_ty; + unsized_substs.types.get_mut_slice(subst::TypeSpace)[tp_index] = new_ty; mk_struct(cx, did, unsized_substs) } _ => cx.sess.span_bug(span, format!("UnsizeStruct with bad sty: {}", - ty_to_str(cx, ty)).as_slice()) + ty_to_string(cx, ty)).as_slice()) }, &UnsizeVtable(bounds, def_id, ref substs) => { mk_trait(cx, def_id, substs.clone(), bounds) @@ -5333,6 +5341,7 @@ pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec, ty_tup(_) | ty_param(_) | ty_infer(_) | + ty_open(_) | ty_err => {} } }) diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs index b246b5ce7a9..2bfbc67bbeb 100644 --- a/src/librustc/middle/ty_fold.rs +++ b/src/librustc/middle/ty_fold.rs @@ -273,6 +273,18 @@ impl TypeFoldable for ty::Generics { } } +impl TypeFoldable for ty::UnsizeKind { + fn fold_with(&self, folder: &mut F) -> ty::UnsizeKind { + match *self { + ty::UnsizeLength(len) => ty::UnsizeLength(len), + ty::UnsizeStruct(box ref k, n) => ty::UnsizeStruct(box k.fold_with(folder), n), + ty::UnsizeVtable(bounds, def_id, ref substs) => { + ty::UnsizeVtable(bounds.fold_with(folder), def_id, substs.fold_with(folder)) + } + } + } +} + /////////////////////////////////////////////////////////////////////////// // "super" routines: these are the default implementations for TypeFolder. // @@ -425,11 +437,11 @@ pub fn super_fold_autoref(this: &mut T, match *autoref { ty::AutoPtr(r, m, None) => ty::AutoPtr(this.fold_region(r), m, None), ty::AutoPtr(r, m, Some(ref a)) => { - ty::AutoPtr(this.fold_region(r), m, Some(box super_fold_autoref(this, a.clone()))) + ty::AutoPtr(this.fold_region(r), m, Some(box super_fold_autoref(this, &**a))) } ty::AutoUnsafe(m) => ty::AutoUnsafe(m), - ty::AutoUnsize(ref k) => ty::AutoUnsize(k.clone()), - ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.clone()), + ty::AutoUnsize(ref k) => ty::AutoUnsize(k.fold_with(this)), + ty::AutoUnsizeUniq(ref k) => ty::AutoUnsizeUniq(k.fold_with(this)), } } diff --git a/src/librustc/middle/typeck/check/method.rs b/src/librustc/middle/typeck/check/method.rs index f3b829e60ca..6bb17c90da2 100644 --- a/src/librustc/middle/typeck/check/method.rs +++ b/src/librustc/middle/typeck/check/method.rs @@ -947,7 +947,7 @@ impl<'a> LookupContext<'a> { // [T, ..len] -> [T] or &[T] or &&[T] fn auto_unsize_vec(&self, ty: ty::t, autoderefs: uint, len: uint) -> Option { let tcx = self.tcx(); - debug!("auto_unsize_vec {}", ppaux::ty_to_str(tcx, ty)); + debug!("auto_unsize_vec {}", ppaux::ty_to_string(tcx, ty)); // First try to borrow to an unsized vec. let entry = self.search_for_some_kind_of_autorefd_method( @@ -1330,7 +1330,7 @@ impl<'a> LookupContext<'a> { match self.fcx.mk_subty(false, infer::Misc(span), rcvr_ty, transformed_self_ty) { Ok(_) => {} - Err(e) => { + Err(_) => { self.bug(format!( "{} was a subtype of {} but now is not?", self.ty_to_string(rcvr_ty), diff --git a/src/librustc/middle/typeck/check/mod.rs b/src/librustc/middle/typeck/check/mod.rs index 6d3e001a00b..02464e17bac 100644 --- a/src/librustc/middle/typeck/check/mod.rs +++ b/src/librustc/middle/typeck/check/mod.rs @@ -1149,7 +1149,7 @@ fn check_cast(fcx: &FnCtxt, if ty::type_is_scalar(t_1) { // Supply the type as a hint so as to influence integer // literals and other things that might care. - check_expr_with_hint(fcx, e, t_1) + check_expr_with_expectation(fcx, e, ExpectCastableToType(t_1)) } else { check_expr(fcx, e) } @@ -2033,7 +2033,6 @@ fn check_argument_types(fcx: &FnCtxt, } check_expr_coercable_to_type(fcx, &**arg, formal_ty); - } } } @@ -2428,12 +2427,12 @@ fn check_expr_with_unifier(fcx: &FnCtxt, // 'else' branch. let expected = match expected.only_has_type() { ExpectHasType(ety) => { - match infer::resolve_type(fcx.infcx(), ety, force_tvar) { + match infer::resolve_type(fcx.infcx(), Some(sp), ety, force_tvar) { Ok(rty) if !ty::type_is_ty_var(rty) => ExpectHasType(rty), _ => NoExpectation } } - None => None + _ => NoExpectation }; check_block_with_expected(fcx, then_blk, expected); let then_ty = fcx.node_ty(then_blk.id); @@ -3067,23 +3066,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt, type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t); - fn check_fn_for_vec_elements_expected(fcx: &FnCtxt, - expected: Expectation) - -> (ExprCheckerWithTy, ty::t) { - let tcx = fcx.ccx.tcx; - let (coerce, t) = match expected { - // If we're given an expected type, we can try to coerce to it - ExpectHasType(t) if ty::type_is_vec(t) => (true, ty::sequence_element_type(tcx, t)), - // Otherwise we just leave the type to be resolved later - _ => (false, fcx.infcx().next_ty_var()) - }; - if coerce { - (check_expr_coercable_to_type, t) - } else { - (check_expr_has_type, t) - } - } - let tcx = fcx.ccx.tcx; let id = expr.id; match expr.node { @@ -3157,7 +3139,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } } ast::ExprUnary(unop, ref oprnd) => { - let expected = expected.only_has_type(); let expected_inner = expected.map(fcx, |sty| { match unop { ast::UnBox | ast::UnUniq => match *sty { @@ -3328,7 +3309,6 @@ fn check_expr_with_unifier(fcx: &FnCtxt, } }, Some(ref e) => { - //check_expr_has_type(fcx, e, ret_ty); check_expr_coercable_to_type(fcx, &**e, ret_ty); } } @@ -3483,12 +3463,15 @@ fn check_expr_with_unifier(fcx: &FnCtxt, check_cast(fcx, &**e, &**t, id, expr.span); } ast::ExprVec(ref args) => { - let uty = unpack_expected( - fcx, expected, - |sty| match *sty { - ty::ty_vec(ty, _) => Some(ty), - _ => None - }); + let uty = match expected { + ExpectHasType(uty) => { + match ty::get(uty).sty { + ty::ty_vec(ty, _) => Some(ty), + _ => None + } + } + _ => None + }; let typ = match uty { Some(uty) => { @@ -3512,12 +3495,15 @@ fn check_expr_with_unifier(fcx: &FnCtxt, check_expr_has_type(fcx, &**count_expr, ty::mk_uint()); let count = ty::eval_repeat_count(fcx, &**count_expr); - let uty = unpack_expected( - fcx, expected, - |sty| match *sty { - ty::ty_vec(ty, _) => Some(ty), - _ => None - }); + let uty = match expected { + ExpectHasType(uty) => { + match ty::get(uty).sty { + ty::ty_vec(ty, _) => Some(ty), + _ => None + } + } + _ => None + }; let (element_ty, t) = match uty { Some(uty) => { @@ -3552,17 +3538,14 @@ fn check_expr_with_unifier(fcx: &FnCtxt, let mut err_field = false; let elt_ts = elts.iter().enumerate().map(|(i, e)| { - let opt_hint = match flds { - Some(ref fs) if i < fs.len() => ExpectHasType(*fs.get(i)), - _ => NoExpectation - }; - let t = match opt_hint { - ExpectHasType(ety) => { + let t = match flds { + Some(ref fs) if i < fs.len() => { + let ety = *fs.get(i); check_expr_coercable_to_type(fcx, &**e, ety); ety } _ => { - check_expr_with_expectation(fcx, &**e, opt_hint); + check_expr_with_expectation(fcx, &**e, NoExpectation); fcx.expr_ty(&**e) } }; @@ -3942,42 +3925,42 @@ fn check_block_with_expected(fcx: &FnCtxt, } match blk.expr { None => if any_err { - fcx.write_error(blk.id); - } - else if any_bot { - fcx.write_bot(blk.id); - } - else { - fcx.write_nil(blk.id); - }, - Some(e) => { - if any_bot && !warned { - fcx.ccx - .tcx - .sess - .add_lint(lint::builtin::UNREACHABLE_CODE, - e.id, - e.span, - "unreachable expression".to_string()); - } - let ety = match expected { - ExpectHasType(ety) => { - check_expr_coercable_to_type(fcx, &*e, ety); - ety + fcx.write_error(blk.id); } - _ => { - check_expr_with_expectation(fcx, &*e, expected); - fcx.expr_ty(e) + else if any_bot { + fcx.write_bot(blk.id); } - }; + else { + fcx.write_nil(blk.id); + }, + Some(e) => { + if any_bot && !warned { + fcx.ccx + .tcx + .sess + .add_lint(lint::builtin::UNREACHABLE_CODE, + e.id, + e.span, + "unreachable expression".to_string()); + } + let ety = match expected { + ExpectHasType(ety) => { + check_expr_coercable_to_type(fcx, &*e, ety); + ety + } + _ => { + check_expr_with_expectation(fcx, &*e, expected); + fcx.expr_ty(&*e) + } + }; - fcx.write_ty(blk.id, ety); - if any_err { - fcx.write_error(blk.id); - } else if any_bot { - fcx.write_bot(blk.id); + fcx.write_ty(blk.id, ety); + if any_err { + fcx.write_error(blk.id); + } else if any_bot { + fcx.write_bot(blk.id); + } } - } }; }); diff --git a/src/librustc/middle/typeck/check/vtable.rs b/src/librustc/middle/typeck/check/vtable.rs index 5b14ee62b0a..530f8dd4b9e 100644 --- a/src/librustc/middle/typeck/check/vtable.rs +++ b/src/librustc/middle/typeck/check/vtable.rs @@ -810,7 +810,6 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { } } AutoDerefRef(ref adj) => { - assert!(!ty::adjust_is_object(adjustment)); for autoderef in range(0, adj.autoderefs) { let method_call = MethodCall::autoderef(ex.id, autoderef); match fcx.inh.method_map.borrow().find(&method_call) { @@ -831,9 +830,7 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) { } } } - _ => { - assert!(!ty::adjust_is_object(adjustment)); - } + _ => {} } } None => {} @@ -867,27 +864,21 @@ fn trait_cast_types(fcx: &FnCtxt, } &ty::UnsizeStruct(box ref k, tp_index) => match ty::get(src_ty).sty { ty::ty_struct(_, ref substs) => { - let ty_substs = substs.types.get_vec(subst::TypeSpace); - let field_ty = *ty_substs.get(tp_index); - let field_ty = structurally_resolved_type(fcx, sp, field_ty); + let ty_substs = substs.types.get_slice(subst::TypeSpace); + let field_ty = structurally_resolved_type(fcx, sp, ty_substs[tp_index]); trait_cast_types_unsize(fcx, k, field_ty, sp) } _ => fail!("Failed to find a ty_struct to correspond with \ UnsizeStruct whilst walking adjustment. Found {}", - ppaux::ty_to_str(fcx.tcx(), src_ty)) + ppaux::ty_to_string(fcx.tcx(), src_ty)) }, _ => None } } match autoref { - &ty::AutoUnsize(ref k) => trait_cast_types_unsize(fcx, k, src_ty, sp), - &ty::AutoUnsizeUniq(ref k) => match k { - &ty::UnsizeVtable(bounds, def_id, ref substs) => { - Some((src_ty, ty::mk_trait(fcx.tcx(), def_id, substs.clone(), bounds))) - } - _ => None - }, + &ty::AutoUnsize(ref k) | + &ty::AutoUnsizeUniq(ref k) => trait_cast_types_unsize(fcx, k, src_ty, sp), &ty::AutoPtr(_, _, Some(box ref autoref)) => { trait_cast_types_autoref(fcx, autoref, src_ty, sp) } diff --git a/src/librustc/middle/typeck/infer/coercion.rs b/src/librustc/middle/typeck/infer/coercion.rs index 6d0b34e89d6..abf36638113 100644 --- a/src/librustc/middle/typeck/infer/coercion.rs +++ b/src/librustc/middle/typeck/infer/coercion.rs @@ -199,8 +199,8 @@ impl<'f> Coerce<'f> { } } - pub fn unpack_actual_value(&self, a: ty::t, f: |&ty::sty| -> CoerceResult) - -> CoerceResult { + pub fn unpack_actual_value(&self, a: ty::t, f: |&ty::sty| -> T) + -> T { match resolve_type(self.get_ref().infcx, None, a, try_resolve_tvar_shallow) { Ok(t) => { @@ -306,7 +306,7 @@ impl<'f> Coerce<'f> { let sty_b = &ty::get(b).sty; match (sty_a, sty_b) { - (&ty::ty_uniq(t_a), &ty::ty_rptr(_, mt_b)) => Err(ty::terr_mismatch), + (&ty::ty_uniq(_), &ty::ty_rptr(..)) => Err(ty::terr_mismatch), (&ty::ty_rptr(_, ty::mt{ty: t_a, ..}), &ty::ty_rptr(_, mt_b)) => { self.unpack_actual_value(t_a, |sty_a| { match self.unsize_ty(sty_a, mt_b.ty) { @@ -381,8 +381,8 @@ impl<'f> Coerce<'f> { if did_a == did_b => { debug!("unsizing a struct"); // Try unsizing each type param in turn to see if we end up with ty_b. - let ty_substs_a = substs_a.types.get_vec(subst::TypeSpace); - let ty_substs_b = substs_b.types.get_vec(subst::TypeSpace); + let ty_substs_a = substs_a.types.get_slice(subst::TypeSpace); + let ty_substs_b = substs_b.types.get_slice(subst::TypeSpace); assert!(ty_substs_a.len() == ty_substs_b.len()); let sub = Sub(self.get_ref().clone()); @@ -397,7 +397,7 @@ impl<'f> Coerce<'f> { Some((new_tp, k)) => { // Check that the whole types match. let mut new_substs = substs_a.clone(); - *new_substs.types.get_mut_vec(subst::TypeSpace).get_mut(i) = new_tp; + new_substs.types.get_mut_slice(subst::TypeSpace)[i] = new_tp; let ty = ty::mk_struct(tcx, did_a, new_substs); if self.get_ref().infcx.try(|| sub.tys(ty, ty_b)).is_err() { debug!("Unsized type parameter '{}', but still \ @@ -439,8 +439,7 @@ impl<'f> Coerce<'f> { let r_a = self.get_ref().infcx.next_region_var(coercion); let a_borrowed = match *sty_a { - ty::ty_uniq(ty) => return Err(ty::terr_mismatch), - ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty { + ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) => match ty::get(ty).sty { ty::ty_trait(box ty::TyTrait { def_id, ref substs, diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index 4f68d42de96..5dff183108c 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -370,7 +370,7 @@ pub fn ty_to_string(cx: &ctxt, typ: t) -> String { buf.push_str(mt_to_string(cx, tm).as_slice()); buf } - ty_open(typ) => format!("opened<{}>", ty_to_str(cx, typ)), + ty_open(typ) => format!("opened<{}>", ty_to_string(cx, typ)), ty_tup(ref elems) => { let strs: Vec = elems.iter().map(|elem| ty_to_string(cx, *elem)).collect(); format!("({})", strs.connect(",")) diff --git a/src/libserialize/serialize.rs b/src/libserialize/serialize.rs index a9cbacb07be..bbaac7a96e9 100644 --- a/src/libserialize/serialize.rs +++ b/src/libserialize/serialize.rs @@ -18,7 +18,6 @@ use std::path; use std::rc::Rc; use std::gc::{Gc, GC}; use std::cell::{Cell, RefCell}; -use std::strbuf::StrBuf; pub trait Encoder { // Primitive types: diff --git a/src/libsyntax/parse/parser.rs b/src/libsyntax/parse/parser.rs index 00513f7f67c..01de001c043 100644 --- a/src/libsyntax/parse/parser.rs +++ b/src/libsyntax/parse/parser.rs @@ -61,7 +61,7 @@ use ast::{UnsafeFn, ViewItem, ViewItem_, ViewItemExternCrate, ViewItemUse}; use ast::{ViewPath, ViewPathGlob, ViewPathList, ViewPathSimple}; use ast::{Visibility, WhereClause, WherePredicate}; use ast; -use ast_util::{as_prec, ident_to_path, lit_is_str, operator_prec}; +use ast_util::{as_prec, ident_to_path, operator_prec}; use ast_util; use attr; use codemap::{Span, BytePos, Spanned, spanned, mk_sp}; @@ -2577,21 +2577,24 @@ impl<'a> Parser<'a> { ex = self.mk_unary(UnUniq, e); } token::IDENT(_, _) => { - if self.is_keyword(keywords::Box) { - self.bump(); + if !self.is_keyword(keywords::Box) { + return self.parse_dot_or_call_expr(); + } - // Check for a place: `box(PLACE) EXPR`. - if self.eat(&token::LPAREN) { - // Support `box() EXPR` as the default. - if !self.eat(&token::RPAREN) { - let place = self.parse_expr(); - self.expect(&token::RPAREN); - let subexpression = self.parse_prefix_expr(); - hi = subexpression.span.hi; - ex = ExprBox(place, subexpression); - return self.mk_expr(lo, hi, ex); - } + self.bump(); + + // Check for a place: `box(PLACE) EXPR`. + if self.eat(&token::LPAREN) { + // Support `box() EXPR` as the default. + if !self.eat(&token::RPAREN) { + let place = self.parse_expr(); + self.expect(&token::RPAREN); + let subexpression = self.parse_prefix_expr(); + hi = subexpression.span.hi; + ex = ExprBox(place, subexpression); + return self.mk_expr(lo, hi, ex); } + } // Otherwise, we use the unique pointer default. let subexpression = self.parse_prefix_expr(); diff --git a/src/libtime/lib.rs b/src/libtime/lib.rs index 9a56dd5c0e4..429a16ec5c8 100644 --- a/src/libtime/lib.rs +++ b/src/libtime/lib.rs @@ -1,4 +1,4 @@ -// Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -268,19 +268,7 @@ pub struct Tm { pub tm_nsec: i32, } -impl Tm { - pub fn tm_zone<'a>(&'a self) -> &'a str { - self.tm_zone.as_slice() - } -} - pub fn empty_tm() -> Tm { - // 64 is the max size of the timezone buffer allocated on windows - // in rust_localtime. In glibc the max timezone size is supposedly 3. - let mut zone = StrBuf::new(); - for _ in range(0, 64) { - zone.push_char(' ') - } Tm { tm_sec: 0_i32, tm_min: 0_i32, @@ -292,7 +280,6 @@ pub fn empty_tm() -> Tm { tm_yday: 0_i32, tm_isdst: 0_i32, tm_gmtoff: 0_i32, - tm_zone: zone, tm_nsec: 0_i32, } } @@ -773,7 +760,6 @@ pub fn strptime(s: &str, format: &str) -> Result { 'Z' => { if match_str(s, pos, "UTC") || match_str(s, pos, "GMT") { tm.tm_gmtoff = 0_i32; - tm.tm_zone = "UTC".into_strbuf(); Ok(pos + 3u) } else { // It's odd, but to maintain compatibility with c's @@ -798,7 +784,6 @@ pub fn strptime(s: &str, format: &str) -> Result { let (v, pos) = item; if v == 0_i32 { tm.tm_gmtoff = 0_i32; - tm.tm_zone = "UTC".into_strbuf(); } Ok(pos) @@ -828,7 +813,6 @@ pub fn strptime(s: &str, format: &str) -> Result { tm_yday: 0_i32, tm_isdst: 0_i32, tm_gmtoff: 0_i32, - tm_zone: StrBuf::new(), tm_nsec: 0_i32, }; let mut pos = 0u; @@ -875,7 +859,6 @@ pub fn strptime(s: &str, format: &str) -> Result { tm_yday: tm.tm_yday, tm_isdst: tm.tm_isdst, tm_gmtoff: tm.tm_gmtoff, - tm_zone: tm.tm_zone.clone(), tm_nsec: tm.tm_nsec, }) } else { result } @@ -1077,7 +1060,6 @@ pub fn strftime(format: &str, tm: &Tm) -> String { 'w' => (tm.tm_wday as int).to_string(), 'Y' => (tm.tm_year as int + 1900).to_string(), 'y' => format!("{:02d}", (tm.tm_year as int + 1900) % 100), - 'Z' => tm.tm_zone.as_slice().to_owned(), 'z' => { let sign = if tm.tm_gmtoff > 0_i32 { '+' } else { '-' }; let mut m = num::abs(tm.tm_gmtoff) / 60_i32; @@ -1203,7 +1185,6 @@ mod tests { assert_eq!(utc.tm_yday, 43_i32); assert_eq!(utc.tm_isdst, 0_i32); assert_eq!(utc.tm_gmtoff, 0_i32); - assert_eq!(utc.tm_zone(), "UTC"); assert_eq!(utc.tm_nsec, 54321_i32); } @@ -1225,12 +1206,6 @@ mod tests { assert_eq!(local.tm_yday, 43_i32); assert_eq!(local.tm_isdst, 0_i32); assert_eq!(local.tm_gmtoff, -28800_i32); - - // FIXME (#2350): We should probably standardize on the timezone - // abbreviation. - let zone = local.tm_zone(); - assert!(zone == "PST" || zone == "Pacific Standard Time"); - assert_eq!(local.tm_nsec, 54321_i32); } @@ -1273,7 +1248,6 @@ mod tests { assert!(tm.tm_wday == 0_i32); assert!(tm.tm_isdst == 0_i32); assert!(tm.tm_gmtoff == 0_i32); - assert!(tm.tm_zone() == ""); assert!(tm.tm_nsec == 0_i32); } Err(_) => () @@ -1297,7 +1271,6 @@ mod tests { assert!(tm.tm_yday == 0_i32); assert!(tm.tm_isdst == 0_i32); assert!(tm.tm_gmtoff == 0_i32); - assert!(tm.tm_zone() == ""); assert!(tm.tm_nsec == 12340000_i32); } } @@ -1409,10 +1382,10 @@ mod tests { assert!(test("6", "%w")); assert!(test("2009", "%Y")); assert!(test("09", "%y")); - assert!(strptime("UTC", "%Z").unwrap().tm_zone() == "UTC"); - assert!(strptime("PST", "%Z").unwrap().tm_zone() == ""); - assert!(strptime("-0000", "%z").unwrap().tm_gmtoff == 0); - assert!(strptime("-0800", "%z").unwrap().tm_gmtoff == 0); + assert!(strptime("-0000", "%z").unwrap().tm_gmtoff == + 0); + assert!(strptime("-0800", "%z").unwrap().tm_gmtoff == + 0); assert!(test("%", "%%")); // Test for #7256 diff --git a/src/libunicode/u_str.rs b/src/libunicode/u_str.rs index 262721bd636..c71cf5557e3 100644 --- a/src/libunicode/u_str.rs +++ b/src/libunicode/u_str.rs @@ -46,9 +46,11 @@ pub trait UnicodeStrSlice<'a> { /// /// ```rust /// let gr1 = "a\u0310e\u0301o\u0308\u0332".graphemes(true).collect::>(); - /// assert_eq!(gr1.as_slice(), &["a\u0310", "e\u0301", "o\u0308\u0332"]); + /// let b: &[_] = &["a\u0310", "e\u0301", "o\u0308\u0332"]; + /// assert_eq!(gr1.as_slice(), b); /// let gr2 = "a\r\nb🇷🇺🇸🇹".graphemes(true).collect::>(); - /// assert_eq!(gr2.as_slice(), &["a", "\r\n", "b", "🇷🇺🇸🇹"]); + /// let b: &[_] = &["a", "\r\n", "b", "🇷🇺🇸🇹"]; + /// assert_eq!(gr2.as_slice(), b); /// ``` fn graphemes(&self, is_extended: bool) -> Graphemes<'a>; @@ -59,7 +61,8 @@ pub trait UnicodeStrSlice<'a> { /// /// ```rust /// let gr_inds = "a̐éö̲\r\n".grapheme_indices(true).collect::>(); - /// assert_eq!(gr_inds.as_slice(), &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]); + /// let b: &[_] = &[(0u, "a̐"), (3, "é"), (6, "ö̲"), (11, "\r\n")]; + /// assert_eq!(gr_inds.as_slice(), b); /// ``` fn grapheme_indices(&self, is_extended: bool) -> GraphemeIndices<'a>; diff --git a/src/liburl/lib.rs b/src/liburl/lib.rs index 9ced6cb62af..b5ffdef22e9 100644 --- a/src/liburl/lib.rs +++ b/src/liburl/lib.rs @@ -1095,7 +1095,8 @@ mod tests { t("\0", "%00"); t("\n", "%0A"); - t(&[0u8, 10, 37], "%00%0A%25"); + let a: &[_] = &[0u8, 10, 37]; + t(a, "%00%0A%25"); } #[test] @@ -1130,7 +1131,8 @@ mod tests { t("\0", "%00"); t("\n", "%0A"); - t(&[0u8, 10, 37], "%00%0A%25"); + let a: &[_] = &[0u8, 10, 37]; + t(a, "%00%0A%25"); } #[test] diff --git a/src/rt/rust_builtin.c b/src/rt/rust_builtin.c index 1a9b1c1c818..ba20f2c6f27 100644 --- a/src/rt/rust_builtin.c +++ b/src/rt/rust_builtin.c @@ -127,15 +127,6 @@ rust_list_dir_wfd_fp_buf(void* wfd) { } #endif -typedef struct -{ - size_t fill; // in bytes; if zero, heapified - size_t alloc; // in bytes - uint8_t *data; -} rust_vec; - -typedef rust_vec rust_str_buf; - typedef struct { int32_t tm_sec; int32_t tm_min; @@ -147,7 +138,6 @@ typedef struct { int32_t tm_yday; int32_t tm_isdst; int32_t tm_gmtoff; - rust_str_buf tm_zone; int32_t tm_nsec; } rust_tm; @@ -164,8 +154,10 @@ void rust_tm_to_tm(rust_tm* in_tm, struct tm* out_tm) { out_tm->tm_isdst = in_tm->tm_isdst; } -void tm_to_rust_tm(struct tm* in_tm, rust_tm* out_tm, int32_t gmtoff, - const char *zone, int32_t nsec) { +void tm_to_rust_tm(struct tm* in_tm, + rust_tm* out_tm, + int32_t gmtoff, + int32_t nsec) { out_tm->tm_sec = in_tm->tm_sec; out_tm->tm_min = in_tm->tm_min; out_tm->tm_hour = in_tm->tm_hour; @@ -177,13 +169,6 @@ void tm_to_rust_tm(struct tm* in_tm, rust_tm* out_tm, int32_t gmtoff, out_tm->tm_isdst = in_tm->tm_isdst; out_tm->tm_gmtoff = gmtoff; out_tm->tm_nsec = nsec; - - if (zone != NULL) { - size_t size = strlen(zone); - assert(out_tm->tm_zone.alloc >= size); - memcpy(out_tm->tm_zone.data, zone, size); - out_tm->tm_zone.fill = size; - } } #if defined(__WIN32__) @@ -225,7 +210,7 @@ rust_gmtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { time_t s = sec; GMTIME(&s, &tm); - tm_to_rust_tm(&tm, timeptr, 0, "UTC", nsec); + tm_to_rust_tm(&tm, timeptr, 0, nsec); } void @@ -234,28 +219,13 @@ rust_localtime(int64_t sec, int32_t nsec, rust_tm *timeptr) { time_t s = sec; LOCALTIME(&s, &tm); - const char* zone = NULL; #if defined(__WIN32__) int32_t gmtoff = -timezone; - wchar_t wbuffer[64] = {0}; - char buffer[256] = {0}; - // strftime("%Z") can contain non-UTF-8 characters on non-English locale (issue #9418), - // so time zone should be converted from UTF-16 string. - // Since wcsftime depends on setlocale() result, - // instead we convert it using MultiByteToWideChar. - if (strftime(buffer, sizeof(buffer) / sizeof(char), "%Z", &tm) > 0) { - // ANSI -> UTF-16 - MultiByteToWideChar(CP_ACP, 0, buffer, -1, wbuffer, sizeof(wbuffer) / sizeof(wchar_t)); - // UTF-16 -> UTF-8 - WideCharToMultiByte(CP_UTF8, 0, wbuffer, -1, buffer, sizeof(buffer), NULL, NULL); - zone = buffer; - } #else int32_t gmtoff = tm.tm_gmtoff; - zone = tm.tm_zone; #endif - tm_to_rust_tm(&tm, timeptr, gmtoff, zone, nsec); + tm_to_rust_tm(&tm, timeptr, gmtoff, nsec); } int64_t diff --git a/src/test/compile-fail/const-cast-different-types.rs b/src/test/compile-fail/const-cast-different-types.rs index 4f53694ebd6..6b8e126db77 100644 --- a/src/test/compile-fail/const-cast-different-types.rs +++ b/src/test/compile-fail/const-cast-different-types.rs @@ -9,8 +9,10 @@ // except according to those terms. static a: &'static str = "foo"; -static b: *const u8 = a as *const u8; //~ ERROR mismatched types: expected `*u8` but found `&'static str` -static c: *const u8 = &a as *const u8; //~ ERROR mismatched types: expected `*u8` but found `&&'static str` +static b: *const u8 = a as *const u8; +//~^ ERROR mismatched types: expected `*const u8`, found `&'static str` +static c: *const u8 = &a as *const u8; +//~^ ERROR mismatched types: expected `*const u8`, found `&&'static str` fn main() { } diff --git a/src/test/compile-fail/dst-bad-assign-2.rs b/src/test/compile-fail/dst-bad-assign-2.rs index 282cf57df26..08e51038104 100644 --- a/src/test/compile-fail/dst-bad-assign-2.rs +++ b/src/test/compile-fail/dst-bad-assign-2.rs @@ -10,7 +10,7 @@ // Forbid assignment into a dynamically sized type. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/compile-fail/dst-bad-assign.rs b/src/test/compile-fail/dst-bad-assign.rs index e069eb01ae1..17149941a7e 100644 --- a/src/test/compile-fail/dst-bad-assign.rs +++ b/src/test/compile-fail/dst-bad-assign.rs @@ -10,7 +10,7 @@ // Forbid assignment into a dynamically sized type. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T @@ -42,5 +42,5 @@ pub fn main() { // Assignment. let f5: &mut Fat = &mut Fat { f1: 5, f2: "some str", ptr: Bar1 {f :42} }; let z: Box = box Bar1 {f: 36}; - f5.ptr = Bar1 {f: 36}; //~ ERROR mismatched types: expected `ToBar` but found `Bar1` + f5.ptr = Bar1 {f: 36}; //~ ERROR mismatched types: expected `ToBar`, found `Bar1` } diff --git a/src/test/compile-fail/dst-bad-coerce1.rs b/src/test/compile-fail/dst-bad-coerce1.rs index a7dc4e123af..a609740eaeb 100644 --- a/src/test/compile-fail/dst-bad-coerce1.rs +++ b/src/test/compile-fail/dst-bad-coerce1.rs @@ -10,7 +10,7 @@ // Attempt to change the type as well as unsizing. -struct Fat { +struct Fat { ptr: T } @@ -22,7 +22,7 @@ pub fn main() { let f1 = Fat { ptr: [1, 2, 3] }; let f2: &Fat<[int, ..3]> = &f1; let f3: &Fat<[uint]> = f2; - //~^ ERROR mismatched types: expected `&Fat<[uint]>` but found `&Fat<[int, .. 3]>` + //~^ ERROR mismatched types: expected `&Fat<[uint]>`, found `&Fat<[int, .. 3]>` // With a trait. let f1 = Fat { ptr: Foo }; diff --git a/src/test/compile-fail/dst-bad-coerce2.rs b/src/test/compile-fail/dst-bad-coerce2.rs index d4ce59b7261..118e4ce7e08 100644 --- a/src/test/compile-fail/dst-bad-coerce2.rs +++ b/src/test/compile-fail/dst-bad-coerce2.rs @@ -10,7 +10,7 @@ // Attempt to change the mutability as well as unsizing. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-coerce3.rs b/src/test/compile-fail/dst-bad-coerce3.rs index bd7c46060a5..7cf647a26d7 100644 --- a/src/test/compile-fail/dst-bad-coerce3.rs +++ b/src/test/compile-fail/dst-bad-coerce3.rs @@ -10,7 +10,7 @@ // Attempt to extend the lifetime as well as unsizing. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/dst-bad-coerce4.rs b/src/test/compile-fail/dst-bad-coerce4.rs index 0916fa08a39..9a192334997 100644 --- a/src/test/compile-fail/dst-bad-coerce4.rs +++ b/src/test/compile-fail/dst-bad-coerce4.rs @@ -10,7 +10,7 @@ // Attempt to coerce from unsized to sized. -struct Fat { +struct Fat { ptr: T } @@ -18,5 +18,5 @@ pub fn main() { // With a vec of ints. let f1: &Fat<[int]> = &Fat { ptr: [1, 2, 3] }; let f2: &Fat<[int, ..3]> = f1; - //~^ ERROR mismatched types: expected `&Fat<[int, .. 3]>` but found `&Fat<[int]>` + //~^ ERROR mismatched types: expected `&Fat<[int, .. 3]>`, found `&Fat<[int]>` } diff --git a/src/test/compile-fail/dst-bad-deep.rs b/src/test/compile-fail/dst-bad-deep.rs index b18e7dad4ac..cf526392283 100644 --- a/src/test/compile-fail/dst-bad-deep.rs +++ b/src/test/compile-fail/dst-bad-deep.rs @@ -13,7 +13,7 @@ // because it would require stack allocation of an unsized temporary (*g in the // test). -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/compile-fail/issue-3907-2.rs b/src/test/compile-fail/issue-3907-2.rs index 795e48cb7b0..ab9f7a84530 100644 --- a/src/test/compile-fail/issue-3907-2.rs +++ b/src/test/compile-fail/issue-3907-2.rs @@ -11,10 +11,12 @@ // aux-build:issue_3907.rs extern crate issue_3907; -type Foo = issue_3907::Foo; //~ ERROR: reference to trait +type Foo = issue_3907::Foo; struct S { name: int } +fn bar(_x: Foo) {} //~ ERROR variable `_x` has dynamically sized type `issue_3907::Foo` + fn main() {} diff --git a/src/test/compile-fail/issue-4972.rs b/src/test/compile-fail/issue-4972.rs index f7199a92d27..199bc3f5c29 100644 --- a/src/test/compile-fail/issue-4972.rs +++ b/src/test/compile-fail/issue-4972.rs @@ -17,7 +17,7 @@ pub enum TraitWrapper { fn get_tw_map(tw: &TraitWrapper) -> &MyTrait { match *tw { - A(box ref map) => map, //~ ERROR mismatched types: expected `Box` but found a box + A(box ref map) => map, //~ ERROR type `Box` cannot be dereferenced } } diff --git a/src/test/compile-fail/issue-5035-2.rs b/src/test/compile-fail/issue-5035-2.rs index 8d9116da81d..689b8f7c613 100644 --- a/src/test/compile-fail/issue-5035-2.rs +++ b/src/test/compile-fail/issue-5035-2.rs @@ -9,6 +9,8 @@ // except according to those terms. trait I {} -type K = I; //~ ERROR: reference to trait +type K = I; + +fn foo(_x: K) {} //~ ERROR: variable `_x` has dynamically sized type `I` fn main() {} diff --git a/src/test/compile-fail/issue-5883.rs b/src/test/compile-fail/issue-5883.rs index 3703d4f39ac..14136d96c2d 100644 --- a/src/test/compile-fail/issue-5883.rs +++ b/src/test/compile-fail/issue-5883.rs @@ -16,7 +16,7 @@ struct Struct { fn new_struct(r: A) -> Struct { //~^ ERROR variable `r` has dynamically sized type `A` - Struct { r: r } + Struct { r: r } //~ ERROR trying to initialise a dynamically sized struct } trait Curve {} diff --git a/src/test/compile-fail/issue-7013.rs b/src/test/compile-fail/issue-7013.rs index efd8e75d3d6..ef585998aa5 100644 --- a/src/test/compile-fail/issue-7013.rs +++ b/src/test/compile-fail/issue-7013.rs @@ -32,7 +32,7 @@ struct A { fn main() { let a = A {v: box B{v: None} as Box}; - //~^ ERROR cannot pack type `Box` as a trait bounded by Send because the type does not fulfil + //~^ ERROR cannot pack type `Box`, which does not fulfill `Send`, as a trait bounded by Send let v = Rc::new(RefCell::new(a)); let w = v.clone(); let b = &*v; diff --git a/src/test/compile-fail/tuple-arity-mismatch.rs b/src/test/compile-fail/tuple-arity-mismatch.rs index 27d272c9f31..1500a3cbe52 100644 --- a/src/test/compile-fail/tuple-arity-mismatch.rs +++ b/src/test/compile-fail/tuple-arity-mismatch.rs @@ -13,6 +13,6 @@ fn first((value, _): (int, f64)) -> int { value } fn main() { - let y = first ((1,2,3)); + let y = first ((1,2.0,3)); //~^ ERROR expected a tuple with 2 elements, found one with 3 elements } diff --git a/src/test/pretty/issue-4264.pp b/src/test/pretty/issue-4264.pp index e1ad27ec5c7..7f93c8595f2 100644 --- a/src/test/pretty/issue-4264.pp +++ b/src/test/pretty/issue-4264.pp @@ -48,8 +48,8 @@ pub fn bar() { as core::fmt::rt::Piece<'static>)] as [core::fmt::rt::Piece<'static>, .. 1]); let __args_vec = - (&([] as &'static [core::fmt::Argument<'static>]) as - &'static [core::fmt::Argument<'static>]); + (&([] as [core::fmt::Argument<'static>, .. 0]) as + &'static [core::fmt::Argument<'static>, .. 0]); let __args = (unsafe { ((::std::fmt::Arguments::new as @@ -58,7 +58,7 @@ pub fn bar() { [core::fmt::rt::Piece<'static>, .. 1]), (__args_vec as - &'static [core::fmt::Argument<'static>])) + &'static [core::fmt::Argument<'static>, .. 0])) as core::fmt::Arguments<'static>) } as core::fmt::Arguments<'static>); diff --git a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot index 978cca56b56..77ee0df5512 100644 --- a/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f15.dot-expected.dot @@ -47,7 +47,7 @@ digraph block { N10 -> N11; N11 -> N12; N12 -> N13; - N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { break ; \"unreachable\"; }\l y -= 3;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { break ; \"unreachable\"; }\l y -= 3;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1 { break \'outer ; \"unreachable\"; }\l if y >= 2 { break ; \"unreachable\"; }\l y -= 3;\l }\l y -= 4;\l x -= 5;\l}\l"]; + N13 -> N7[label="exiting scope_0 expr break \'outer,\lexiting scope_1 stmt break \'outer ;,\lexiting scope_2 block { break \'outer ; \"unreachable\"; },\lexiting scope_3 expr if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_4 stmt if x == 1i { break \'outer ; \"unreachable\"; },\lexiting scope_5 block {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l}\l,\lexiting scope_6 expr \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_7 stmt \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l,\lexiting scope_8 block {\l \'inner:\l loop {\l if x == 1i { break \'outer ; \"unreachable\"; }\l if y >= 2i { break ; \"unreachable\"; }\l y -= 3i;\l }\l y -= 4i;\l x -= 5i;\l}\l"]; N14 -> N15; N15 -> N16; N12 -> N17; diff --git a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot index 963c4b43531..b5a867e6029 100644 --- a/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot +++ b/src/test/run-make/graphviz-flowgraph/f16.dot-expected.dot @@ -29,7 +29,7 @@ digraph block { N27[label="expr y"]; N28[label="expr y -= 1i"]; N29[label="block {\l if x == 1i { continue \'outer ; \"unreachable\"; }\l if y >= 1i { break ; \"unreachable\"; }\l y -= 1i;\l}\l"]; - N30[label="expr 1"]; + N30[label="expr 1i"]; N31[label="expr y"]; N32[label="expr y -= 1i"]; N33[label="expr 1i"]; diff --git a/src/test/run-pass/dst-dtor-1.rs b/src/test/run-pass/dst-dtor-1.rs new file mode 100644 index 00000000000..6e2ae117ce7 --- /dev/null +++ b/src/test/run-pass/dst-dtor-1.rs @@ -0,0 +1,34 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut DROP_RAN: bool = false; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN = true; } + } +} + +trait Trait {} +impl Trait for Foo {} + +struct Fat { + f: T +} + +pub fn main() { + { + let _x: Box> = box Fat { f: Foo }; + } + unsafe { + assert!(DROP_RAN); + } +} diff --git a/src/test/run-pass/dst-dtor-2.rs b/src/test/run-pass/dst-dtor-2.rs new file mode 100644 index 00000000000..deaf49228bc --- /dev/null +++ b/src/test/run-pass/dst-dtor-2.rs @@ -0,0 +1,31 @@ +// Copyright 2014 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +static mut DROP_RAN: int = 0; + +struct Foo; +impl Drop for Foo { + fn drop(&mut self) { + unsafe { DROP_RAN += 1; } + } +} + +struct Fat { + f: T +} + +pub fn main() { + { + let _x: Box> = box Fat { f: [Foo, Foo, Foo] }; + } + unsafe { + assert!(DROP_RAN == 3); + } +} diff --git a/src/test/run-pass/dst-struct-reflect.rs b/src/test/run-pass/dst-struct-reflect.rs index 297880a8b53..2028ebf64c2 100644 --- a/src/test/run-pass/dst-struct-reflect.rs +++ b/src/test/run-pass/dst-struct-reflect.rs @@ -8,11 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// FIXME(15049) Re-enable this test. +// ignore-test // Test that structs with unsized fields work with {:?} reflection. extern crate debug; -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/run-pass/dst-struct-sole.rs b/src/test/run-pass/dst-struct-sole.rs index 3f01d013cee..04fe6d5cefd 100644 --- a/src/test/run-pass/dst-struct-sole.rs +++ b/src/test/run-pass/dst-struct-sole.rs @@ -10,7 +10,7 @@ // As dst-struct.rs, but the unsized field is the only field in the struct. -struct Fat { +struct Fat { ptr: T } diff --git a/src/test/run-pass/dst-struct.rs b/src/test/run-pass/dst-struct.rs index ae1f854ccab..6b8e25e8559 100644 --- a/src/test/run-pass/dst-struct.rs +++ b/src/test/run-pass/dst-struct.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/run-pass/dst-trait.rs b/src/test/run-pass/dst-trait.rs index 7429136716c..97627309551 100644 --- a/src/test/run-pass/dst-trait.rs +++ b/src/test/run-pass/dst-trait.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -struct Fat { +struct Fat { f1: int, f2: &'static str, ptr: T diff --git a/src/test/run-pass/gc-vec.rs b/src/test/run-pass/gc-vec.rs index d2f43aacd66..430ee16bc8a 100644 --- a/src/test/run-pass/gc-vec.rs +++ b/src/test/run-pass/gc-vec.rs @@ -12,11 +12,11 @@ use std::gc::{GC}; fn main() { // A fixed-size array allocated in a garbage-collected box - let x = box(GC) [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]; + let x = box(GC) [1i, 2, 3, 4, 5, 6, 7, 8, 9, 10]; assert_eq!(x[0], 1); assert_eq!(x[6], 7); assert_eq!(x[9], 10); let y = x; - assert!(*y == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]); + assert!(*y == [1i, 2, 3, 4, 5, 6, 7, 8, 9, 10]); } diff --git a/src/test/run-pass/issue-14936.rs b/src/test/run-pass/issue-14936.rs index 123ad36ee4f..0aca74c76c3 100644 --- a/src/test/run-pass/issue-14936.rs +++ b/src/test/run-pass/issue-14936.rs @@ -30,7 +30,8 @@ macro_rules! demo { : "r"(&wrap(y, "in", &mut history))); } assert_eq!((x,y), (1,1)); - assert_eq!(history.as_slice(), &["out", "in"]); + let b: &[_] = &["out", "in"]; + assert_eq!(history.as_slice(), b); } } } diff --git a/src/test/run-pass/issue-15080.rs b/src/test/run-pass/issue-15080.rs index b0741391d80..444e8bd3770 100644 --- a/src/test/run-pass/issue-15080.rs +++ b/src/test/run-pass/issue-15080.rs @@ -9,7 +9,7 @@ // except according to those terms. fn main() { - let mut x = &[1i, 2, 3, 4]; + let mut x: &[_] = &[1i, 2, 3, 4]; let mut result = vec!(); loop { diff --git a/src/test/run-pass/match-vec-alternatives.rs b/src/test/run-pass/match-vec-alternatives.rs index ffbc4e85cb6..de1bb02bfef 100644 --- a/src/test/run-pass/match-vec-alternatives.rs +++ b/src/test/run-pass/match-vec-alternatives.rs @@ -68,15 +68,21 @@ fn main() { assert_eq!(match_vecs_snoc::(&[], &[]), "both empty"); assert_eq!(match_vecs_snoc(&[1i, 2, 3], &[]), "one empty"); - assert_eq!(match_nested_vecs_cons(None, Ok(&[4u, 2u])), "None, Ok(at least two elements)"); + assert_eq!(match_nested_vecs_cons(None, Ok::<&[_], ()>(&[4u, 2u])), + "None, Ok(at least two elements)"); assert_eq!(match_nested_vecs_cons::(None, Err(())), "None, Ok(less than one element)"); - assert_eq!(match_nested_vecs_cons::(Some(&[]), Ok(&[])), "Some(empty), Ok(empty)"); - assert_eq!(match_nested_vecs_cons(Some(&[1i]), Err(())), "Some(non-empty), any"); - assert_eq!(match_nested_vecs_cons(Some(&[(42i, ())]), Ok(&[(1i, ())])), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_cons::(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), + "Some(empty), Ok(empty)"); + assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[1i]), Err(())), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_cons(Some::<&[_]>(&[(42i, ())]), Ok::<&[_], ()>(&[(1i, ())])), + "Some(non-empty), any"); - assert_eq!(match_nested_vecs_snoc(None, Ok(&[4u, 2u])), "None, Ok(at least two elements)"); + assert_eq!(match_nested_vecs_snoc(None, Ok::<&[_], ()>(&[4u, 2u])), + "None, Ok(at least two elements)"); assert_eq!(match_nested_vecs_snoc::(None, Err(())), "None, Ok(less than one element)"); - assert_eq!(match_nested_vecs_snoc::(Some(&[]), Ok(&[])), "Some(empty), Ok(empty)"); - assert_eq!(match_nested_vecs_snoc(Some(&[1i]), Err(())), "Some(non-empty), any"); - assert_eq!(match_nested_vecs_snoc(Some(&[(42i, ())]), Ok(&[(1i, ())])), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_snoc::(Some::<&[_]>(&[]), Ok::<&[_], ()>(&[])), + "Some(empty), Ok(empty)"); + assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[1i]), Err(())), "Some(non-empty), any"); + assert_eq!(match_nested_vecs_snoc(Some::<&[_]>(&[(42i, ())]), Ok::<&[_], ()>(&[(1i, ())])), + "Some(non-empty), any"); } diff --git a/src/test/run-pass/order-drop-with-match.rs b/src/test/run-pass/order-drop-with-match.rs index ed5cff36c8b..9a76beac9e5 100644 --- a/src/test/run-pass/order-drop-with-match.rs +++ b/src/test/run-pass/order-drop-with-match.rs @@ -59,6 +59,7 @@ fn main() { } } unsafe { - assert_eq!(&[1, 2, 3], ORDER.as_slice()); + let expected: &[_] = &[1, 2, 3]; + assert_eq!(expected, ORDER.as_slice()); } } diff --git a/src/test/run-pass/vec-matching.rs b/src/test/run-pass/vec-matching.rs index 76f3b7bc280..e95495a42d2 100644 --- a/src/test/run-pass/vec-matching.rs +++ b/src/test/run-pass/vec-matching.rs @@ -72,7 +72,8 @@ fn d() { } fn e() { - match &[1i, 2, 3] { + let x: &[int] = &[1i, 2, 3]; + match x { [1, 2] => (), [..] => () } diff --git a/src/test/run-pass/vec-to_str.rs b/src/test/run-pass/vec-to_str.rs index b96761f8b64..52e0ba89479 100644 --- a/src/test/run-pass/vec-to_str.rs +++ b/src/test/run-pass/vec-to_str.rs @@ -9,9 +9,9 @@ // except according to those terms. pub fn main() { - assert_eq!((vec!(0, 1)).to_string(), "[0, 1]".to_string()); + assert_eq!((vec!(0i, 1)).to_string(), "[0, 1]".to_string()); - let foo = vec!(3, 4); + let foo = vec!(3i, 4); let bar: &[int] = &[4, 5]; assert_eq!(foo.to_string(), "[3, 4]".to_string()); -- cgit 1.4.1-3-g733a5