From 81f0bf76672e2f4d30470920e62dc3cfe70bec6c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 24 Sep 2015 09:40:50 -0700 Subject: [PATCH 01/20] std: Switch string::ParseError to an empty enum It can never be instantiated, so signify this by having it actually be an empty `enum`. cc #27734 --- src/libcollections/string.rs | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index bb65d7469ab14..eb6aa4eec30e8 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -1030,8 +1030,8 @@ impl ops::DerefMut for String { #[unstable(feature = "str_parse_error", reason = "may want to be replaced with \ Void if it ever exists", issue = "27734")] -#[derive(Copy, Clone, Debug, Eq, PartialEq)] -pub struct ParseError(()); +#[derive(Copy)] +pub enum ParseError {} #[stable(feature = "rust1", since = "1.0.0")] impl FromStr for String { @@ -1042,6 +1042,26 @@ impl FromStr for String { } } +impl Clone for ParseError { + fn clone(&self) -> ParseError { + match *self {} + } +} + +impl fmt::Debug for ParseError { + fn fmt(&self, _: &mut fmt::Formatter) -> fmt::Result { + match *self {} + } +} + +impl PartialEq for ParseError { + fn eq(&self, _: &ParseError) -> bool { + match *self {} + } +} + +impl Eq for ParseError {} + /// A generic trait for converting a value to a string #[stable(feature = "rust1", since = "1.0.0")] pub trait ToString { From e82bb915e4daede832b3dcb45df6b8f4cc3569c4 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 21 Aug 2015 00:41:07 -0700 Subject: [PATCH 02/20] Fix dllimports of static data from rlibs --- src/librustc_trans/trans/base.rs | 100 +++++++++++++++------- src/test/run-make/msvc-data-only/Makefile | 8 ++ src/test/run-make/msvc-data-only/bar.rs | 15 ++++ src/test/run-make/msvc-data-only/foo.rs | 13 +++ 4 files changed, 105 insertions(+), 31 deletions(-) create mode 100644 src/test/run-make/msvc-data-only/Makefile create mode 100644 src/test/run-make/msvc-data-only/bar.rs create mode 100644 src/test/run-make/msvc-data-only/foo.rs diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index dd0c06c9142e6..02aeb1103539a 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2570,20 +2570,6 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) { unsafe { let mut declared = HashSet::new(); - let iter_globals = |llmod| { - ValueIter { - cur: llvm::LLVMGetFirstGlobal(llmod), - step: llvm::LLVMGetNextGlobal, - } - }; - - let iter_functions = |llmod| { - ValueIter { - cur: llvm::LLVMGetFirstFunction(llmod), - step: llvm::LLVMGetNextFunction, - } - }; - // Collect all external declarations in all compilation units. for ccx in cx.iter() { for val in iter_globals(ccx.llmod()).chain(iter_functions(ccx.llmod())) { @@ -2623,28 +2609,74 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) { } } } +} +// Create a `__imp_ = &symbol` global for every public static `symbol`. +// This is required to satisfy `dllimport` references to static data in .rlibs +// when using MSVC linker. We do this only for data, as linker can fix up +// code references on its own. +// See #26591, #27438 +fn create_imps(cx: &SharedCrateContext, _reachable: &HashSet<&str>) { + unsafe { - struct ValueIter { - cur: ValueRef, - step: unsafe extern "C" fn(ValueRef) -> ValueRef, + for ccx in cx.iter() { + let exported: Vec<_> = iter_globals(ccx.llmod()) + .filter(|&val| llvm::LLVMGetLinkage(val) == llvm::ExternalLinkage as c_uint && + llvm::LLVMIsDeclaration(val) == 0) + .collect(); + + let i8p_ty = Type::i8p(&ccx); + for val in exported { + let name = CStr::from_ptr(llvm::LLVMGetValueName(val)); + let imp_name = String::from("__imp_") + + str::from_utf8(name.to_bytes()).unwrap(); + let imp_name = CString::new(imp_name).unwrap(); + let imp = llvm::LLVMAddGlobal(ccx.llmod(), i8p_ty.to_ref(), + imp_name.as_ptr() as *const _); + llvm::LLVMSetInitializer(imp, llvm::LLVMConstBitCast(val, i8p_ty.to_ref())); + llvm::SetLinkage(imp, llvm::ExternalLinkage); + } + } } +} - impl Iterator for ValueIter { - type Item = ValueRef; +struct ValueIter { + cur: ValueRef, + step: unsafe extern "C" fn(ValueRef) -> ValueRef, +} - fn next(&mut self) -> Option { - let old = self.cur; - if !old.is_null() { - self.cur = unsafe { - let step: unsafe extern "C" fn(ValueRef) -> ValueRef = - mem::transmute_copy(&self.step); - step(old) - }; - Some(old) - } else { - None - } +impl Iterator for ValueIter { + type Item = ValueRef; + + fn next(&mut self) -> Option { + let old = self.cur; + if !old.is_null() { + self.cur = unsafe { + let step: unsafe extern "C" fn(ValueRef) -> ValueRef = + mem::transmute_copy(&self.step); + step(old) + }; + Some(old) + } else { + None + } + } +} + +fn iter_globals(llmod: llvm::ModuleRef) -> ValueIter { + unsafe { + ValueIter { + cur: llvm::LLVMGetFirstGlobal(llmod), + step: llvm::LLVMGetNextGlobal, + } + } +} + +fn iter_functions(llmod: llvm::ModuleRef) -> ValueIter { + unsafe { + ValueIter { + cur: llvm::LLVMGetFirstFunction(llmod), + step: llvm::LLVMGetNextFunction, } } } @@ -2824,6 +2856,12 @@ pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslat &reachable_symbols.iter().map(|x| &x[..]).collect()); } + if sess.target.target.options.is_like_msvc && + sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib || + *ct == config::CrateTypeStaticlib) { + create_imps(&shared_ccx, &reachable_symbols.iter().map(|x| &x[..]).collect()); + } + let metadata_module = ModuleTranslation { llcx: shared_ccx.metadata_llcx(), llmod: shared_ccx.metadata_llmod(), diff --git a/src/test/run-make/msvc-data-only/Makefile b/src/test/run-make/msvc-data-only/Makefile new file mode 100644 index 0000000000000..251a3a9768d78 --- /dev/null +++ b/src/test/run-make/msvc-data-only/Makefile @@ -0,0 +1,8 @@ +# Test that on *-pc-windows-msvc we can link to a rlib containing only data. +# See #26591, #27438 + +-include ../tools.mk + +all: + $(RUSTC) foo.rs + $(RUSTC) bar.rs diff --git a/src/test/run-make/msvc-data-only/bar.rs b/src/test/run-make/msvc-data-only/bar.rs new file mode 100644 index 0000000000000..0e3af9ff3fd48 --- /dev/null +++ b/src/test/run-make/msvc-data-only/bar.rs @@ -0,0 +1,15 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +extern crate foo; + +fn main() { + println!("The answer is {} !", foo::FOO); +} diff --git a/src/test/run-make/msvc-data-only/foo.rs b/src/test/run-make/msvc-data-only/foo.rs new file mode 100644 index 0000000000000..38bff8be125b6 --- /dev/null +++ b/src/test/run-make/msvc-data-only/foo.rs @@ -0,0 +1,13 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +#![crate_type = "rlib"] + +pub static FOO: i32 = 42; From 91f7c60d2d77423ed8f163beb6f76b92de03a09f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Steinbrink?= Date: Fri, 25 Sep 2015 11:02:51 +0200 Subject: [PATCH 03/20] Tell LLVM when a match is exhaustive By putting an "unreachable" instruction into the default arm of a switch instruction we can let LLVM know that the match is exhaustive, allowing for better optimizations. For example, this match: ```rust pub enum Enum { One, Two, Three, } impl Enum { pub fn get_disc(self) -> u8 { match self { Enum::One => 0, Enum::Two => 1, Enum::Three => 2, } } } ``` Currently compiles to this on x86_64: ```asm .cfi_startproc movzbl %dil, %ecx cmpl $1, %ecx setne %al testb %cl, %cl je .LBB0_2 incb %al movb %al, %dil .LBB0_2: movb %dil, %al retq .Lfunc_end0: ``` But with this change we get: ```asm .cfi_startproc movb %dil, %al retq .Lfunc_end0: ``` --- src/librustc_trans/trans/_match.rs | 6 +++++- src/test/codegen/match.rs | 30 ++++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) create mode 100644 src/test/codegen/match.rs diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs index af0780587e8b0..70940345e97d4 100644 --- a/src/librustc_trans/trans/_match.rs +++ b/src/librustc_trans/trans/_match.rs @@ -1283,6 +1283,10 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let exhaustive = chk.is_infallible() && defaults.is_empty(); let len = opts.len(); + if exhaustive && kind == Switch { + build::Unreachable(else_cx); + } + // Compile subtrees for each option for (i, opt) in opts.iter().enumerate() { // In some cases of range and vector pattern matching, we need to @@ -1293,7 +1297,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>, let mut opt_cx = else_cx; let debug_loc = opt.debug_loc(); - if !exhaustive || i + 1 < len { + if kind == Switch || !exhaustive || i + 1 < len { opt_cx = bcx.fcx.new_temp_block("match_case"); match kind { Single => Br(bcx, opt_cx.llbb, debug_loc), diff --git a/src/test/codegen/match.rs b/src/test/codegen/match.rs new file mode 100644 index 0000000000000..ac47f6082e3e3 --- /dev/null +++ b/src/test/codegen/match.rs @@ -0,0 +1,30 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// compile-flags: -C no-prepopulate-passes + +#![crate_type = "lib"] + +pub enum E { + A, + B, +} + +// CHECK-LABEL: @exhaustive_match +#[no_mangle] +pub fn exhaustive_match(e: E) { +// CHECK: switch{{.*}}, label %[[DEFAULT:[a-zA-Z0-9_]+]] +// CHECK: [[DEFAULT]]: +// CHECK-NEXT: unreachable + match e { + E::A => (), + E::B => (), + } +} From db187188098ebce87ad5d9cf0cb2d7faf8673ba5 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Fri, 25 Sep 2015 12:03:03 -0400 Subject: [PATCH 04/20] Simplify `Debug` for `{EnumSet, VecDeque}` --- src/libcollections/enum_set.rs | 11 +---------- src/libcollections/vec_deque.rs | 9 +-------- 2 files changed, 2 insertions(+), 18 deletions(-) diff --git a/src/libcollections/enum_set.rs b/src/libcollections/enum_set.rs index 7e7e8ba2356e3..32cd4193d8855 100644 --- a/src/libcollections/enum_set.rs +++ b/src/libcollections/enum_set.rs @@ -49,16 +49,7 @@ impl Clone for EnumSet { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for EnumSet { fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result { - try!(write!(fmt, "{{")); - let mut first = true; - for e in self { - if !first { - try!(write!(fmt, ", ")); - } - try!(write!(fmt, "{:?}", e)); - first = false; - } - write!(fmt, "}}") + fmt.debug_set().entries(self).finish() } } diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 4ee9787c9ec8a..6de5f27068d47 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1787,14 +1787,7 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque { #[stable(feature = "rust1", since = "1.0.0")] impl fmt::Debug for VecDeque { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - try!(write!(f, "[")); - - for (i, e) in self.iter().enumerate() { - if i != 0 { try!(write!(f, ", ")); } - try!(write!(f, "{:?}", *e)); - } - - write!(f, "]") + f.debug_list().entries(self).finish() } } From d5f2d3b1773d70bf3d32b94ad2a2bf3125bf743e Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 24 Sep 2015 08:38:48 -0700 Subject: [PATCH 05/20] std: Update MatchIndices to return a subslice This commit updates the `MatchIndices` and `RMatchIndices` iterators to follow the same pattern as the `chars` and `char_indices` iterators. The `matches` iterator currently yield `&str` elements, so the `MatchIndices` iterator now yields the index of the match as well as the `&str` that matched (instead of start/end indexes). cc #27743 --- src/libcollections/str.rs | 72 +++++++++++++------------------- src/libcollectionstest/str.rs | 4 +- src/libcore/str/mod.rs | 14 ++++--- src/librustc/session/mod.rs | 4 +- src/test/run-pass/issue-14919.rs | 2 +- 5 files changed, 44 insertions(+), 52 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 2f74ab5026e92..a3d38bdd1b31b 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -1157,25 +1157,21 @@ impl str { core_str::StrExt::rmatches(self, pat) } - /// An iterator over the start and end indices of the disjoint matches - /// of a pattern within `self`. + /// An iterator over the disjoint matches of a pattern within `self` as well + /// as the index that the match starts at. /// /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the first - /// match are returned. + /// corresponding to the first match are returned. /// - /// The pattern can be a simple `&str`, `char`, or a closure that - /// determines if a character matches. - /// Additional libraries might provide more complex patterns like - /// regular expressions. + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// if a character matches. Additional libraries might provide more complex + /// patterns like regular expressions. /// /// # Iterator behavior /// /// The returned iterator will be double ended if the pattern allows a - /// reverse search - /// and forward/reverse search yields the same elements. This is true for, - /// eg, `char` but not - /// for `&str`. + /// reverse search and forward/reverse search yields the same elements. This + /// is true for, eg, `char` but not for `&str`. /// /// If the pattern allows a reverse search but its results might differ /// from a forward search, `rmatch_indices()` can be used. @@ -1185,42 +1181,36 @@ impl str { /// ``` /// #![feature(str_match_indices)] /// - /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".match_indices("abc").collect(); - /// assert_eq!(v, [(0, 3), (6, 9), (12, 15)]); + /// let v: Vec<_> = "abcXXXabcYYYabc".match_indices("abc").collect(); + /// assert_eq!(v, [(0, "abc"), (6, "abc"), (12, "abc")]); /// - /// let v: Vec<(usize, usize)> = "1abcabc2".match_indices("abc").collect(); - /// assert_eq!(v, [(1, 4), (4, 7)]); + /// let v: Vec<_> = "1abcabc2".match_indices("abc").collect(); + /// assert_eq!(v, [(1, "abc"), (4, "abc")]); /// - /// let v: Vec<(usize, usize)> = "ababa".match_indices("aba").collect(); - /// assert_eq!(v, [(0, 3)]); // only the first `aba` + /// let v: Vec<_> = "ababa".match_indices("aba").collect(); + /// assert_eq!(v, [(0, "aba")]); // only the first `aba` /// ``` #[unstable(feature = "str_match_indices", reason = "might have its iterator type changed", issue = "27743")] - // NB: Right now MatchIndices yields `(usize, usize)`, but it would - // be more consistent with `matches` and `char_indices` to return `(usize, &str)` pub fn match_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> MatchIndices<'a, P> { core_str::StrExt::match_indices(self, pat) } - /// An iterator over the start and end indices of the disjoint matches of - /// a pattern within - /// `self`, yielded in reverse order. + /// An iterator over the disjoint matches of a pattern within `self`, + /// yielded in reverse order along with the index of the match. /// /// For matches of `pat` within `self` that overlap, only the indices - /// corresponding to the last - /// match are returned. + /// corresponding to the last match are returned. /// - /// The pattern can be a simple `&str`, `char`, or a closure that - /// determines if a character matches. - /// Additional libraries might provide more complex patterns like - /// regular expressions. + /// The pattern can be a simple `&str`, `char`, or a closure that determines + /// if a character matches. Additional libraries might provide more complex + /// patterns like regular expressions. /// /// # Iterator behavior /// - /// The returned iterator requires that the pattern supports a - /// reverse search, - /// and it will be double ended if a forward/reverse search yields + /// The returned iterator requires that the pattern supports a reverse + /// search, and it will be double ended if a forward/reverse search yields /// the same elements. /// /// For iterating from the front, `match_indices()` can be used. @@ -1230,20 +1220,18 @@ impl str { /// ``` /// #![feature(str_match_indices)] /// - /// let v: Vec<(usize, usize)> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(12, 15), (6, 9), (0, 3)]); + /// let v: Vec<_> = "abcXXXabcYYYabc".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(12, "abc"), (6, "abc"), (0, "abc")]); /// - /// let v: Vec<(usize, usize)> = "1abcabc2".rmatch_indices("abc").collect(); - /// assert_eq!(v, [(4, 7), (1, 4)]); + /// let v: Vec<_> = "1abcabc2".rmatch_indices("abc").collect(); + /// assert_eq!(v, [(4, "abc"), (1, "abc")]); /// - /// let v: Vec<(usize, usize)> = "ababa".rmatch_indices("aba").collect(); - /// assert_eq!(v, [(2, 5)]); // only the last `aba` + /// let v: Vec<_> = "ababa".rmatch_indices("aba").collect(); + /// assert_eq!(v, [(2, "aba")]); // only the last `aba` /// ``` #[unstable(feature = "str_match_indices", reason = "might have its iterator type changed", issue = "27743")] - // NB: Right now RMatchIndices yields `(usize, usize)`, but it would - // be more consistent with `rmatches` and `char_indices` to return `(usize, &str)` pub fn rmatch_indices<'a, P: Pattern<'a>>(&'a self, pat: P) -> RMatchIndices<'a, P> where P::Searcher: ReverseSearcher<'a> { @@ -1416,10 +1404,10 @@ impl str { pub fn replace(&self, from: &str, to: &str) -> String { let mut result = String::new(); let mut last_end = 0; - for (start, end) in self.match_indices(from) { + for (start, part) in self.match_indices(from) { result.push_str(unsafe { self.slice_unchecked(last_end, start) }); result.push_str(to); - last_end = end; + last_end = start + part.len(); } result.push_str(unsafe { self.slice_unchecked(last_end, self.len()) }); result diff --git a/src/libcollectionstest/str.rs b/src/libcollectionstest/str.rs index 7b481f6399116..b4555679e9c1b 100644 --- a/src/libcollectionstest/str.rs +++ b/src/libcollectionstest/str.rs @@ -1047,7 +1047,7 @@ fn test_pattern_deref_forward() { fn test_empty_match_indices() { let data = "aä中!"; let vec: Vec<_> = data.match_indices("").collect(); - assert_eq!(vec, [(0, 0), (1, 1), (3, 3), (6, 6), (7, 7)]); + assert_eq!(vec, [(0, ""), (1, ""), (3, ""), (6, ""), (7, "")]); } #[test] @@ -1477,7 +1477,7 @@ generate_iterator_test! { generate_iterator_test! { double_ended_match_indices { - ("a1b2c3", char::is_numeric) -> [(1, 2), (3, 4), (5, 6)]; + ("a1b2c3", char::is_numeric) -> [(1, "1"), (3, "2"), (5, "3")]; } with str::match_indices, str::rmatch_indices; } diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs index 69ebcb1ab7e14..affa8918884f2 100644 --- a/src/libcore/str/mod.rs +++ b/src/libcore/str/mod.rs @@ -729,15 +729,19 @@ struct MatchIndicesInternal<'a, P: Pattern<'a>>(P::Searcher); impl<'a, P: Pattern<'a>> MatchIndicesInternal<'a, P> { #[inline] - fn next(&mut self) -> Option<(usize, usize)> { - self.0.next_match() + fn next(&mut self) -> Option<(usize, &'a str)> { + self.0.next_match().map(|(start, end)| unsafe { + (start, self.0.haystack().slice_unchecked(start, end)) + }) } #[inline] - fn next_back(&mut self) -> Option<(usize, usize)> + fn next_back(&mut self) -> Option<(usize, &'a str)> where P::Searcher: ReverseSearcher<'a> { - self.0.next_match_back() + self.0.next_match_back().map(|(start, end)| unsafe { + (start, self.0.haystack().slice_unchecked(start, end)) + }) } } @@ -753,7 +757,7 @@ generate_pattern_iterators! { reason = "type may be removed or have its iterator impl changed", issue = "27743")] internal: - MatchIndicesInternal yielding ((usize, usize)); + MatchIndicesInternal yielding ((usize, &'a str)); delegate double ended; } diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs index ff732ee7b9d80..9d1674b74d1fc 100644 --- a/src/librustc/session/mod.rs +++ b/src/librustc/session/mod.rs @@ -331,10 +331,10 @@ fn split_msg_into_multilines(msg: &str) -> Option { let first = msg.match_indices("expected").filter(|s| { s.0 > 0 && (msg.char_at_reverse(s.0) == ' ' || msg.char_at_reverse(s.0) == '(') - }).map(|(a, b)| (a - 1, b)); + }).map(|(a, b)| (a - 1, a + b.len())); let second = msg.match_indices("found").filter(|s| { msg.char_at_reverse(s.0) == ' ' - }).map(|(a, b)| (a - 1, b)); + }).map(|(a, b)| (a - 1, a + b.len())); let mut new_msg = String::new(); let mut head = 0; diff --git a/src/test/run-pass/issue-14919.rs b/src/test/run-pass/issue-14919.rs index 371e926ab18d5..d3c9fe9161ccb 100644 --- a/src/test/run-pass/issue-14919.rs +++ b/src/test/run-pass/issue-14919.rs @@ -59,5 +59,5 @@ fn match_indices<'a, M, T: IntoMatcher<'a, M>>(s: &'a str, from: T) -> MatchIndi fn main() { let s = "abcbdef"; match_indices(s, |c: char| c == 'b') - .collect::>(); + .collect::>(); } From c21fcac29320c065b184cc30973308982a417445 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 25 Sep 2015 18:48:54 -0700 Subject: [PATCH 06/20] Converted test to rpass. --- .../foo.rs => auxiliary/msvc-data-only-lib.rs} | 2 ++ src/test/run-make/msvc-data-only/Makefile | 8 -------- .../msvc-data-only/bar.rs => run-pass/msvc-data-only.rs} | 6 ++++-- 3 files changed, 6 insertions(+), 10 deletions(-) rename src/test/{run-make/msvc-data-only/foo.rs => auxiliary/msvc-data-only-lib.rs} (95%) delete mode 100644 src/test/run-make/msvc-data-only/Makefile rename src/test/{run-make/msvc-data-only/bar.rs => run-pass/msvc-data-only.rs} (78%) diff --git a/src/test/run-make/msvc-data-only/foo.rs b/src/test/auxiliary/msvc-data-only-lib.rs similarity index 95% rename from src/test/run-make/msvc-data-only/foo.rs rename to src/test/auxiliary/msvc-data-only-lib.rs index 38bff8be125b6..71fb9a519489b 100644 --- a/src/test/run-make/msvc-data-only/foo.rs +++ b/src/test/auxiliary/msvc-data-only-lib.rs @@ -8,6 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// no-prefer-dynamic + #![crate_type = "rlib"] pub static FOO: i32 = 42; diff --git a/src/test/run-make/msvc-data-only/Makefile b/src/test/run-make/msvc-data-only/Makefile deleted file mode 100644 index 251a3a9768d78..0000000000000 --- a/src/test/run-make/msvc-data-only/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# Test that on *-pc-windows-msvc we can link to a rlib containing only data. -# See #26591, #27438 - --include ../tools.mk - -all: - $(RUSTC) foo.rs - $(RUSTC) bar.rs diff --git a/src/test/run-make/msvc-data-only/bar.rs b/src/test/run-pass/msvc-data-only.rs similarity index 78% rename from src/test/run-make/msvc-data-only/bar.rs rename to src/test/run-pass/msvc-data-only.rs index 0e3af9ff3fd48..ad6888c4d3096 100644 --- a/src/test/run-make/msvc-data-only/bar.rs +++ b/src/test/run-pass/msvc-data-only.rs @@ -8,8 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -extern crate foo; +// aux-build:msvc-data-only-lib.rs + +extern crate msvc_data_only_lib; fn main() { - println!("The answer is {} !", foo::FOO); + println!("The answer is {} !", msvc_data_only_lib::FOO); } From 38f1c47d18761414cbe69e76b4d76c71afc24789 Mon Sep 17 00:00:00 2001 From: Vadim Chugunov Date: Fri, 25 Sep 2015 18:53:14 -0700 Subject: [PATCH 07/20] Removed unused parameter. --- src/librustc_trans/trans/base.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs index 02aeb1103539a..69268f1fde26f 100644 --- a/src/librustc_trans/trans/base.rs +++ b/src/librustc_trans/trans/base.rs @@ -2616,9 +2616,8 @@ fn internalize_symbols(cx: &SharedCrateContext, reachable: &HashSet<&str>) { // when using MSVC linker. We do this only for data, as linker can fix up // code references on its own. // See #26591, #27438 -fn create_imps(cx: &SharedCrateContext, _reachable: &HashSet<&str>) { +fn create_imps(cx: &SharedCrateContext) { unsafe { - for ccx in cx.iter() { let exported: Vec<_> = iter_globals(ccx.llmod()) .filter(|&val| llvm::LLVMGetLinkage(val) == llvm::ExternalLinkage as c_uint && @@ -2857,9 +2856,8 @@ pub fn trans_crate(tcx: &ty::ctxt, analysis: ty::CrateAnalysis) -> CrateTranslat } if sess.target.target.options.is_like_msvc && - sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib || - *ct == config::CrateTypeStaticlib) { - create_imps(&shared_ccx, &reachable_symbols.iter().map(|x| &x[..]).collect()); + sess.crate_types.borrow().iter().any(|ct| *ct == config::CrateTypeRlib) { + create_imps(&shared_ccx); } let metadata_module = ModuleTranslation { From eef6030c9245a63abb2102425f65b97b35b33568 Mon Sep 17 00:00:00 2001 From: William Throwe Date: Fri, 25 Sep 2015 00:46:33 -0400 Subject: [PATCH 08/20] Don't ICE if an archive isn't actually an archive --- src/librustc_trans/back/archive.rs | 7 +++++-- src/librustc_trans/back/link.rs | 4 ++-- src/test/run-make/invalid-staticlib/Makefile | 5 +++++ 3 files changed, 12 insertions(+), 4 deletions(-) create mode 100644 src/test/run-make/invalid-staticlib/Makefile diff --git a/src/librustc_trans/back/archive.rs b/src/librustc_trans/back/archive.rs index 76bbce00f19dc..1b3242eb97d33 100644 --- a/src/librustc_trans/back/archive.rs +++ b/src/librustc_trans/back/archive.rs @@ -145,10 +145,13 @@ impl<'a> ArchiveBuilder<'a> { /// Adds all of the contents of a native library to this archive. This will /// search in the relevant locations for a library named `name`. - pub fn add_native_library(&mut self, name: &str) -> io::Result<()> { + pub fn add_native_library(&mut self, name: &str) { let location = find_library(name, &self.config.lib_search_paths, self.config.sess); - self.add_archive(&location, name, |_| false) + self.add_archive(&location, name, |_| false).unwrap_or_else(|e| { + self.config.sess.fatal(&format!("failed to add native library {}: {}", + location.to_string_lossy(), e)); + }); } /// Adds all of the contents of the rlib at the specified path to this diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index f25132e1856e8..4e493e6779c66 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -616,7 +616,7 @@ fn link_rlib<'a>(sess: &'a Session, for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() { match kind { - cstore::NativeStatic => ab.add_native_library(&l).unwrap(), + cstore::NativeStatic => ab.add_native_library(&l), cstore::NativeFramework | cstore::NativeUnknown => {} } } @@ -792,7 +792,7 @@ fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, ab.build(); } if !sess.target.target.options.no_compiler_rt { - ab.add_native_library("compiler-rt").unwrap(); + ab.add_native_library("compiler-rt"); } let mut all_native_libs = vec![]; diff --git a/src/test/run-make/invalid-staticlib/Makefile b/src/test/run-make/invalid-staticlib/Makefile new file mode 100644 index 0000000000000..d4aa6d5e72098 --- /dev/null +++ b/src/test/run-make/invalid-staticlib/Makefile @@ -0,0 +1,5 @@ +-include ../tools.mk + +all: + touch $(TMPDIR)/libfoo.a + echo | $(RUSTC) - --crate-type=rlib -lstatic=foo 2>&1 | grep "failed to add native library" From 0f491bee6976191ea977b4e400e6831844766f84 Mon Sep 17 00:00:00 2001 From: DenisKolodin Date: Sat, 26 Sep 2015 12:16:55 +0300 Subject: [PATCH 09/20] Typo fix in use declaration section of reference --- src/doc/reference.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/reference.md b/src/doc/reference.md index eeae2de827ae6..b50e3af0fdd95 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -881,7 +881,7 @@ mod foo { } use foo::example::iter; // good: foo is at crate root -// use example::iter; // bad: core is not at the crate root +// use example::iter; // bad: example is not at the crate root use self::baz::foobaz; // good: self refers to module 'foo' use foo::bar::foobar; // good: foo is at crate root From c099cfab061e8464141a1cf85c2bd09536a311d0 Mon Sep 17 00:00:00 2001 From: Sebastian Wicki Date: Mon, 21 Sep 2015 19:16:24 +0200 Subject: [PATCH 10/20] Add support for the rumprun unikernel For most parts, rumprun currently looks like NetBSD, as they share the same libc and drivers. However, being a unikernel, rumprun does not support process management, signals or virtual memory, so related functions might fail at runtime. Stack guards are disabled exactly for this reason. Code for rumprun is always cross-compiled, it uses always static linking and needs a custom linker. --- configure | 6 ++++ mk/cfg/x86_64-rumprun-netbsd.mk | 24 +++++++++++++ src/liblibc/lib.rs | 6 +++- src/librustc_back/target/mod.rs | 1 + .../target/x86_64_rumprun_netbsd.rs | 35 +++++++++++++++++++ src/libstd/lib.rs | 1 + src/libstd/sys/common/libunwind.rs | 10 +++++- src/libstd/sys/unix/stack_overflow.rs | 4 +-- src/libstd/sys/unix/thread.rs | 4 +-- 9 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 mk/cfg/x86_64-rumprun-netbsd.mk create mode 100644 src/librustc_back/target/x86_64_rumprun_netbsd.rs diff --git a/configure b/configure index 1d95965150cae..fa2117dcc1d3d 100755 --- a/configure +++ b/configure @@ -1295,6 +1295,12 @@ $ pacman -R cmake && pacman -S mingw-w64-x86_64-cmake putvar CFG_MSVC_LIB_PATH_${bits} ;; + *-rumprun-netbsd) + step_msg "targeting rumprun-netbsd, disabling jemalloc" + CFG_DISABLE_JEMALLOC=1 + putvar CFG_DISABLE_JEMALLOC + ;; + *) ;; esac diff --git a/mk/cfg/x86_64-rumprun-netbsd.mk b/mk/cfg/x86_64-rumprun-netbsd.mk new file mode 100644 index 0000000000000..5894805e3e5c9 --- /dev/null +++ b/mk/cfg/x86_64-rumprun-netbsd.mk @@ -0,0 +1,24 @@ +# x86_64-rumprun-netbsd configuration +CROSS_PREFIX_x86_64-rumprun-netbsd=x86_64-rumprun-netbsd- +CC_x86_64-rumprun-netbsd=gcc +CXX_x86_64-rumprun-netbsd=g++ +CPP_x86_64-rumprun-netbsd=gcc -E +AR_x86_64-rumprun-netbsd=ar +CFG_INSTALL_ONLY_RLIB_x86_64-rumprun-netbsd = 1 +CFG_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).so +CFG_STATIC_LIB_NAME_x86_64-rumprun-netbsd=lib$(1).a +CFG_LIB_GLOB_x86_64-rumprun-netbsd=lib$(1)-*.so +CFG_JEMALLOC_CFLAGS_x86_64-rumprun-netbsd := -m64 +CFG_GCCISH_CFLAGS_x86_64-rumprun-netbsd := -Wall -Werror -g -fPIC -m64 +CFG_GCCISH_CXXFLAGS_x86_64-rumprun-netbsd := +CFG_GCCISH_LINK_FLAGS_x86_64-rumprun-netbsd := +CFG_GCCISH_DEF_FLAG_x86_64-rumprun-netbsd := +CFG_LLC_FLAGS_x86_64-rumprun-netbsd := +CFG_INSTALL_NAME_x86_64-rumprun-netbsd = +CFG_EXE_SUFFIX_x86_64-rumprun-netbsd = +CFG_WINDOWSY_x86_64-rumprun-netbsd := +CFG_UNIXY_x86_64-rumprun-netbsd := 1 +CFG_LDPATH_x86_64-rumprun-netbsd := +CFG_RUN_x86_64-rumprun-netbsd=$(2) +CFG_RUN_TARG_x86_64-rumprun-netbsd=$(call CFG_RUN_x86_64-rumprun-netbsd,,$(2)) +CFG_GNU_TRIPLE_x86_64-rumprun-netbsd := x86_64-rumprun-netbsd diff --git a/src/liblibc/lib.rs b/src/liblibc/lib.rs index 2ee69543c3cf3..f75851506c279 100644 --- a/src/liblibc/lib.rs +++ b/src/liblibc/lib.rs @@ -24,6 +24,7 @@ html_playground_url = "https://play.rust-lang.org/", issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")] #![cfg_attr(test, feature(test))] +#![feature(cfg_target_vendor)] //! Bindings for the C standard library and other platform libraries //! @@ -143,7 +144,10 @@ pub use funcs::bsd43::*; // On NaCl, these libraries are static. Thus it would be a Bad Idea to link them // in when creating a test crate. -#[cfg(not(any(windows, target_env = "musl", all(target_os = "nacl", test))))] +#[cfg(not(any(windows, + target_env = "musl", + all(target_os = "nacl", test), + all(target_os = "netbsd", target_vendor = "rumprun"))))] #[link(name = "c")] #[link(name = "m")] extern {} diff --git a/src/librustc_back/target/mod.rs b/src/librustc_back/target/mod.rs index b5847b98af1f6..be404fc97ce08 100644 --- a/src/librustc_back/target/mod.rs +++ b/src/librustc_back/target/mod.rs @@ -411,6 +411,7 @@ impl Target { x86_64_unknown_bitrig, x86_64_unknown_openbsd, x86_64_unknown_netbsd, + x86_64_rumprun_netbsd, x86_64_apple_darwin, i686_apple_darwin, diff --git a/src/librustc_back/target/x86_64_rumprun_netbsd.rs b/src/librustc_back/target/x86_64_rumprun_netbsd.rs new file mode 100644 index 0000000000000..d63ad53cc2bb9 --- /dev/null +++ b/src/librustc_back/target/x86_64_rumprun_netbsd.rs @@ -0,0 +1,35 @@ +// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use target::Target; + +pub fn target() -> Target { + let mut base = super::netbsd_base::opts(); + base.pre_link_args.push("-m64".to_string()); + base.linker = "x86_64-rumprun-netbsd-gcc".to_string(); + base.ar = "x86_64-rumprun-netbsd-ar".to_string(); + + base.dynamic_linking = false; + base.has_rpath = false; + base.position_independent_executables = false; + base.disable_redzone = true; + base.no_default_libraries = false; + + Target { + llvm_target: "x86_64-rumprun-netbsd".to_string(), + target_endian: "little".to_string(), + target_pointer_width: "64".to_string(), + arch: "x86_64".to_string(), + target_os: "netbsd".to_string(), + target_env: "".to_string(), + target_vendor: "rumprun".to_string(), + options: base, + } +} diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c67a4182f54cb..9129ffcc21182 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -204,6 +204,7 @@ #![feature(associated_consts)] #![feature(borrow_state)] #![feature(box_syntax)] +#![feature(cfg_target_vendor)] #![feature(char_from_unchecked)] #![feature(char_internals)] #![feature(clone_from_slice)] diff --git a/src/libstd/sys/common/libunwind.rs b/src/libstd/sys/common/libunwind.rs index c6bffb0f733ee..da7ebbf4ed39f 100644 --- a/src/libstd/sys/common/libunwind.rs +++ b/src/libstd/sys/common/libunwind.rs @@ -108,10 +108,18 @@ extern {} #[link(name = "unwind", kind = "static")] extern {} -#[cfg(any(target_os = "android", target_os = "netbsd", target_os = "openbsd"))] +#[cfg(any(target_os = "android", target_os = "openbsd"))] #[link(name = "gcc")] extern {} +#[cfg(all(target_os = "netbsd", not(target_vendor = "rumprun")))] +#[link(name = "gcc")] +extern {} + +#[cfg(all(target_os = "netbsd", target_vendor = "rumprun"))] +#[link(name = "unwind")] +extern {} + #[cfg(target_os = "dragonfly")] #[link(name = "gcc_pic")] extern {} diff --git a/src/libstd/sys/unix/stack_overflow.rs b/src/libstd/sys/unix/stack_overflow.rs index 441313bc63993..f5fd11b61b1e6 100644 --- a/src/libstd/sys/unix/stack_overflow.rs +++ b/src/libstd/sys/unix/stack_overflow.rs @@ -34,7 +34,7 @@ impl Drop for Handler { #[cfg(any(target_os = "linux", target_os = "macos", target_os = "bitrig", - target_os = "netbsd", + all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd"))] mod imp { use super::Handler; @@ -143,7 +143,7 @@ mod imp { #[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "bitrig", - target_os = "netbsd", + all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd")))] mod imp { use ptr; diff --git a/src/libstd/sys/unix/thread.rs b/src/libstd/sys/unix/thread.rs index 83e0a03a2341e..50e01ecf9fa98 100644 --- a/src/libstd/sys/unix/thread.rs +++ b/src/libstd/sys/unix/thread.rs @@ -174,7 +174,7 @@ impl Drop for Thread { #[cfg(all(not(target_os = "linux"), not(target_os = "macos"), not(target_os = "bitrig"), - not(target_os = "netbsd"), + not(all(target_os = "netbsd", not(target_vendor = "rumprun"))), not(target_os = "openbsd")))] pub mod guard { pub unsafe fn current() -> Option { None } @@ -185,7 +185,7 @@ pub mod guard { #[cfg(any(target_os = "linux", target_os = "macos", target_os = "bitrig", - target_os = "netbsd", + all(target_os = "netbsd", not(target_vendor = "rumprun")), target_os = "openbsd"))] #[allow(unused_imports)] pub mod guard { From 08181d2a3bec3484dc7d0cc7a903922f9d2a302f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 26 Sep 2015 00:03:10 +0200 Subject: [PATCH 11/20] Remove warning of duplicated error code --- src/librustc/middle/check_const.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs index c6ff38d0f093d..b5901762e30d7 100644 --- a/src/librustc/middle/check_const.rs +++ b/src/librustc/middle/check_const.rs @@ -709,20 +709,26 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, if !is_const { v.add_qualif(ConstQualif::NOT_CONST); if v.mode != Mode::Var { + fn span_limited_call_error(tcx: &ty::ctxt, span: Span, s: &str) { + span_err!(tcx.sess, span, E0015, "{}", s); + } + // FIXME(#24111) Remove this check when const fn stabilizes if let UnstableFeatures::Disallow = v.tcx.sess.opts.unstable_features { - span_err!(v.tcx.sess, e.span, E0015, - "function calls in {}s are limited to \ - struct and enum constructors", v.msg()); + span_limited_call_error(&v.tcx, e.span, + &format!("function calls in {}s are limited to \ + struct and enum constructors", + v.msg())); v.tcx.sess.span_note(e.span, "a limited form of compile-time function \ evaluation is available on a nightly \ compiler via `const fn`"); } else { - span_err!(v.tcx.sess, e.span, E0015, - "function calls in {}s are limited to \ - constant functions, \ - struct and enum constructors", v.msg()); + span_limited_call_error(&v.tcx, e.span, + &format!("function calls in {}s are limited \ + to constant functions, \ + struct and enum constructors", + v.msg())); } } } From ded2370a740e7d3b3bd631012f1a724c11b315cf Mon Sep 17 00:00:00 2001 From: David Elliott Date: Sat, 26 Sep 2015 10:36:37 -0700 Subject: [PATCH 12/20] clarify that `find` returns first match the example for `find` was misleading in that it fails to mention the result is either `None` or `Some` containing only the first match. Further confusing the issue is the `println!` statement, "We got some numbers!" --- src/doc/trpl/iterators.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/doc/trpl/iterators.md b/src/doc/trpl/iterators.md index 1c574f02091f8..b52e0fefa57e2 100644 --- a/src/doc/trpl/iterators.md +++ b/src/doc/trpl/iterators.md @@ -150,15 +150,16 @@ let greater_than_forty_two = (0..100) .find(|x| *x > 42); match greater_than_forty_two { - Some(_) => println!("We got some numbers!"), - None => println!("No numbers found :("), + Some(_) => println!("Found a match!"), + None => println!("No match found :("), } ``` `find` takes a closure, and works on a reference to each element of an iterator. This closure returns `true` if the element is the element we're -looking for, and `false` otherwise. Because we might not find a matching -element, `find` returns an `Option` rather than the element itself. +looking for, and `false` otherwise. `find` returns the first element satisfying +the specified predicate. Because we might not find a matching element, `find` +returns an `Option` rather than the element itself. Another important consumer is `fold`. Here's what it looks like: From fe6ad097c654d2655ad11610b2c96d577a3fcc2b Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2015 19:58:00 +0300 Subject: [PATCH 13/20] deduplicate trait errors before they are displayed Because of type inference, duplicate obligations exist and cause duplicate errors. To avoid this, only display the first error for each (predicate,span). The inclusion of the span is somewhat bikesheddy, but *is* the more conservative option (it does not remove some instability, as duplicate obligations are ignored by `duplicate_set` under some inference conditions). Fixes #28098 cc #21528 (is it a dupe?) --- src/librustc/middle/infer/mod.rs | 7 +++- src/librustc/middle/traits/error_reporting.rs | 27 ++++++++++++++ src/librustc/middle/traits/fulfill.rs | 6 ++++ src/librustc/middle/traits/mod.rs | 2 ++ ...ed-types-ICE-when-projecting-out-of-err.rs | 1 - .../compile-fail/associated-types-path-2.rs | 1 - .../compile-fail/coerce-unsafe-to-closure.rs | 1 - .../compile-fail/const-eval-overflow-4b.rs | 2 -- src/test/compile-fail/fn-variance-1.rs | 2 -- src/test/compile-fail/for-loop-bogosity.rs | 3 -- .../compile-fail/indexing-requires-a-uint.rs | 1 - src/test/compile-fail/integral-indexing.rs | 8 ----- src/test/compile-fail/issue-11771.rs | 2 -- src/test/compile-fail/issue-13352.rs | 1 - src/test/compile-fail/issue-14084.rs | 1 - src/test/compile-fail/issue-20605.rs | 3 -- src/test/compile-fail/issue-2149.rs | 1 - src/test/compile-fail/issue-22645.rs | 4 +-- src/test/compile-fail/issue-24352.rs | 1 - src/test/compile-fail/issue-28098.rs | 35 +++++++++++++++++++ .../compile-fail/shift-various-bad-types.rs | 3 -- src/test/compile-fail/str-idx.rs | 1 - src/test/compile-fail/str-mut-idx.rs | 1 - .../unboxed-closures-unsafe-extern-fn.rs | 1 - .../unboxed-closures-wrong-abi.rs | 1 - ...boxed-closures-wrong-arg-type-extern-fn.rs | 1 - 26 files changed, 77 insertions(+), 40 deletions(-) create mode 100644 src/test/compile-fail/issue-28098.rs diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs index 917727907ba88..3def56f94a181 100644 --- a/src/librustc/middle/infer/mod.rs +++ b/src/librustc/middle/infer/mod.rs @@ -43,7 +43,7 @@ use std::rc::Rc; use syntax::ast; use syntax::codemap; use syntax::codemap::{Span, DUMMY_SP}; -use util::nodemap::{FnvHashMap, NodeMap}; +use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap}; use self::combine::CombineFields; use self::region_inference::{RegionVarBindings, RegionSnapshot}; @@ -92,6 +92,10 @@ pub struct InferCtxt<'a, 'tcx: 'a> { pub fulfillment_cx: RefCell>, + // the set of predicates on which errors have been reported, to + // avoid reporting the same error twice. + pub reported_trait_errors: RefCell>>, + // This is a temporary field used for toggling on normalization in the inference context, // as we move towards the approach described here: // https://internals.rust-lang.org/t/flattening-the-contexts-for-fun-and-profit/2293 @@ -374,6 +378,7 @@ pub fn new_infer_ctxt<'a, 'tcx>(tcx: &'a ty::ctxt<'tcx>, region_vars: RegionVarBindings::new(tcx), parameter_environment: param_env.unwrap_or(tcx.empty_parameter_environment()), fulfillment_cx: RefCell::new(traits::FulfillmentContext::new(errors_will_be_reported)), + reported_trait_errors: RefCell::new(FnvHashSet()), normalize: false, err_count_on_creation: tcx.sess.err_count() } diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index 25e6036e85ab4..c6c438f1d83c4 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -33,6 +33,26 @@ use std::fmt; use syntax::codemap::Span; use syntax::attr::{AttributeMethods, AttrMetaMethods}; +#[derive(Debug, PartialEq, Eq, Hash)] +pub struct TraitErrorKey<'tcx> { + is_warning: bool, + span: Span, + predicate: ty::Predicate<'tcx> +} + +impl<'tcx> TraitErrorKey<'tcx> { + fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>, + e: &FulfillmentError<'tcx>) -> Self { + let predicate = + infcx.resolve_type_vars_if_possible(&e.obligation.predicate); + TraitErrorKey { + is_warning: is_warning(&e.obligation), + span: e.obligation.cause.span, + predicate: infcx.tcx.erase_regions(&predicate) + } + } +} + pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, errors: &Vec>) { for error in errors { @@ -42,6 +62,13 @@ pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, error: &FulfillmentError<'tcx>) { + let error_key = TraitErrorKey::from_error(infcx, error); + debug!("report_fulfillment_errors({:?}) - key={:?}", + error, error_key); + if !infcx.reported_trait_errors.borrow_mut().insert(error_key) { + debug!("report_fulfillment_errors: skipping duplicate"); + return; + } match error.code { FulfillmentErrorCode::CodeSelectionError(ref e) => { report_selection_error(infcx, &error.obligation, e); diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs index 29032f0c4719a..d4e6f693d965d 100644 --- a/src/librustc/middle/traits/fulfill.rs +++ b/src/librustc/middle/traits/fulfill.rs @@ -49,6 +49,12 @@ pub struct FulfillmentContext<'tcx> { // than the `SelectionCache`: it avoids duplicate errors and // permits recursive obligations, which are often generated from // traits like `Send` et al. + // + // Note that because of type inference, a predicate can still + // occur twice in the predicates list, for example when 2 + // initially-distinct type variables are unified after being + // inserted. Deduplicating the predicate set on selection had a + // significant performance cost the last time I checked. duplicate_set: FulfilledPredicates<'tcx>, // A list of all obligations that have been registered with this diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs index 5dc6f9454a881..a037621f5c025 100644 --- a/src/librustc/middle/traits/mod.rs +++ b/src/librustc/middle/traits/mod.rs @@ -21,10 +21,12 @@ use middle::subst; use middle::ty::{self, HasTypeFlags, Ty}; use middle::ty::fold::TypeFoldable; use middle::infer::{self, fixup_err_to_string, InferCtxt}; + use std::rc::Rc; use syntax::ast; use syntax::codemap::{Span, DUMMY_SP}; +pub use self::error_reporting::TraitErrorKey; pub use self::error_reporting::report_fulfillment_errors; pub use self::error_reporting::report_overflow_error; pub use self::error_reporting::report_selection_error; diff --git a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs index 4aad828590a30..c5a47f3e5358f 100644 --- a/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs +++ b/src/test/compile-fail/associated-types-ICE-when-projecting-out-of-err.rs @@ -32,5 +32,4 @@ fn ice(a: A) { let r = loop {}; r = r + a; //~^ ERROR not implemented - //~| ERROR not implemented } diff --git a/src/test/compile-fail/associated-types-path-2.rs b/src/test/compile-fail/associated-types-path-2.rs index e603cca7f384b..c9374d4293800 100644 --- a/src/test/compile-fail/associated-types-path-2.rs +++ b/src/test/compile-fail/associated-types-path-2.rs @@ -39,7 +39,6 @@ pub fn f1_int_uint() { pub fn f1_uint_uint() { f1(2u32, 4u32); //~^ ERROR the trait `Foo` is not implemented - //~| ERROR the trait `Foo` is not implemented } pub fn f1_uint_int() { diff --git a/src/test/compile-fail/coerce-unsafe-to-closure.rs b/src/test/compile-fail/coerce-unsafe-to-closure.rs index 27b4a04054f07..90cbbf242aad4 100644 --- a/src/test/compile-fail/coerce-unsafe-to-closure.rs +++ b/src/test/compile-fail/coerce-unsafe-to-closure.rs @@ -11,5 +11,4 @@ fn main() { let x: Option<&[u8]> = Some("foo").map(std::mem::transmute); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/const-eval-overflow-4b.rs b/src/test/compile-fail/const-eval-overflow-4b.rs index 6322b56a82f00..a8f47ab92e529 100644 --- a/src/test/compile-fail/const-eval-overflow-4b.rs +++ b/src/test/compile-fail/const-eval-overflow-4b.rs @@ -23,7 +23,6 @@ const A_I8_T : [u32; (i8::MAX as i8 + 1u8) as usize] //~^ ERROR mismatched types //~| the trait `core::ops::Add` is not implemented for the type `i8` - //~| the trait `core::ops::Add` is not implemented for the type `i8` = [0; (i8::MAX as usize) + 1]; fn main() { @@ -33,4 +32,3 @@ fn main() { fn foo(x: T) { println!("{:?}", x); } - diff --git a/src/test/compile-fail/fn-variance-1.rs b/src/test/compile-fail/fn-variance-1.rs index 8e1e88a92e452..e9dd1cb719dbc 100644 --- a/src/test/compile-fail/fn-variance-1.rs +++ b/src/test/compile-fail/fn-variance-1.rs @@ -20,10 +20,8 @@ fn main() { apply(&3, takes_imm); apply(&3, takes_mut); //~^ ERROR (values differ in mutability) - //~| ERROR (values differ in mutability) apply(&mut 3, takes_mut); apply(&mut 3, takes_imm); //~^ ERROR (values differ in mutability) - //~| ERROR (values differ in mutability) } diff --git a/src/test/compile-fail/for-loop-bogosity.rs b/src/test/compile-fail/for-loop-bogosity.rs index 6bc0e74a2eb58..c77683045170e 100644 --- a/src/test/compile-fail/for-loop-bogosity.rs +++ b/src/test/compile-fail/for-loop-bogosity.rs @@ -25,9 +25,6 @@ pub fn main() { y: 2, }; for x in bogus { //~ ERROR `core::iter::Iterator` is not implemented for the type `MyStruct` - //~^ ERROR - //~^^ ERROR - // FIXME(#21528) not fulfilled obligation error should be reported once, not thrice drop(x); } } diff --git a/src/test/compile-fail/indexing-requires-a-uint.rs b/src/test/compile-fail/indexing-requires-a-uint.rs index 3ca00fcb66ac1..3d3b7bc1bcb43 100644 --- a/src/test/compile-fail/indexing-requires-a-uint.rs +++ b/src/test/compile-fail/indexing-requires-a-uint.rs @@ -14,7 +14,6 @@ fn main() { fn bar(_: T) {} [0][0u8]; //~ ERROR: the trait `core::ops::Index` is not implemented - //~^ ERROR: the trait `core::ops::Index` is not implemented [0][0]; // should infer to be a usize diff --git a/src/test/compile-fail/integral-indexing.rs b/src/test/compile-fail/integral-indexing.rs index e2fb0fa4f2fa5..f78d677679bc8 100644 --- a/src/test/compile-fail/integral-indexing.rs +++ b/src/test/compile-fail/integral-indexing.rs @@ -14,21 +14,13 @@ pub fn main() { v[3_usize]; v[3]; v[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented v[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented v[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented v[3i32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3_usize]; s.as_bytes()[3]; s.as_bytes()[3u8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3i8]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3u32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented s.as_bytes()[3i32]; //~ERROR the trait `core::ops::Index` is not implemented - //~^ ERROR the trait `core::ops::Index` is not implemented } diff --git a/src/test/compile-fail/issue-11771.rs b/src/test/compile-fail/issue-11771.rs index 40fc6b1ed6aaa..69899105bc317 100644 --- a/src/test/compile-fail/issue-11771.rs +++ b/src/test/compile-fail/issue-11771.rs @@ -12,12 +12,10 @@ fn main() { let x = (); 1 + x //~^ ERROR E0277 - //~| ERROR E0277 ; let x: () = (); 1 + x //~^ ERROR E0277 - //~| ERROR E0277 ; } diff --git a/src/test/compile-fail/issue-13352.rs b/src/test/compile-fail/issue-13352.rs index 14128a0e6f7ec..13e677d72bc1e 100644 --- a/src/test/compile-fail/issue-13352.rs +++ b/src/test/compile-fail/issue-13352.rs @@ -18,5 +18,4 @@ fn main() { }); 2_usize + (loop {}); //~^ ERROR E0277 - //~| ERROR E0277 } diff --git a/src/test/compile-fail/issue-14084.rs b/src/test/compile-fail/issue-14084.rs index b2863202ef0cf..6b19cb0b68f10 100644 --- a/src/test/compile-fail/issue-14084.rs +++ b/src/test/compile-fail/issue-14084.rs @@ -14,5 +14,4 @@ fn main() { in () { 0 }; //~^ ERROR: the trait `core::ops::Placer<_>` is not implemented - //~| ERROR: the trait `core::ops::Placer<_>` is not implemented } diff --git a/src/test/compile-fail/issue-20605.rs b/src/test/compile-fail/issue-20605.rs index 87b7616db8ed2..f2d65af9cdfc8 100644 --- a/src/test/compile-fail/issue-20605.rs +++ b/src/test/compile-fail/issue-20605.rs @@ -11,9 +11,6 @@ fn changer<'a>(mut things: Box>) { for item in *things { *item = 0 } //~^ ERROR the trait `core::marker::Sized` is not implemented for the type `core::iter::Iterator -//~^^ ERROR -//~^^^ ERROR -// FIXME(#21528) error should be reported once, not thrice } fn main() {} diff --git a/src/test/compile-fail/issue-2149.rs b/src/test/compile-fail/issue-2149.rs index bb170ef7d0036..256c5d8e6f72c 100644 --- a/src/test/compile-fail/issue-2149.rs +++ b/src/test/compile-fail/issue-2149.rs @@ -17,7 +17,6 @@ impl vec_monad for Vec { let mut r = panic!(); for elt in self { r = r + f(*elt); } //~^ ERROR E0277 - //~| ERROR E0277 } } fn main() { diff --git a/src/test/compile-fail/issue-22645.rs b/src/test/compile-fail/issue-22645.rs index 8677934fd646c..aa7fa82fa29ba 100644 --- a/src/test/compile-fail/issue-22645.rs +++ b/src/test/compile-fail/issue-22645.rs @@ -23,7 +23,5 @@ impl Add for Bob { fn main() { let b = Bob + 3.5; b + 3 //~ ERROR: is not implemented - //~^ ERROR: is not implemented - //~^^ ERROR: is not implemented - //~^^^ ERROR: mismatched types + //~^ ERROR: mismatched types } diff --git a/src/test/compile-fail/issue-24352.rs b/src/test/compile-fail/issue-24352.rs index 0fbc634826bc5..9936f67b3af3c 100644 --- a/src/test/compile-fail/issue-24352.rs +++ b/src/test/compile-fail/issue-24352.rs @@ -11,5 +11,4 @@ fn main() { 1.0f64 - 1.0; 1.0f64 - 1 //~ ERROR: is not implemented - //~^ ERROR: is not implemented } diff --git a/src/test/compile-fail/issue-28098.rs b/src/test/compile-fail/issue-28098.rs new file mode 100644 index 0000000000000..f565d24e1fd08 --- /dev/null +++ b/src/test/compile-fail/issue-28098.rs @@ -0,0 +1,35 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +fn main() { + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + for _ in false {} + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + other() +} + +pub fn other() { + // check errors are still reported globally + + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + let _ = Iterator::next(&mut ()); + //~^ ERROR the trait `core::iter::Iterator` is not implemented + + for _ in false {} + //~^ ERROR the trait `core::iter::Iterator` is not implemented +} diff --git a/src/test/compile-fail/shift-various-bad-types.rs b/src/test/compile-fail/shift-various-bad-types.rs index 24b66213b39bd..c980572fa152f 100644 --- a/src/test/compile-fail/shift-various-bad-types.rs +++ b/src/test/compile-fail/shift-various-bad-types.rs @@ -18,15 +18,12 @@ struct Panolpy { fn foo(p: &Panolpy) { 22 >> p.char; //~^ ERROR E0277 - //~| ERROR E0277 22 >> p.str; //~^ ERROR E0277 - //~| ERROR E0277 22 >> p; //~^ ERROR E0277 - //~| ERROR E0277 let x; 22 >> x; // ambiguity error winds up being suppressed diff --git a/src/test/compile-fail/str-idx.rs b/src/test/compile-fail/str-idx.rs index ddd2a4eeedf76..6e48ae20d09f3 100644 --- a/src/test/compile-fail/str-idx.rs +++ b/src/test/compile-fail/str-idx.rs @@ -11,5 +11,4 @@ pub fn main() { let s: &str = "hello"; let c: u8 = s[4]; //~ ERROR the trait `core::ops::Index<_>` is not implemented - //~^ ERROR the trait `core::ops::Index<_>` is not implemented } diff --git a/src/test/compile-fail/str-mut-idx.rs b/src/test/compile-fail/str-mut-idx.rs index 73abe6cb59db2..ec6a14778a463 100644 --- a/src/test/compile-fail/str-mut-idx.rs +++ b/src/test/compile-fail/str-mut-idx.rs @@ -17,7 +17,6 @@ fn mutate(s: &mut str) { s[1usize] = bot(); //~^ ERROR `core::ops::Index` is not implemented for the type `str` //~| ERROR `core::ops::IndexMut` is not implemented for the type `str` - //~| ERROR `core::ops::Index` is not implemented for the type `str` } pub fn main() {} diff --git a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs index dc7c70ba649d8..361df93a71669 100644 --- a/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-unsafe-extern-fn.rs @@ -35,7 +35,6 @@ fn b() { fn c() { let z = call_it_once(square, 22); //~^ ERROR not implemented - //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-wrong-abi.rs b/src/test/compile-fail/unboxed-closures-wrong-abi.rs index cdcb435b65a6a..ca15d1bb5eefc 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-abi.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-abi.rs @@ -35,7 +35,6 @@ fn b() { fn c() { let z = call_it_once(square, 22); //~^ ERROR not implemented - //~| ERROR not implemented } fn main() { } diff --git a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs index 150bf36dcc286..b960362aad7cd 100644 --- a/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs +++ b/src/test/compile-fail/unboxed-closures-wrong-arg-type-extern-fn.rs @@ -36,7 +36,6 @@ fn b() { fn c() { let z = call_it_once(square, 22); //~^ ERROR not implemented - //~| ERROR not implemented } fn main() { } From c3a74fa4c6239f7396b0d1980c2510ffed8501af Mon Sep 17 00:00:00 2001 From: Florian Hartwig Date: Sat, 26 Sep 2015 20:40:22 +0200 Subject: [PATCH 14/20] Elide lifetime in Deref doc example --- src/libcore/ops.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index 350ade22707ca..582c091091fb2 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -1628,7 +1628,7 @@ impl fmt::Debug for RangeTo { /// impl Deref for DerefExample { /// type Target = T; /// -/// fn deref<'a>(&'a self) -> &'a T { +/// fn deref(&self) -> &T { /// &self.value /// } /// } From 346088b555b5dd7ec2a156d82c5362632f9b8972 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Fri, 25 Sep 2015 02:40:57 +0300 Subject: [PATCH 15/20] show each object-safety violation once different supertraits can suffer from the same object-safety violation, leading to duplication in the error message. Avoid it. Fixes #20692 --- src/librustc/middle/traits/error_reporting.rs | 9 ++++++-- src/librustc/middle/traits/object_safety.rs | 2 +- src/librustc/middle/ty/mod.rs | 14 +++++++++++ src/test/compile-fail/issue-20692.rs | 23 +++++++++++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) create mode 100644 src/test/compile-fail/issue-20692.rs diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs index c6c438f1d83c4..43b3831604bbf 100644 --- a/src/librustc/middle/traits/error_reporting.rs +++ b/src/librustc/middle/traits/error_reporting.rs @@ -28,7 +28,8 @@ use middle::def_id::DefId; use middle::infer::InferCtxt; use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef, Ty}; use middle::ty::fold::TypeFoldable; -use std::collections::HashMap; +use util::nodemap::{FnvHashMap, FnvHashSet}; + use std::fmt; use syntax::codemap::Span; use syntax::attr::{AttributeMethods, AttrMetaMethods}; @@ -124,7 +125,7 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>, (gen.name.as_str().to_string(), trait_ref.substs.types.get(param, i) .to_string()) - }).collect::>(); + }).collect::>(); generic_map.insert("Self".to_string(), trait_ref.self_ty().to_string()); let parser = Parser::new(&istring); @@ -335,7 +336,11 @@ pub fn report_object_safety_error<'tcx>(tcx: &ty::ctxt<'tcx>, "the trait `{}` cannot be made into an object", tcx.item_path_str(trait_def_id)); + let mut reported_violations = FnvHashSet(); for violation in violations { + if !reported_violations.insert(violation.clone()) { + continue; + } match violation { ObjectSafetyViolation::SizedSelf => { tcx.sess.fileline_note( diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs index 1762233b0449a..5768e13c5bf2d 100644 --- a/src/librustc/middle/traits/object_safety.rs +++ b/src/librustc/middle/traits/object_safety.rs @@ -27,7 +27,7 @@ use middle::ty::{self, ToPolyTraitRef, Ty}; use std::rc::Rc; use syntax::ast; -#[derive(Debug)] +#[derive(Clone, Debug, PartialEq, Eq, Hash)] pub enum ObjectSafetyViolation<'tcx> { /// Self : Sized declared on the trait SizedSelf, diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index 972f7242808b6..a726b4f5b6673 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -272,6 +272,20 @@ impl<'tcx> Method<'tcx> { } } +impl<'tcx> PartialEq for Method<'tcx> { + #[inline] + fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id } +} + +impl<'tcx> Eq for Method<'tcx> {} + +impl<'tcx> Hash for Method<'tcx> { + #[inline] + fn hash(&self, s: &mut H) { + self.def_id.hash(s) + } +} + #[derive(Clone, Copy, Debug)] pub struct AssociatedConst<'tcx> { pub name: Name, diff --git a/src/test/compile-fail/issue-20692.rs b/src/test/compile-fail/issue-20692.rs new file mode 100644 index 0000000000000..62d775adac3c7 --- /dev/null +++ b/src/test/compile-fail/issue-20692.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +trait Array: Sized {} + +fn f(x: &T) { + let _ = x + //~^ ERROR `Array` cannot be made into an object + //~| NOTE the trait cannot require that `Self : Sized` + as + &Array; + //~^ ERROR `Array` cannot be made into an object + //~| NOTE the trait cannot require that `Self : Sized` +} + +fn main() {} From 3885a81e5fa9913075537c9df857fa1753c5d7c1 Mon Sep 17 00:00:00 2001 From: Xavier Shay Date: Sat, 26 Sep 2015 11:59:00 -0700 Subject: [PATCH 16/20] Add an example of constructing a unit-like struct. This was non-obvious to me: with no example, I assumed `Electron {}` and didn't know what else to try when it didn't work. The correct form is weird because it looks like you're assigning the struct name rather than an instance of the struct. --- src/doc/trpl/structs.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/doc/trpl/structs.md b/src/doc/trpl/structs.md index 85b11d0b6b5ee..b51ad8e087d22 100644 --- a/src/doc/trpl/structs.md +++ b/src/doc/trpl/structs.md @@ -184,6 +184,8 @@ You can define a `struct` with no members at all: ```rust struct Electron; + +let x = Electron; ``` Such a `struct` is called ‘unit-like’ because it resembles the empty From 865889a2ccf6c217df158b5e088b2fba71e86da4 Mon Sep 17 00:00:00 2001 From: Xavier Shay Date: Sat, 26 Sep 2015 12:03:42 -0700 Subject: [PATCH 17/20] Fix meta-documentation for generating all docs. This wasn't complete (you need a `./configure`), and it is already documented well in the main README. Also adds a reference to the books that this also generates. --- src/doc/README.md | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/doc/README.md b/src/doc/README.md index c09f28ae4f62d..0882b073ea48c 100644 --- a/src/doc/README.md +++ b/src/doc/README.md @@ -2,9 +2,10 @@ ## Building -To generate all the docs, just run `make docs` from the root of the repository. -This will convert the distributed Markdown docs to HTML and generate HTML doc -for the 'std' and 'extra' libraries. +To generate all the docs, follow the "Building Documentation" instructions in +the README in the root of the repository. This will convert the distributed +Markdown docs to HTML and generate HTML doc for the books, 'std' and 'extra' +libraries. To generate HTML documentation from one source file/crate, do something like: From 589c82449a8a2fc339757f12001e9309903791e3 Mon Sep 17 00:00:00 2001 From: Andrew Paseltiner Date: Sat, 26 Sep 2015 14:40:22 -0400 Subject: [PATCH 18/20] Remove unnecessary `#![feature]` attributes --- src/libcollections/str.rs | 2 -- src/libcollections/vec.rs | 2 -- src/libcollections/vec_deque.rs | 4 ---- src/libcollectionstest/lib.rs | 5 ----- src/librustc_front/lib.rs | 1 - src/libstd/lib.rs | 4 ++-- 6 files changed, 2 insertions(+), 16 deletions(-) diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 2f74ab5026e92..350f17e44b83a 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -506,8 +506,6 @@ impl str { /// /// # Examples /// ``` - /// #![feature(str_split_at)] - /// /// let s = "Löwe 老虎 Léopard"; /// let first_space = s.find(' ').unwrap_or(s.len()); /// let (a, b) = s.split_at(first_space); diff --git a/src/libcollections/vec.rs b/src/libcollections/vec.rs index de3e6f94e8746..cc4db40ff802c 100644 --- a/src/libcollections/vec.rs +++ b/src/libcollections/vec.rs @@ -753,8 +753,6 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(split_off)] - /// /// let mut vec = vec![1,2,3]; /// let vec2 = vec.split_off(1); /// assert_eq!(vec, [1]); diff --git a/src/libcollections/vec_deque.rs b/src/libcollections/vec_deque.rs index 4ee9787c9ec8a..9dd9805d2afbb 100644 --- a/src/libcollections/vec_deque.rs +++ b/src/libcollections/vec_deque.rs @@ -1319,8 +1319,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(split_off)] - /// /// use std::collections::VecDeque; /// /// let mut buf: VecDeque<_> = vec![1,2,3].into_iter().collect(); @@ -1406,8 +1404,6 @@ impl VecDeque { /// # Examples /// /// ``` - /// #![feature(vec_deque_retain)] - /// /// use std::collections::VecDeque; /// /// let mut buf = VecDeque::new(); diff --git a/src/libcollectionstest/lib.rs b/src/libcollectionstest/lib.rs index d84f5bdf10785..63c7bc15c8fc6 100644 --- a/src/libcollectionstest/lib.rs +++ b/src/libcollectionstest/lib.rs @@ -9,7 +9,6 @@ // except according to those terms. #![feature(ascii)] -#![feature(append)] #![feature(binary_heap_extras)] #![feature(box_syntax)] #![feature(btree_range)] @@ -29,18 +28,14 @@ #![feature(set_recovery)] #![feature(slice_bytes)] #![feature(slice_splits)] -#![feature(split_off)] #![feature(step_by)] #![feature(str_char)] #![feature(str_escape)] #![feature(str_match_indices)] -#![feature(str_split_at)] #![feature(str_utf16)] -#![feature(box_str)] #![feature(test)] #![feature(unboxed_closures)] #![feature(unicode)] -#![feature(vec_deque_retain)] #![feature(vec_push_all)] #[macro_use] extern crate log; diff --git a/src/librustc_front/lib.rs b/src/librustc_front/lib.rs index 4c6d8505c81f0..fa2c098e2cff7 100644 --- a/src/librustc_front/lib.rs +++ b/src/librustc_front/lib.rs @@ -36,7 +36,6 @@ #![feature(staged_api)] #![feature(str_char)] #![feature(filling_drop)] -#![cfg_attr(test, feature(test))] extern crate serialize; #[macro_use] extern crate log; diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index c67a4182f54cb..cb36b0c1f5a3d 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -248,8 +248,8 @@ #![feature(wrapping)] #![feature(zero_one)] #![cfg_attr(windows, feature(str_utf16))] -#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras, hash_default))] -#![cfg_attr(test, feature(test, rustc_private, float_consts))] +#![cfg_attr(test, feature(float_from_str_radix, range_inclusive, float_extras))] +#![cfg_attr(test, feature(test, rustc_private))] #![cfg_attr(target_env = "msvc", feature(link_args))] // Don't link to std. We are std. From f9b703e7ab10383236ff687870c186220019f442 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 26 Sep 2015 22:25:49 +0300 Subject: [PATCH 19/20] remove the destructors table --- src/librustc/middle/reachable.rs | 14 +++++++++----- src/librustc/middle/ty/context.rs | 4 ---- src/librustc/middle/ty/mod.rs | 5 ----- src/librustc_lint/builtin.rs | 19 +++++++++---------- src/librustc_typeck/check/method/confirm.rs | 8 +------- src/librustc_typeck/check/mod.rs | 10 ++++++---- src/librustc_typeck/coherence/mod.rs | 7 ++----- 7 files changed, 27 insertions(+), 40 deletions(-) diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 3fb3d575f93c6..017c8f1e42bec 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -348,13 +348,17 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { // this properly would result in the necessity of computing *type* // reachability, which might result in a compile time loss. fn mark_destructors_reachable(&mut self) { - for adt in self.tcx.adt_defs() { - if let Some(destructor_def_id) = adt.destructor() { - if destructor_def_id.is_local() { - self.reachable_symbols.insert(destructor_def_id.node); + let drop_trait = match self.tcx.lang_items.drop_trait() { + Some(id) => self.tcx.lookup_trait_def(id), None => { return } + }; + drop_trait.for_each_impl(self.tcx, |drop_impl| { + for destructor in &self.tcx.impl_items.borrow()[&drop_impl] { + let destructor_did = destructor.def_id(); + if destructor_did.is_local() { + self.reachable_symbols.insert(destructor_did.node); } } - } + }) } } diff --git a/src/librustc/middle/ty/context.rs b/src/librustc/middle/ty/context.rs index 31e4765aaaa60..f32e86e276c71 100644 --- a/src/librustc/middle/ty/context.rs +++ b/src/librustc/middle/ty/context.rs @@ -245,9 +245,6 @@ pub struct ctxt<'tcx> { /// True if the variance has been computed yet; false otherwise. pub variance_computed: Cell, - /// A method will be in this list if and only if it is a destructor. - pub destructors: RefCell, - /// Maps a DefId of a type to a list of its inherent impls. /// Contains implementations of methods that are inherent to a type. /// Methods in these implementations don't need to be exported. @@ -475,7 +472,6 @@ impl<'tcx> ctxt<'tcx> { normalized_cache: RefCell::new(FnvHashMap()), lang_items: lang_items, provided_method_sources: RefCell::new(DefIdMap()), - destructors: RefCell::new(DefIdSet()), inherent_impls: RefCell::new(DefIdMap()), impl_items: RefCell::new(DefIdMap()), used_unsafe: RefCell::new(NodeSet()), diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index a726b4f5b6673..eb93c58f38c55 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -2329,11 +2329,6 @@ impl<'tcx> ctxt<'tcx> { self.lookup_adt_def_master(did) } - /// Return the list of all interned ADT definitions - pub fn adt_defs(&self) -> Vec> { - self.adt_defs.borrow().values().cloned().collect() - } - /// Given the did of an item, returns its full set of predicates. pub fn lookup_predicates(&self, did: DefId) -> GenericPredicates<'tcx> { lookup_locally_or_in_crate_store( diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 111913adb8aa8..dbd6286e42606 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -1213,15 +1213,14 @@ impl LintPass for DropWithReprExtern { impl LateLintPass for DropWithReprExtern { fn check_crate(&mut self, ctx: &LateContext, _: &hir::Crate) { - for dtor_did in ctx.tcx.destructors.borrow().iter() { - let (drop_impl_did, dtor_self_type) = - if dtor_did.is_local() { - let impl_did = ctx.tcx.map.get_parent_did(dtor_did.node); - let ty = ctx.tcx.lookup_item_type(impl_did).ty; - (impl_did, ty) - } else { - continue; - }; + let drop_trait = match ctx.tcx.lang_items.drop_trait() { + Some(id) => ctx.tcx.lookup_trait_def(id), None => { return } + }; + drop_trait.for_each_impl(ctx.tcx, |drop_impl_did| { + if !drop_impl_did.is_local() { + return; + } + let dtor_self_type = ctx.tcx.lookup_item_type(drop_impl_did).ty; match dtor_self_type.sty { ty::TyEnum(self_type_def, _) | @@ -1247,6 +1246,6 @@ impl LateLintPass for DropWithReprExtern { } _ => {} } - } + }) } } diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs index abdcbf099a57a..b0e81803ba72f 100644 --- a/src/librustc_typeck/check/method/confirm.rs +++ b/src/librustc_typeck/check/method/confirm.rs @@ -620,13 +620,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> { ty::TraitContainer(trait_def_id) => { callee::check_legal_trait_for_method_call(self.fcx.ccx, self.span, trait_def_id) } - ty::ImplContainer(..) => { - // Since `drop` is a trait method, we expect that any - // potential calls to it will wind up in the other - // arm. But just to be sure, check that the method id - // does not appear in the list of destructors. - assert!(!self.tcx().destructors.borrow().contains(&pick.item.def_id())); - } + ty::ImplContainer(..) => {} } } diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index dec2e49272b48..66a3790e52d44 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -431,9 +431,11 @@ pub fn check_item_bodies(ccx: &CrateCtxt) { } pub fn check_drop_impls(ccx: &CrateCtxt) { - for drop_method_did in ccx.tcx.destructors.borrow().iter() { - if drop_method_did.is_local() { - let drop_impl_did = ccx.tcx.map.get_parent_did(drop_method_did.node); + let drop_trait = match ccx.tcx.lang_items.drop_trait() { + Some(id) => ccx.tcx.lookup_trait_def(id), None => { return } + }; + drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| { + if drop_impl_did.is_local() { match dropck::check_drop_impl(ccx.tcx, drop_impl_did) { Ok(()) => {} Err(()) => { @@ -441,7 +443,7 @@ pub fn check_drop_impls(ccx: &CrateCtxt) { } } } - } + }); ccx.tcx.sess.abort_if_errors(); } diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs index 228f1f0fe445b..0c152a419d25f 100644 --- a/src/librustc_typeck/coherence/mod.rs +++ b/src/librustc_typeck/coherence/mod.rs @@ -126,7 +126,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Populate the table of destructors. It might seem a bit strange to // do this here, but it's actually the most convenient place, since // the coherence tables contain the trait -> type mappings. - self.populate_destructor_table(); + self.populate_destructors(); // Check to make sure implementations of `Copy` are legal. self.check_implementations_of_copy(); @@ -286,7 +286,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { // Destructors // - fn populate_destructor_table(&self) { + fn populate_destructors(&self) { let tcx = self.crate_context.tcx; let drop_trait = match tcx.lang_items.drop_trait() { Some(id) => id, None => { return } @@ -309,9 +309,6 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> { ty::TyEnum(type_def, _) | ty::TyStruct(type_def, _) => { type_def.set_destructor(method_def_id.def_id()); - tcx.destructors - .borrow_mut() - .insert(method_def_id.def_id()); } _ => { // Destructors only work on nominal types. From 9a8671316699d21841d26ab37ba0414d35825222 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Sat, 26 Sep 2015 23:12:11 +0300 Subject: [PATCH 20/20] don't crash when there are multiple conflicting implementations of Drop Fixes #28568 --- src/librustc/middle/ty/mod.rs | 1 - src/test/compile-fail/issue-28568.rs | 23 +++++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 src/test/compile-fail/issue-28568.rs diff --git a/src/librustc/middle/ty/mod.rs b/src/librustc/middle/ty/mod.rs index eb93c58f38c55..c3e7fd4ceca21 100644 --- a/src/librustc/middle/ty/mod.rs +++ b/src/librustc/middle/ty/mod.rs @@ -1695,7 +1695,6 @@ impl<'tcx, 'container> AdtDefData<'tcx, 'container> { } pub fn set_destructor(&self, dtor: DefId) { - assert!(self.destructor.get().is_none()); self.destructor.set(Some(dtor)); } diff --git a/src/test/compile-fail/issue-28568.rs b/src/test/compile-fail/issue-28568.rs new file mode 100644 index 0000000000000..36b4a57eb117f --- /dev/null +++ b/src/test/compile-fail/issue-28568.rs @@ -0,0 +1,23 @@ +// Copyright 2015 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct MyStruct; + +impl Drop for MyStruct { +//~^ ERROR conflicting implementations for trait + fn drop(&mut self) { } +} + +impl Drop for MyStruct { +//~^ NOTE conflicting implementation here + fn drop(&mut self) { } +} + +fn main() {}